[Util] Saving and Loading locations to and from Strings

Discussion in 'Resources' started by Shadowwolf97, Jan 17, 2014.

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

    Shadowwolf97

    Hey everybody, if you are anything like me at all, you hate having to hard code in location data for a plugins that need to save a location even after the server restarts. I have written a few basic methods that will solve these problems, and convert Locations to Strings, and convert those Strings back into location objects.

    Serialize Location (Convert to String)
    Code:java
    1. public static String serializeLocation(Location l) {
    2. String s = "";
    3. s += "@w;" + l.getWorld().getName();
    4. s += ":@x;" + l.getBlockX();
    5. s += ":@y;" + l.getBlockY();
    6. s += ":@z;" + l.getBlockZ();
    7. s += ":@p;" + l.getPitch();
    8. s += ":@ya;" + l.getYaw();
    9. return s;
    10. }


    Deserialize Location (Convert back to Location object)
    Code:java
    1. public static Location deserializeLocation(String s) {
    2. Location l = new Location(Bukkit.getWorlds().get(0), 0, 0, 0);
    3. String[] att = s.split(":");
    4. for(String attribute : att) {
    5. String[] split = attribute.split(";");
    6. if(split[0].equalsIgnoreCase("@w"))
    7. l.setWorld(Bukkit.getWorld(split[1]));
    8. if(split[0].equalsIgnoreCase("@x"))
    9. l.setX(Double.parseDouble(split[1]));
    10. if(split[0].equalsIgnoreCase("@y"))
    11. l.setY(Double.parseDouble(split[1]));
    12. if(split[0].equalsIgnoreCase("@z"))
    13. l.setZ(Double.parseDouble(split[1]));
    14. if(split[0].equalsIgnoreCase("@p"))
    15. l.setPitch(Float.parseFloat(split[1]));
    16. if(split[0].equalsIgnoreCase("@ya"))
    17. l.setYaw(Float.parseFloat(split[1]));
    18.  
    19. }
    20. return l;
    21. }


    There are many things you can do with just these few lines of code, such as saving a spawn location, or saving the location of a block, the possibilities are endless.

    Let me know if there are any other code snippets you would like, and I'll see what I can do!
    ~Shadowwolf97
     
    Scullyking likes this.
  2. Offline

    Scullyking

    Thanks, a useful snippet!
     
  3. Offline

    xTrollxDudex

    Shadowwolf97
    You could have gone by using array indexes instead of attributes, that would shorten the code a bit.
     
  4. Offline

    Not2EXceL

    So many if loops and the attributes part is inefficient. No need to split twice.
     
  5. Offline

    Shadowwolf97

    Yeah I know, Ill revise the code, I had originally wanted to have it convert multiple locations to a String, but I decided against that, and just forgot to update the method.

    I suppose I could have, I just like being able to read the string and understand what is going on.
     
  6. Offline

    Cirno

    Code:java
    1. public String locToString(Location loc){
    2. StringBuilder sb = new StringBuilder();
    3. sb.append(loc.getWorld().getName());
    4. sb.append(';');
    5. sb.append(loc.getX());
    6. sb.append(';');
    7. sb.append(loc.getY());
    8. sb.append(';');
    9. sb.append(loc.getZ());
    10. sb.append(';');
    11. sb.append(loc.getPitch());
    12. sb.append(';');
    13. sb.append(loc.getYaw());
    14. return sb.toString();
    15. }


    Code:java
    1. public Location strToLoc(String str){
    2. String[] data = str.split(';');
    3. return new Location(Bukkit.getWorld(data[0]), data[1], data[2], data[3], data[4], data[5]);
    4. }


    Untested, but should be correct :)
     
  7. Offline

    xTrollxDudex

    Cirno
    You forgot to return sb.toString() at the end :p
     
  8. Offline

    Cirno

    Shhhh... Only dreams now.
     
  9. Offline

    Wizehh

    Thank you!
     
  10. Offline

    Shadowwolf97

    Thanks for that! :D
    Just wanted to add a bit to the strToLoc method, as the Doubles and Floats were never parsed.
    Code:java
    1. public Location strToLoc(String str){
    2. String[] data = str.split(";");
    3. return new Location(Bukkit.getWorld(data[0]), Double.parseDouble(data[1]), Double.parseDouble(data[2]), Double.parseDouble(data[3]), Float.parseFloat(data[4]), Float.parseFloat(data[5]));
    4. }
     
  11. Offline

    RawCode

    String based serialization is joke, what about byte[]?

    Code:
    	public static final byte[] intToByteArray(int value) {
    	    return new byte[] {
    	            (byte)(value >>> 24),
    	            (byte)(value >>> 16),
    	            (byte)(value >>> 8),
    	            (byte)value};
    	}
    	
    	
    	public static byte[] Coordinate2ByteNONEG(int XZ)
    	{
    		if (XZ < 0)XZ *= -1;
    		return new byte[]{(byte) (XZ >>> 8),(byte) XZ};
    	}
    	
    	public static int Byte2CoordinateNONEG(byte[] bytes)
    	{
    		return ((bytes[0] & 0xFF) << 8) + (bytes[1] & 0xFF);
    	}
    	
    	public static byte ApplyNegs(byte B,boolean X, boolean Z)
    	{
    		if (X)
    			B += 64;
    		if (Z)
    			B *= -1;
    		return B;
    	}
    	public static byte GetNeg(byte B,boolean isX)
    	{
    		if (isX ? (B & 64)==0 : B < 0)
    			return -1;
    		return 1;
    	}
    	
    	public static byte GetValue(byte B)
    	{
    		if (B < 0) B *= -1;
    		return (byte) (B & 63);
    	}
    	
        static float factor = 360f/255f;
    	public static byte Compress360(float F)
    	{
    		return (byte) (F/factor);
    	}
    	public static float Extract360(byte B)
    	{
    		return (B & 0xFF)*factor;
    	}
    	
    	
    	public static byte[] serializeLocation(Location l) {
    
    		byte[] data = new byte[8];
    
    		data[0] = ApplyNegs((byte) Bukkit.getWorlds().indexOf(l.getWorld()),l.getBlockX() <0 , l.getBlockY() < 0);
    		byte[] x = Coordinate2ByteNONEG(l.getBlockX());
    		data[1] = x[0];
    		data[2] = x[1];
    		data[3] = (byte) l.getBlockY();
    		byte[] y = Coordinate2ByteNONEG(l.getBlockY());
    		data[4] = y[0];
    		data[5] = y[1];
    		data[6] = Compress360(l.getPitch());
    		data[7] = Compress360(l.getYaw());
    
    		return data;
    	}
    
     
  12. Offline

    Shadowwolf97

    What are the advantages of using byte arrays instead of Strings?
     
  13. Offline

    RawCode

    how many bytes your string based serialization consume per location?
     
  14. Offline

    Cirno

    I highly doubt a sheer couple of bytes makes much of a difference. Performance wise, your method is probably better by a handful of nanoseconds, a couple of milliseconds at most. Remember; premature optimization is the source of all evil.
     
  15. Offline

    RawCode

    looks like you dont understand how JVM works, what about benchmarking before posting something like this? Cirno
     
Thread Status:
Not open for further replies.

Share This Page