Util Serializing Locations

Discussion in 'Resources' started by The Fancy Whale, Jun 16, 2015.

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

    The Fancy Whale

    Aimed towards beginning developers
    Original Code (open)

    2 classes I created which you can use to serialize locations for storage, and then deserialize.
    Class 1 (for serializing a location -> string):
    Code:
    import org.bukkit.Location;
    
    public class DeserializedLocation {
        private String serializedLoc;
        public DeserializedLocation(Location loc) {
            serializedLoc = loc.getX() + ";" + loc.getY() + ";" + loc.getZ() + ";" + loc.getWorld().getName();
        }
        public String getSerializedLocation() {
            return serializedLoc;
        }
    }
    Class 2 (for deserializing a string -> location):
    Code:
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.World;
    
    public class SerializedLocation {
    private Location deserializeLoc;
        public SerializedLocation(String s) {
            String [] parts = s.split(";");
            double x = Double.parseDouble(parts[0]);
            double y = Double.parseDouble(parts[1]);
            double z = Double.parseDouble(parts[2]);
            World w = Bukkit.getServer().getWorld(parts[3]);
            deserializeLoc = new Location(w, x, y, z);
        }
        public Location getDeserializedLocation() {
            return deserializeLoc;
        }
    }
    
    Example of serializing a location:
    Code:
    DeserializedLocation spawnLoc = new DeserializedLocation(player.getLocation());
    
    getConfig().set("PlayerSpawn", spawnLoc.getSerializedLocation());
    Example of deserializing a location:
    Code:
    SerializedLocation playerSpawn = SerializedLocation(getConfig().getString("PlayerSpawn"));
    
    player.teleport(playerSpawn.getDeserializedLocation());

    So here is the new code. Special thanks to @RingOfStorms and @ChipDev for the suggestions:
    All in one class using static methods
    Code:
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.World;
    
    public class LocationSerializer {
    
        public static String getSerializedLocation(Location loc) { //Converts location -> String
            return loc.getX() + ";" + loc.getY() + ";" + loc.getZ() + ";" + loc.getWorld().getUID();
            //feel free to use something to split them other than semicolons (Don't use periods or numbers)
        }
     
        public static Location getDeserializedLocation(String s) {//Converts String -> Location
                String [] parts = s.split(";"); //If you changed the semicolon you must change it here too
                double x = Double.parseDouble(parts[0]);
                double y = Double.parseDouble(parts[1]);
                double z = Double.parseDouble(parts[2]);
                UUID u = UUID.fromString(parts[3]);
                World w = Bukkit.getServer().getWorld(u);
                return new Location(w, x, y, z); //can return null if the world no longer exists
        }
    }
    
    Here is an example of how to use the class:
    Code:
    //Converting location to string
    getConfig().set("PlayerSpawn", LocationSrializer.getSerializedLocation(player.getLocation()));
         
    //Converting stored string to location
    String serializedString = getConfig().getString("PlayerSpawn");
    player.teleport(getDeserializedLocation(serializedString));
    Code W/ Yaw/Pitch (open)

    Code:
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.World;
    
    public class LocationSerializer {
    
        public static String getSerializedLocation(Location loc) { //Converts location -> String
            return loc.getX() + ";" + loc.getY() + ";" + loc.getZ() + ";" + loc.getYaw() + ";" + loc.getPitch()
                    + ";" + loc.getWorld().getUID();
            //feel free to use something to split them other than semicolons (Don't use periods or numbers)
        }
      
        public static Location getDeserializedLocation(String s) {//Converts String -> Location
                String [] parts = s.split(";"); //If you changed the semicolon you must change it here too
                double x = Double.parseDouble(parts[0]);
                double y = Double.parseDouble(parts[1]);
                double z = Double.parseDouble(parts[2]);
                float yaw = Float.parseFloat(parts[3]);
                float pitch = Float.parseFloat(parts[4]);
                UUID u = UUID.fromString(parts[5]);
                World w = Bukkit.getServer().getWorld(u);
                return new Location(w, x, y, z, yaw, pitch); //can return null if the world no longer exists
        }
    }

    Just a short tutorial which I thought might help some people with storing their locations to config files. Let me know if you find any errors, or have any suggestions to improve this.
     
    Last edited: Jun 19, 2015
    RingOfStorms and ChipDev like this.
  2. Offline

    ChipDev

    Good tutorial, Recommending adding some comments so devs know that you don't have to split by ;, and can use anything.
     
    The Fancy Whale likes this.
  3. Offline

    RingOfStorms

    I feel like this would be better as a utility class with all static methods. You will never use the objects for any oop purpose with the methods they currently contain. So really there is much need for creating an instance of an object just to serialize. You may want to consider just making one utility class with the static methods, since this is a case where that is totally acceptable and probably better.
     
    The Fancy Whale likes this.
  4. Offline

    The Fancy Whale

    I like that idea @RingOfStorms and I will add comments to help out the developers. Working on rewriting a bit as we speak.
    EDIT: Updated the post with new code, comments, and with optional yaw/pitch. Thanks again!
     
    Last edited: Jun 17, 2015
    ChipDev likes this.
  5. Offline

    Konato_K

  6. Offline

    RingOfStorms

    Oh yea! I didn't even see that either, this is a must for a location object, otherwise you will not retain the rotation of the camera.

    Also, I would recommend using world UUID's rather than world names. Two different worlds could have the same name and clash, but they will never have the same UUID
     
  7. Offline

    teej107

    Doesn't Bukkit already have a way of (de)serializing locations?
     
    Hawktasard likes this.
  8. What about pitch and yaw?
     
  9. Offline

    The Fancy Whale

    I guess I could use world UUID's. Although, it isn't too often people have two worlds with the same name as far as I know. Also, just so you all know I originally made this for a plugin of mine with saving locations of blocks, but I did add a spoiler a when I changed the code yesterday which includes yaw and pitch for those interested.
    Not that I know of...
     
  10. Offline

    RingOfStorms

    If you are serializing and saving locations on a database across a network or anything of the sorts then you could have standardized world names on each server node, resulting in it loading possibly the wrong locations.
     
  11. Offline

    The Fancy Whale

    I changed it to use unique id's.
     
  12. Offline

    xTrollxDudex

    Functional programming :D
     
  13. No. Locations have a World object. Worlds would be hard to serialize.
     
  14. Offline

    teej107

    I'm not talking about serializing the World object directly. World uuid/name and coordinates is all you need.
     
  15. I get it, and the answer is no.
    And the best reason that I can think of is that they don't want to differ from the standard serialization.
     
  16. Yes, but in my opinion and many others, a String is much nicer and easier to use than a Map for locations.
     
  17. Offline

    teej107

    Is that what Bukkit does and what it saves it as? I remember seeing it somewhere but not enough apparently :p. I do agree though that I like it as a single path than as a Map.
     
  18. Yeah, Location implements ConfigurationSerializable and so has a serialize() method which returns a Map<String, Object> for serialization and has a constructor which takes in a Map for deserialization. And yeah :p
     
Thread Status:
Not open for further replies.

Share This Page