package net.obnoxint.mcdev.util; import java.io.Serializable; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; /** * A serializable and immutable wrapper for org.bukkit.Location objects. */ public class SerializableLocation implements Serializable { private static final long serialVersionUID = 8130077079595390518L; /** * Creates a new instance based on the given string. The general contract of this method is that if the output of the {@link #toString()} is passed it will result in a clone. * * @param string the String. * @return a new instance or null if string could not be parsed. */ public static SerializableLocation fromString(final String string) { if (string != null && !string.isEmpty()) { final String[] s = string.trim().split(" "); try { String worldName; double x, y, z; float pitch, yaw; if (s.length == 4) { worldName = s[0]; x = Double.parseDouble(s[1]); y = Double.parseDouble(s[2]); z = Double.parseDouble(s[3]); pitch = 0f; yaw = 0f; } else if (s.length == 6) { worldName = s[0]; x = Double.parseDouble(s[1]); y = Double.parseDouble(s[2]); z = Double.parseDouble(s[3]); pitch = Float.parseFloat(s[4]); yaw = Float.parseFloat(s[5]); } else { return null; } return new SerializableLocation(worldName, x, y, z, pitch, yaw); } catch (final NumberFormatException e) {} } return null; } private final float pitch, yaw; private final String worldName; private final double x, y, z; /** * Creates a new instance based on the given Location. * * @param location the Locatuion. */ public SerializableLocation(final Location location) { this(location.getWorld().getName(), location.getX(), location.getBlockY(), location.getZ(), location.getPitch(), location.getYaw()); } /** * Creates a new instance. Pitch and yaw will be assumed as 0. * * @param worldName the name of the world. * @param x the x-coordinate. * @param y the y-coordinate. * @param z the z-coordinate. */ public SerializableLocation(final String worldName, final double x, final double y, final double z) { this(worldName, x, y, z, 0f, 0f); } /** * Creates a new instance. * * @param worldName the name of the world. * @param x the x-coordinate. * @param y the y-coordinate. * @param z the z-coordinate. * @param pitch the pitch. * @param yaw the yaw. */ public SerializableLocation(final String worldName, final double x, final double y, final double z, final float pitch, final float yaw) { this.worldName = worldName; this.x = x; this.y = y; this.z = z; this.pitch = pitch; this.yaw = yaw; } /** * <p> * The following types can be used to compare the instance with the passed value: * </p> * <ul> * <li><b>SerializableLocation:</b> All values will be compared.</li> * <li><b>Location:</b> All values will be compared by internally creating a new instance of SerializableLocation based on the given Location.</li> * <li><b>World:</b> The name of the World will be compared.</li> * </ul> * * @return true if the passed value is equal to this instance. */ @Override public boolean equals(final Object obj) { if (obj != null) { if (obj instanceof SerializableLocation) { final SerializableLocation l = (SerializableLocation) obj; return l.worldName.equals(worldName) && l.x == x && l.y == y && l.z == z && l.pitch == pitch && l.yaw == yaw; } else if (obj instanceof Location) { final Location l = (Location) obj; return new SerializableLocation(l).equals(this); } else if (obj instanceof World) { return ((World) obj).getName().equals(worldName); } } return false; } /** * @return the pitch. */ public final float getPitch() { return pitch; } /** * @return the World object of this instance or null if there is no world loaded with this name. */ public World getWorld() { return Bukkit.getWorld(worldName); } /** * @return the name of the world. */ public final String getWorldName() { return worldName; } /** * @return the x-coordinate. */ public final double getX() { return x; } /** * @return the y-coordinate. */ public final double getY() { return y; } /** * @return the yaw. */ public final float getYaw() { return yaw; } /** * @return the z-coordinate. */ public final double getZ() { return z; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Float.floatToIntBits(pitch); result = prime * result + ((worldName == null) ? 0 : worldName.hashCode()); long temp; temp = Double.doubleToLongBits(x); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(y); result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + Float.floatToIntBits(yaw); temp = Double.doubleToLongBits(z); result = prime * result + (int) (temp ^ (temp >>> 32)); return result; } /** * Creates a new Location based on this instance. * * @return the Location. */ public Location toLocation() { return new Location(getWorld(), x, y, z, yaw, pitch); } /** * Creates a String representing this instance in the following format: [worldname][space][x][space][y][space][z][space][pitch][space][yaw] * * @return a String representing this instance. */ @Override public String toString() { return (new StringBuilder()).append(worldName).append(" ").append(String.valueOf(x)).append(" ").append(String.valueOf(y)).append(" ") .append(String.valueOf(z)).append(" ").append(String.valueOf(pitch)).append(" ").append(String.valueOf(yaw)).toString(); } }