Solved Problem with getting random arena!

Discussion in 'Plugin Development' started by jusjus112, Mar 21, 2016.

Thread Status:
Not open for further replies.
  1. Offline

    jusjus112

    Hello guys,

    i have a problem with getting a random arena.
    I know how i get a random arena, but it must look at the spawn point.

    For example, i want to get a random arena that has all spawnpoint set. So, if the arena has not set an spawnpoint get another random arena. @ This point i'm stuck. This is what i have so far:
    Code:
        public String chooseRandomArena(Arena a) {
            String randomArenaName = null;
           
            randomArenaName = chooseRandom();
            a = getArena(randomArenaName);
           
            if (a.isStarted(randomArenaName)||!isArenaLocationSet(1, randomArenaName)||!isArenaLocationSet(2, randomArenaName)||!isArenaLocationSet(3, randomArenaName)) {
                randomArenaName = chooseRandomArena(a);
                a = getArena(randomArenaName);
            }
            return randomArenaName;
        }
    Ik now i'm calling the method in a method. "chooseRandomArena(a);"
    But i cant find another option. Because when i replace "chooseRandomArena(a);" With "chooseRandom();" It has a chance to get the same arena, and the method isn't calling.

    I hope you guys can help me out ;)
     
  2. Offline

    Gonmarte

    I dont have much experience in arenas so what im going to say is what i would probably do, so if its completly wrong dont hurt me :-:
    You should not get a random arena. Instead, you should loop through all your arenas and check if the arena is being used or no, if it is just keep looping till you find some arena free to use and break the loop.
     
  3. Offline

    I Al Istannen

    @Gonmarte
    Yes, that would be a good way.


    @jusjus112
    Your code should work in some cases (if I haven't missed anything)
    What you have done is called recursion. But in this case it is not quite good.
    You call the method for the first time. It will choose a random one and check it. Let's say the check was false. Now the code will call the method again (recursion) and perform the same task. Choose a random arena and check it. Let's say that is true. Now it won't call the method again, but return the name. This name is now passed up to the first method. This method now exits the if and returns the correct name.

    I will try to visualize it, although that is quite hard with just spaced :/ You can read a lot about recursion in the internet though.

    EDIT: nevermind, doesn't work in code tags.
    bold ==> first method call
    italic ==> second method call from within the first method


    Code:
    first method call
        randomArenaName = chooseRandom();
        a = getArena(randomArenaName)
        check ==> false
          second method call
            randomArenaName = chooseRandom()
            a = getArena(randomArenaName)
            check ==> true
            return randomArenaName
          a = getArena(randomArenaName);
        end of the if
        return randomArenaName
    
    Now what happens when there is no valid arena? It will just call and call and call the chooseRandomArena() method again. Hundred, thousand times, until your computer says goodbye. This is probably not the desired outcome.

    I would suggest following what @Gonmarte said, as that is probably the easiest method. Depends on the situation though. If you want to get a random one from the free ones, create a new List, and fill it with every valid arena. If the list is empty, there is none. Else pick a random one out of the newly created list.

    Apart from that, why do you need the "Arena a" parameter, if you want to get a random one? Typical would be, that you don't have an arena and want one. No need to supply one before. But, as always, hard to tell from just one method.

    I do hope that my example above was correct, but I don't see why not. If it shouldn't be however, please correct me.
     
    Gonmarte likes this.
  4. Offline

    jusjus112

    @Gonmarte and @I Al Istannen

    Big thanks for your help. Now it works fine. Im proud ;) I changed it the same way but a bit different :D
    But now i have a last question. Everything works, but how can i check if all of the arena's has'nt set any spawns!
    Or that every arena is ingame. All returns null.
    This is my working code:
    Code:
        public String chooseRandomArena() {       
            ArrayList<String> list = (ArrayList<String>) Main.newConfigz.getList("totalArenas");
                Random r = new Random();
                int s = r.nextInt(list.size());
                System.out.print(list.get(s));
                if (!Arena.isStarted(list.get(s))&&isArenaLocationSet(1, list.get(s))&&isArenaLocationSet(1, list.get(s))&&isArenaLocationSet(2, list.get(s))&&isArenaLocationSet(3, list.get(s))) {
                    String a = list.get(s);
                    System.out.print(a);
                    return a;
                }else {
                    chooseRandomArena();
                }
                return null;
        }
    I cant get the "list.toString();" because then you get the info with the brackets and stuff..
    I can make a loop, but im stuck at this point ;(
    I hope you can help ;)
     
  5. @jusjus112 if you have solved the problem mark the thread as solved ;)
     
  6. Offline

    jusjus112

  7. Offline

    Gonmarte

    Havent you read that he still needs help?

    @jusjus112 I would save the arena in a yml file (config is ok) and inside the arena i would save his all things related to an arena like the spawns location. So i would check if there is any coords of spawn inside ur arena in the config file :)
    Everytime a player creates a arena you would add it to the yml file.

    I must repeat that i never worked with arenas and this is just what i would do!
     
  8. Offline

    jusjus112

    @Gonmarte
    Ya, ik now that my friend. I have saved everything in a .yml file. Spawns and stuff... But, i want to make a if statement for all the arenas. So if 0 of all arena's have no spawns set. Return null. The loop trough all of the arena's im stuck.

    So, a axample is good. Or just tell me ;)
     
  9. Offline

    Gonmarte

    I cant tell you this if you dont show me your arena code and how are you creating a arena. For what im seeing, you should take a look at this https://bukkit.org/threads/make-a-minigame-plugin.168164/ once it shows how to create an arena!
    Good luck, if you dont understand anything tag me back.
     
  10. Offline

    jusjus112

    @Gonmarte

    Ehm.. my friend. I know everything about arena's and stuff, and i don't use tutorials. I just found out by myself. Thanks for giving me this, but i cant do shitt without it.

    I think i must say it again. I'm not stuck on things like arenas but with getting an stringList from an yml file and make a loop for checking all that's inside the list and check if something contains for that name from the list ;)

    So, nothing with arena's or minigames. ;)
     
  11. Offline

    mcdorli

    ArrayList#contains(Object obj)
     
    Gonmarte likes this.
  12. Offline

    I Al Istannen

    @jusjus112

    You still have one of the logical errors though. It will work, but there is a twist.
    Let's say, there are no arenas in the list. The size of the list will therefore be 0. The Ranom#nextInt has a condition ofr the int passed. It must be positive. If you use 0 however it will show you this:
    Code:
    java.lang.IllegalArgumentException: bound must be positive
            at java.util.Random.nextInt(Unknown Source) ~[?:1.8.0_45]
    So this is something to keep in mind. Either check it in the method (preferred) or make sure to check it before every method call.

    The next thing lies within the approach of choosing a random number, checking that and if the condition is false, checking another. This works as long as at least ONE arena is valid, though the runtime gets worse and worse as the amount of free arenas goes down. If you have 100 arenas and only one is valid, you have only a 1/100 chance to choose the correct one. So the algorithm will run 99 times on average, until it finally returns the free one. While this is maybe negligble, the following isn't.
    Let's assume, none out of the 100 arenas is valid. The method will choose a random one, sees that the arena isn't valid and ... calls itself again, repeating the circle. Soon you will have hundreds of nested calls, piling up and you will get a StackOverflow error or your computer just blows up. While the last part is certainly exaggerated, you need to change your finding algorithm. Personally, I would loop through the list with all arenas and if the arena is valid, add it to another list. Then I would check the size. If the new list is empty, there is no free arena and you throw some exception or return null. If it isn't empty, you can use the first part of your method and select a random entry.
     
  13. Offline

    jusjus112

    @I Al Istannen
    Thanks for your comment. I have already created a choose random arean method for myself. So, i have fixed errors and made it how i want it. So your right, and thaks for advance ;)
    Code:
        @SuppressWarnings({ "unchecked"})
        public static String chooseRandom() {
            ArrayList<String> list = (ArrayList<String>) Main.newConfigz.getList("totalArenas");
            Random random = new Random();
            if (list == null || list.size() <= 0) {
                return null;
            }
            int selector = random.nextInt(list.size());
            String chosenReward = list.get(selector);
            return chosenReward;
        }
     
  14. Offline

    Gonmarte

    Mark this as solved plz! :)
     
  15. Ah, my phone at the time didn't load every message @jusjus112 so the last message was "thanks for the help I got it working"
     
  16. Offline

    jusjus112

    @Leviticalpixel10 , @Gonmarte
    Look, i have sort off figure it out. But i have a problem with my loop. It doesn't loop. when i do this:
    Code:
    for (String a: Main.newConfigz.getConfigurationSection("arenas").getKeys(false)) {
                System.out.print(a);
                if (isArenaLocationSet(1, a)&&isArenaLocationSet(2, a)&&isArenaLocationSet(3, a)) {
                    return true;
    //blablablabla
    The "for" line will send just 1 arena. Not 2 arena's. So, wtf, it should work right...
     
  17. Offline

    Gonmarte

    Can you show me your stringlist of arenas in your config file?
     
  18. Offline

    jusjus112

    @Gonmarte
    This is my config, and arenas. is btw not a stringList ;)
    HTML:
    arenas:
      JusJus:
        maxPlayers: 2
        isStarted: false
      test:
        maxPlayers: 2
        isStarted: false
        first:
          World: world
          X: -259.5676946413985
          Y: 70.0
          Z: 340.59141019156465
          Pitch: 1.5938188
          Yaw: 180.95029
        second:
          World: world
          X: -259.5162794543612
          Y: 70.0
          Z: 313.3172465800877
          Pitch: 3.0938148
          Yaw: 1.1003113
        end:
          World: world
          X: -295.1191272691274
          Y: 69.0
          Z: 323.98014998035444
          Pitch: 2.9438016
          Yaw: -84.84981
    totalArenas:
    - JusJus
    - test
    
     
  19. Offline

    Gonmarte

    @jusjus112 What are you trying to make here?
    Code:
    [LIST=1]
    [*] if (isArenaLocationSet(1, a)&&isArenaLocationSet(2, a)&&isArenaLocationSet(3, a)) {
    [*]               return true;
    [/LIST]
    
    And if you just want to get the arenas, you should loop through the totalArenas and create a stringlist inside it as you were doing.
     
  20. Offline

    jusjus112

    @Gonmarte
    I'm creating, if all the arena's dont't have a location return true ;)
    And. yes. im gone try that ;)

    @Gonmarte
    Oke this is frustrating. It dont work how i want xD. I have now this:

    Code:
        public boolean isAllLocationsNull() {
            for (String a: Main.newConfigz.getStringList("totalArenas")) {
                if (Main.newConfigz.contains("arenas." + a + ".first")&&Main.newConfigz.contains("arenas." + a + ".second")&&Main.newConfigz.contains("arenas." + a + ".first")) {
                    return false;
                }else {
                    return true;
                }
            }
            return true;
        }
    But if the arena doenst have a spawnpoint it returns false, but there is another arena that can played on it. So, how can i do this. If at least 1 arena is playable return false, if all of the arena's doesnt have a spawnpoint it return true!
    I have tried everything. Google Yahoo and bing so useless. And cant find it on. OMG, i hope you can help ;)

    This is my final code: It will always return null, because the chosen arena doenst have set a spawnpoint. So, the other arena HOW do i get them. And check if at least 1 arena is usable. IF not, return null
    Code:
        public String chooseRandomArena() {   
            //System.out.print(checkAllArenasIfitHasASpawn());
            ArrayList<String> list = (ArrayList<String>) Main.newConfigz.getList("totalArenas");
                Random r = new Random();
                int s = r.nextInt(list.size());
                //System.out.print(list.get(s));
                if (!Arena.isStarted(list.get(s))&&isArenaLocationSet(1,list.get(s))&&isArenaLocationSet(1, list.get(s))&&isArenaLocationSet(2, list.get(s))&&isArenaLocationSet(3, list.get(s))) {
                    String a = list.get(s);
                    //System.out.print(list.get(s));
                    return a;
                }else {
                    if (!isAllLocationsNull()) {
                        chooseRandomArena();
                    }else {
                        return null;
                    }
                }           
            return null;
        }
     
    Last edited: Mar 23, 2016
    Gonmarte likes this.
Thread Status:
Not open for further replies.

Share This Page