From d8a39140fcc9ad1423836051dd1854344eeb0eb8 Mon Sep 17 00:00:00 2001 From: Brettflan Date: Wed, 14 Mar 2012 13:06:38 -0500 Subject: [PATCH] Faction homes should no longer be lost if their target world isn't already loaded when Factions loads at server startup. This is done using a new lazy-load Location container class which only initializes the Location when it's actually needed. --- src/com/massivecraft/factions/Faction.java | 14 ++- src/com/massivecraft/factions/P.java | 3 +- .../adapters/LocationTypeAdapter.java | 34 ++---- .../massivecraft/factions/cmd/CmdHome.java | 2 +- .../factions/util/LazyLocation.java | 107 ++++++++++++++++++ 5 files changed, 128 insertions(+), 32 deletions(-) create mode 100644 src/com/massivecraft/factions/util/LazyLocation.java diff --git a/src/com/massivecraft/factions/Faction.java b/src/com/massivecraft/factions/Faction.java index 542c3ad9..d3243678 100644 --- a/src/com/massivecraft/factions/Faction.java +++ b/src/com/massivecraft/factions/Faction.java @@ -65,16 +65,18 @@ public class Faction extends Entity implements EconomyParticipator public void setDescription(String value) { this.description = value; } // FIELD: home - private Location home; - public void setHome(Location home) { this.home = home; } - public Location getHome() { confirmValidHome(); return home; } + private LazyLocation home; + public void setHome(Location home) { this.home = new LazyLocation(home); } public boolean hasHome() { return this.getHome() != null; } + public Location getHome() + { + confirmValidHome(); + return (this.home != null) ? this.home.getLocation() : null; + } public void confirmValidHome() { - if (!Conf.homesMustBeInClaimedTerritory || this.home == null || Board.getFactionAt(new FLocation(this.home)) == this) - { + if (!Conf.homesMustBeInClaimedTerritory || this.home == null || Board.getFactionAt(new FLocation(this.home.getLocation())) == this) return; - } msg("Your faction home has been un-set since it is no longer in your territory."); this.home = null; diff --git a/src/com/massivecraft/factions/P.java b/src/com/massivecraft/factions/P.java index 7ca3c48d..8c473561 100644 --- a/src/com/massivecraft/factions/P.java +++ b/src/com/massivecraft/factions/P.java @@ -37,6 +37,7 @@ import com.massivecraft.factions.struct.FFlag; import com.massivecraft.factions.struct.FPerm; import com.massivecraft.factions.struct.Rel; import com.massivecraft.factions.util.AutoLeaveTask; +import com.massivecraft.factions.util.LazyLocation; import com.massivecraft.factions.zcore.MPlugin; import com.massivecraft.factions.zcore.util.TextUtil; @@ -131,7 +132,7 @@ public class P extends MPlugin .setPrettyPrinting() .disableHtmlEscaping() .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE) - .registerTypeAdapter(Location.class, new LocationTypeAdapter()) + .registerTypeAdapter(LazyLocation.class, new LocationTypeAdapter()) .registerTypeAdapter(mapFLocToStringSetType, new FLocToStringSetTypeAdapter()) .registerTypeAdapter(Rel.class, new RelTypeAdapter()) .registerTypeAdapter(FPerm.class, new FPermTypeAdapter()) diff --git a/src/com/massivecraft/factions/adapters/LocationTypeAdapter.java b/src/com/massivecraft/factions/adapters/LocationTypeAdapter.java index c94506ea..b9c8cbe9 100644 --- a/src/com/massivecraft/factions/adapters/LocationTypeAdapter.java +++ b/src/com/massivecraft/factions/adapters/LocationTypeAdapter.java @@ -3,8 +3,8 @@ package com.massivecraft.factions.adapters; import java.lang.reflect.Type; import java.util.logging.Level; -import org.bukkit.Location; -import org.bukkit.World; +import com.massivecraft.factions.P; +import com.massivecraft.factions.util.LazyLocation; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; @@ -13,10 +13,9 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import com.massivecraft.factions.P; -public class LocationTypeAdapter implements JsonDeserializer, JsonSerializer +public class LocationTypeAdapter implements JsonDeserializer, JsonSerializer { private static final String WORLD = "world"; private static final String X = "x"; @@ -26,49 +25,37 @@ public class LocationTypeAdapter implements JsonDeserializer, JsonSeri private static final String PITCH = "pitch"; @Override - public Location deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException + public LazyLocation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { try { JsonObject obj = json.getAsJsonObject(); - String worldname = obj.get(WORLD).getAsString(); - World world = P.p.getServer().getWorld(worldname); - if (world == null) { - P.p.log(Level.WARNING, "Stored location's world \"" + worldname + "\" not found on server; dropping the location."); - return null; - } - + String worldName = obj.get(WORLD).getAsString(); double x = obj.get(X).getAsDouble(); double y = obj.get(Y).getAsDouble(); double z = obj.get(Z).getAsDouble(); float yaw = obj.get(YAW).getAsFloat(); float pitch = obj.get(PITCH).getAsFloat(); - return new Location(world, x, y, z, yaw, pitch); + return new LazyLocation(worldName, x, y, z, yaw, pitch); } catch (Exception ex) { ex.printStackTrace(); - P.p.log(Level.WARNING, "Error encountered while deserializing a location."); + P.p.log(Level.WARNING, "Error encountered while deserializing a LazyLocation."); return null; } } @Override - public JsonElement serialize(Location src, Type typeOfSrc, JsonSerializationContext context) { + public JsonElement serialize(LazyLocation src, Type typeOfSrc, JsonSerializationContext context) { JsonObject obj = new JsonObject(); try { - if (src.getWorld() == null) - { - P.p.log(Level.WARNING, "Passed location's world was not found on the server. Dropping the location."); - return obj; - } - - obj.addProperty(WORLD, src.getWorld().getName()); + obj.addProperty(WORLD, src.getWorldName()); obj.addProperty(X, src.getX()); obj.addProperty(Y, src.getY()); obj.addProperty(Z, src.getZ()); @@ -76,12 +63,11 @@ public class LocationTypeAdapter implements JsonDeserializer, JsonSeri obj.addProperty(PITCH, src.getPitch()); return obj; - } catch (Exception ex) { ex.printStackTrace(); - P.p.log(Level.WARNING, "Error encountered while serializing a location."); + P.p.log(Level.WARNING, "Error encountered while serializing a LazyLocation."); return obj; } } diff --git a/src/com/massivecraft/factions/cmd/CmdHome.java b/src/com/massivecraft/factions/cmd/CmdHome.java index 442a2690..8df231e9 100644 --- a/src/com/massivecraft/factions/cmd/CmdHome.java +++ b/src/com/massivecraft/factions/cmd/CmdHome.java @@ -58,7 +58,7 @@ public class CmdHome extends FCommand if ( ! myFaction.hasHome()) { - fme.msg("You faction does not have a home. " + (fme.getRole().isLessThan(Rel.OFFICER) ? " Ask your leader to:" : "You should:")); + fme.msg("Your faction does not have a home. " + (fme.getRole().isLessThan(Rel.OFFICER) ? " Ask your leader to:" : "You should:")); fme.sendMessage(p.cmdBase.cmdSethome.getUseageTemplate()); return; } diff --git a/src/com/massivecraft/factions/util/LazyLocation.java b/src/com/massivecraft/factions/util/LazyLocation.java new file mode 100644 index 00000000..83d748ac --- /dev/null +++ b/src/com/massivecraft/factions/util/LazyLocation.java @@ -0,0 +1,107 @@ +package com.massivecraft.factions.util; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +/* + * This class provides a lazy-load Location, so that World doesn't need to be initialized + * yet when an object of this class is created, only when the Location is first accessed. + */ + +public class LazyLocation +{ + private Location location = null; + private String worldName; + private double x; + private double y; + private double z; + private float pitch; + private float yaw; + + public LazyLocation(Location loc) + { + setLocation(loc); + } + + public LazyLocation(final String worldName, final double x, final double y, final double z) + { + this(worldName, x, y, z, 0, 0); + } + + public LazyLocation(final String worldName, final double x, final double y, final double z, final float yaw, final float pitch) + { + this.worldName = worldName; + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + } + + // This returns the actual Location + public final Location getLocation() + { + // make sure Location is initialized before returning it + initLocation(); + return location; + } + + // change the Location + public final void setLocation(Location loc) + { + this.location = loc; + this.worldName = loc.getWorld().getName(); + this.x = loc.getX(); + this.y = loc.getY(); + this.z = loc.getZ(); + this.yaw = loc.getYaw(); + this.pitch = loc.getPitch(); + } + + + // This initializes the Location + private void initLocation() + { + // if location is already initialized, simply return + if (location != null) return; + + // get World; hopefully it's initialized at this point + World world = Bukkit.getWorld(worldName); + if (world == null) return; + + // store the Location for future calls, and pass it on + location = new Location(world, x, y, z, yaw, pitch); + } + + + public final String getWorldName() + { + return worldName; + } + + public final double getX() + { + return x; + } + + public final double getY() + { + return y; + } + + public final double getZ() + { + return z; + } + + public final double getPitch() + { + return pitch; + } + + public final double getYaw() + { + return yaw; + } +}