Serializing a Chunk

Discussion in 'Spigot Plugin Development' started by koekeritis, May 11, 2015.

  1. for a guild plugin I'm making I have a claim system that works based on chunks. It works great and all... but the guilds aren't saved anymore becuase Chunk is nor serializable. I tried it with storing locations (get chunk from location in getTerritory() etc..) But locations aren't serializable either! Does anyone know how I could save the claimed chunks?

    thanks in advance,
    koekeritis
     
  2. You can write a simple util to serialize a location like this:
    Code (Text):
        public static String locToString(Location loc)
        {
            if(loc == null)
                return null;

            return (loc.getWorld().getName() + ";" + loc.getX() + ";" + loc.getY() + ";" + loc.getZ() + ";" + loc.getYaw() + ";" + loc.getPitch())
                .replace(".", "?"); //Replace dots because dots are new lines in config.
        }
    And to deserialize simply go the other way.
     
  3. That would not be a good way to do it..

    dots are not new lines in a config file. That would be a bug in what ever you are using to save the data.

    Here's my methods:

    Code (Text):

        public static final Pattern COLON = Pattern.compile(":");
        public static Location stringToLocation(String storedLoc, World forcedWorld) {
            if (storedLoc == null) {
                return null;
            }
            String[] args = COLON.split(storedLoc);
            if (args.length >= 4) {
                String world = forcedWorld != null ? forcedWorld.getName() : args[0];
                double x = Double.parseDouble(args[1]);
                double y = Double.parseDouble(args[2]);
                double z = Double.parseDouble(args[3]);
                Location loc = new Location(Bukkit.getWorld(world), x, y, z);
                if (args.length >= 6) {
                    loc.setPitch(Float.parseFloat(args[4]));
                    loc.setYaw(Float.parseFloat(args[5]));
                }
                return loc;
            }
            return null;
        }

        public static String locationToString(Location loc) {
            if (loc == null) {
                return null;
            }
            return loc.getWorld().getName() + ':' +
                loc.getX() + ':' +
                loc.getY() + ':' +
                loc.getZ() + ":" +
                loc.getPitch() + ":" +
                loc.getYaw();

        }
     
     
  4. How is this a bad way? Also dots definitely start a new line in Bukkit's Yaml API.

    I.e:
    Code (Text):
    Test: <dot>
      Test: <dot>
        Test: test
     
    #4 XlordalX, May 11, 2015
    Last edited: May 11, 2015
  5. You should be saving the data as a string, so it would be Test: "Test.Test.Test"

    And it's bad because any developer reading it would go "Huh"? The code is not intuitive. You immediately say "Why are you replacing . with ?"

    Util methods are not the place to solve shortcomings in another place.

    If you absolutely do need to convert decimals to ? for some reason, it should be done outside of the method.

    worldname:32.22:42.22:56.33

    is pretty intuitive on what it is.
     
  6. So what you're saying is calling a .replace is bad in a util method and should be done everytime you run this method?
     
  7. If you want to use the serialized location as a key, it will start new lines.
     
  8. Using it as a key yes I could see issues. Thats a different usage, and yes I would do the string replacement in a different method.

    like
    Code (Text):

    String safeKey = Util.escapeKey(Util.locationToString(loc));
    public static String escapeKey(String key) {
        return key.replaceAll(".", "\\.");
    }
    -- Given if \. works which I hope it does....

    Note simpler methods like this is better for the JVM and general coding style, as it can inline them where appropriate for performance improvements, and you can then use locationToString in OTHER places in your code that doesn't require special treatment of .
     
    • Agree Agree x 1
  9. @koekeritis all you need to do is store the chunk's x and z coordinate.
     
    • Agree Agree x 1
  10. And the world unless he only alows it in one world anyways
     
    • Agree Agree x 1
  11. Woops, late response I already fixed it but yeah, DarkSeraphim's solution is the best in my case.
     
  12. @koekeritis
    In my Settlements plugin (functions in a similar way to Factions), I store the following information for every claimed chunk:
    • UUID of player claiming the chunk
    • Settlement ID
    • Chunk X
    • Chunk Y
    • World ID
    • ChunkType (used for various purposes you won't need)
    For you I'd store the Guild (name/ID), Chunk X & Z, and World ID