Saving/Getting amount of locations from config

Discussion in 'Spigot Plugin Development' started by JacksonHogan, May 12, 2016.

  1. I'm having a HUGE brain-fart, and can't figure this out. I'm trying to make it so when players issue the command "/skywars addspawn <arenaName>", it will get the highest number from the config, add 1 to it. Then save it. So, this is what the config would look like.

    Code (Text):

    ##Example##
    Arenas:
      testArena:
        Spawnpoints:
          1:
            x: 2.548
            y: 2.546
            z: 2.545
            pitch: 2.544
            yaw: 2.574
          2:
            x: 3.548
            y: 1.546
            z: 5.545
            pitch: 12.544
            yaw: 7.574
      blahArena:
        Spawnpoints:
          1:
            x: 2.548
            y: 2.546
            z: 2.545
            pitch: 2.544
            yaw: 2.574
     
  2. Use FileConfiguration#getConfigurationSection to get the Arenas.arenaName.spawnpoints configuration sections, then use ConfigurationSection#getKeys with false as an argument to get the keys of 1 through n. From there use your own logic to determine the highest value
     
  3. Totally agree, just want to add that when looking for the highest value remember that if you remove a spawn point that isn't the last one there may be gaps like1,2,4,5,6 which if you don't make the loop for checking the highest value right may mess up a few things, so when removing one may you would want to re order the ones after it so there are no blanks when counting up
     
  4. I'm sooo confused, Can i get an example? (Or explain a little better? I don't understand).
     
  5. BadBones69

    Supporter

    Here is a way you could use to get the last spawn point.
    So what your doing with this code is looping through all the number that are in the Spawn Points of <Arena>. Then setting the string num as the number which is point. The last one in the loop will be the last thing to be set as num so that means num will be the last point in your Spawn Points Section. Then the int i will turn num into a Integer so you can then add 1 to it later.
    Code (Text):
    String num = "1";
    for(String point : getConfig().getConfigurationSection("Arenas.<Arena>.SpawnPoints").getKeys(false)){
        num=point;
    }
    int i = Integer.parseInt(num);
    i would be the last spawn point number. But the only problem is when your delete a spawn point number it will remove the spawn point from the config and then the spawn points could look like this. 1,2,4,6,9. If you understand what I mean. So make sure you have a way to fix that. I just recommend making the player number the spawn points.
     
  6. You can't just iterate through a set and remember the last item because a set doesn't have any order! It is by definition unordered! Not to mention that the last number is not necessarily the largest because again, it is not ordered.

    @JacksonHogan
    You could go with the options given above or just to give you some other choices you could use a list of locations instead of this mapping with keys that you are trying to use as an index anyways. Put your locations in a list and save the list instead. Or serialize your locations to a single string like "yourX:yourY:yourZ:yaw:pitch" type of thing and again store a nice List<String> which can be nicely retrieved with ConfigurationSection#getStringList()
     
  7. BadBones69

    Supporter

    Hmm your probley right with how i was doing it. I didn't test it. I believe what you said could be right.
     
  8. I just did this a few days ago! ;)

    Code (Text):
    int nextLocNum = getConfig().getConfigurationSection("Arenas.testArena.Spawnpoints").getKeys(false).size() + 1;
                getConfig().set("Arenas.testArena.Spawnpoints " + nextLocNum +".X", x);
                getConfig().set("Arenas.testArena.Spawnpoints " + nextLocNum + ".Y", y);
                getConfig().set("Arenas.testArena.Spawnpoints " + nextLocNum +".Z", z);
     
    There ya go. ;)

    *my last spoon for today*
     
  9. Way more efficient than any other methods mentioned here. ^
     
  10. BadBones69

    Supporter

    Theres a problem with your method. Say these are the spawn points 1,2,3,4,5. If they delete number 2 then there is only 4 spawn points. If they then set a new one it will look at and over write number 5 because number 5 already exits. And it would get stuck in a endless loop of setting it as number 5 because its not really adding a new spawn point just over writing one.
     
  11. Would like to point out that's exactly what I said and for a user friendly approach (bit harder) I would recommend moving every input after the missing one down to complete the line. I know it will be harder to make but user friendliness is key when you are making consumer products for anything
     
    • Agree Agree x 2
  12. I would like to thank all who replied to my thread. I figured it out (I think).
    This is what i believe i'm gonna be using.

    Code (Java):
    public class SpawnManager {
       
        public HashMap<String, Integer> spawncount = new HashMap<String, Integer>();
        public HashMap<Player, Integer> pspawn = new HashMap<Player, Integer>();
       
        public Location getSpawn(String arena, int count) {
            Arena a = ArenaManager.getArena(arena);
            Location ret = null;
            if (a != null) {
                String entry = ".Spawnpoints." + Integer.toString(count) + ".";
                if (!Skywars.config.getConfig().isSet(String.valueOf(arena) + entry)) {
                    entry = ".Spawnpoints.";
                }
                World world = Bukkit.getWorld("Arenas." + arena + entry + ".world");
                int x = Skywars.config.getConfig().getInt("Arenas." + String.valueOf(arena) + entry + ".x");
                int y = Skywars.config.getConfig().getInt("Arenas." + String.valueOf(arena) + entry + ".y");
                int z = Skywars.config.getConfig().getInt("Arenas." + String.valueOf(arena) + entry + ".z");
                int pitch = Skywars.config.getConfig().getInt("Arenas." + String.valueOf(arena) + entry + ".pitch");
                int yaw = Skywars.config.getConfig().getInt("Arenas." + String.valueOf(arena) + entry + ".yaw");
               
                ret = new Location(world, (double)x, (double)y, (double)z, (float)pitch, (float)yaw);
            }
            return ret;
        }

        public Location getSpawn(String arena) {
            return this.getSpawn(arena, 0);
        }

        public Location getSpawnForPlayer(Player p, String arena) {
            if (!this.spawncount.containsKey(arena)) {
                this.spawncount.put(arena, 0);
                this.pspawn.put(p, 0);
                this.spawncount.put(arena, this.spawncount.get(arena) + 1);
                return this.getSpawn(arena, 0);
            }
            if (this.spawncount.get(arena) < this.getCurrentSpawnIndex(arena)) {
                Location ret = this.getSpawn(arena, this.spawncount.get(arena));
                this.pspawn.put(p, this.spawncount.get(arena));
                this.spawncount.put(arena, this.spawncount.get(arena) + 1);
                return ret;
            }
            this.spawncount.put(arena, 0);
            this.pspawn.put(p, 0);
            return this.getSpawn(arena, 0);
        }

        public Location getSpawnForPlayerRAW(Player p, String arena) {
            return this.getSpawn(arena, this.pspawn.get(p));
        }

        public int getCurrentSpawnIndex(String arena) {
            if (!Skywars.config.getConfig().isSet("Arenas." + String.valueOf(arena) + ".Spawnpoints")) {
                return 0;
            }
            int count = 0;
            Set<String> f = Skywars.config.getConfig().getConfigurationSection("Arenas." + String.valueOf(arena) + ".Spawnpoints").getKeys(false);
            for (String key : f) {
                if (key.equalsIgnoreCase("world") || key.equalsIgnoreCase("loc")) continue;
                ++count;
            }
            return count;
        }
    }
     
  13. Just focusing on the first method here. And mind you everything looks fine here are some things that don't need to be there

    When adding a number to a string I belive you don't need to parse it as a string as it is already a character in its own right so when getting the slaw point for count the Integer.toString is not needed

    The variable arena is a string... So may I ask why you are parsing a string as a string? String.valueOf(arena) is 100% pointless so if there's any arguments to be made about these changes this isn't one of them.

    Instead of using getInt for the X y and z and then casting them to a double, just use the getDouble method that way you will be able to store floating point type numbers in the config instead of just into and it will reduce the amount of words used in the code too.

    Last but not least, this one is sort of minor but should always be taken seriously, your naming of variables is a bit off, for the sake of easy reading consider using lowerCamelCase for variables just like you have done for your methods to make it easier to read for you and other people. And I get using AllCamelCase for the YAML is fine, I just would like to stress the importance of keeping things consistent. And personally I use lowerCamelCase for my config variables because it's what I do for everything else and I'm used to it, makes it easier for me. So when introducing a different way of writing variable names consider these small things that can help in the long run.
     
  14. BadBones69

    Supporter

    I am not sure if you figured it out already but I have recently been doing this.

    Code (Text):
    int num = 1;
    for(;getConfig().contains("Arena.testArena.SpawnPoints."+num);num++);
    getConfig().set("Arena.testArena.SpawnPoints."+num+".X", x );
    getConfig().set("Arena.testArena.SpawnPoints."+num+".Y", y );
    getConfig().set("Arena.testArena.SpawnPoints."+num+".Z", z );
     
    • Like Like x 1
  15. I would highly suggest learning Java properly before answering questions in this forum, you clearly do not realise that your code is in correct and will not work.

    You need to use {}
    The code would be cleaner if you move the int into the for statement
    Your naming conventions are all over the place... In the config either use UpperCamelCase OR lowerCamelCase OR UPPER_CASE but don't mix them up as you will one day get confused
     
    • Creative Creative x 1
  16. BadBones69

    Supporter

    I was just copying what @JacksonHogan had in his file for when I set the cords. I have been using that for loop and it works perfectly fine for me. It checks if the "Number" for the spawn point exists. and if it does it adds one and checks again. And I didn't learn java properly. I am just trying to help him out with what I know. <3
     
  17. I am absolutely amazed that you say it works, because the code you supplied does the following:

    Has a loop that hasn't been defined properly. That loop contains nothing

    It then saves the first spawn and nothing else.

    If the code really does work I would love to see the working plugin jar to try it myself (noting that I will open the jar to check that the code copied is the same as in the jar). I mean forget it working I'm surprised anyone's IDE even let that code be compiled...
     
  18. MiniDigger

    Supporter

    eclipse doesn't care if you got an empty loop iirc ^^
     
  19. Oh, I recently moved to IntelliJ form eclipse, maybe have forgotten this xD