Serializing Location Objects

Nov 17, 2016
Serializing Location Objects
  • Serializing Location Objects

    Learn how to serialize & deserialize Location objects for use with config files!




    What is serialization and why does it matter?(top)

    Serialization is taking one object and changing it into a format that can be appropriately stored and recalled later when needed. For Spigot, this means the ability to turn a complex object, like a Location, into a relatively simple object, like a String, that can be saved safely to our "config.yml" file.

    Next, one can deserialize the String object when necessary by converting it back into a Location through constructor methods contained within the object class. This allows for easy reading/writing of Locations without manually reading/writing/plugging-in all of the variables associated with a Location constructor -- which requires between four and six different variables.

    The Location object(top)

    Before starting to break down and re-build Location objects, it helps to first understand what makes up a Location first.

    A Location object pinpoints a specific coordinate (x, y, z) in a given world, at the very least. It can also specify two extra optional values, a "pitch" and a "yaw", used when orienting entity directions -- but they can be left out of the constructor to use defaults.

    To construct what I call a "lite" Location (meaning no pitch or yaw), you can do something like this:

    Code (Text):
    Location loc = new Location(world, x, y, z);
    ...where world is an object of class World (perhaps retrieved through Bukkit.getServer().getWorld("world");) and x, y, & z are int/double values corresponding to the in-game coordinate system.

    To construct a full-fledged Location object, simply add two double variables to the constructor defining the pitch and yaw. The difference between a full Location and a lite Location is mostly noticed when teleporting a player, since pitch and yaw determine the direction the player is facing on teleport to that Location.

    Location-String serialization(top)

    With the various parts of a Location, one can create suitable methods for serialization and deserialization. It is advisable to create a separate class which facilitates your serialization, perhaps named LocSerialization, to allow for easier use in other classes/projects.

    To serialize a 'lite' Location (i.e. no pitch/yaw) create a getLiteStringFromLocation() method which takes a single Location parameter "loc". Be sure to preliminarily check if the location is null; if so, return (or send an error/debugging message).

    If loc passes the null check, construct a String combining the variables of a lite Location in the appropriate order separated by a special delimiting character. This character should not be expected to occur in the String variable parts, so it is suggested to use a colon ":" or comma "," character.

    To construct and return the Location as a String, use a statement such as this:
    Code (Text):
    return loc.getWorld().getName() + ":" + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ();
    To get the full Location with pitch and yaw, create a getStringFromLocation() method which also takes a Location parameter "loc". Run a null check as before, and add a modified version of the above statement:
    Code (Text):
    return loc.getWorld().getName() + ":" + loc.getX() + ":" + loc.getY() + ":" + loc.getZ() + ":" + loc.getYaw() + ":" + loc.getPitch() ;
    The returned value can be saved to the config as a single String value, and later recalled by a deserialization method and converted back into a Location.

    String-Location deserialization(top)

    To deserialize a String into a Location object, create a getLiteLocationFromString() method which takes a single String parameter "s". Be sure to check if s is null and if:
    Code (Text):
    s.trim == ""
    Create a String array called parts and set it to s.split(":"). Check the length of parts, and if it equals 4 (or 6 for a full Location) set the variables according to each part. Return a new Location constructed from those variables. This is how a lite Location might be parsed and constructed:

    Code (Text):
    if (parts.length == 4) {
                World w = Bukkit.getServer().getWorld(parts[0]);
                double x = Double.parseDouble(parts[1]);
                double y = Double.parseDouble(parts[2]);
                double z = Double.parseDouble(parts[3]);
                return new Location(w, x, y, z);
            }
            return null;
    To deserialize a full Location, create a getLocationFromString() method which also takes a String parameter "s". Check if it's null, check the trim, and then check if the parts.length() equals 6. If so, add pitch and yaw variables to the method as well.

    Now just call the method by inputting a Location-String serialization from your config to get a saved & serialized Location!

    Example code(top)

    Code (Text):
    package com.kraken.example;

    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.World;

    public class LocSerialization {

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

      public static Location getLocationFromString(String s) {
      if (s == null || s.trim() == "") {
      return null;
      }
      final String[] parts = s.split(":");
      if (parts.length == 6) {
      World w = Bukkit.getServer().getWorld(parts[0]);
      double x = Double.parseDouble(parts[1]);
      double y = Double.parseDouble(parts[2]);
      double z = Double.parseDouble(parts[3]);
      float yaw = Float.parseFloat(parts[4]);
      float pitch = Float.parseFloat(parts[5]);
      return new Location(w, x, y, z, yaw, pitch);
      }
      return null;
      }

      public static String getLiteStringFromLocation(Location loc) {  
        if (loc == null) {
        return "";
        }
        return loc.getWorld().getName() + ":" + loc.getBlockX() + ":" + l.getBlockY() + ":" + loc.getBlockZ() ;  
       }

      public static Location getLiteLocationFromString(String s) {
      if (s == null || s.trim() == "") {
      return null;
      }
      final String[] parts = s.split(":");
      if (parts.length == 4) {
      World w = Bukkit.getServer().getWorld(parts[0]);
      double x = Double.parseDouble(parts[1]);
      double y = Double.parseDouble(parts[2]);
      double z = Double.parseDouble(parts[3]);
      return new Location(w, x, y, z);
      }
      return null;
      }

    }
  • Loading...
  • Loading...