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.

This commit is contained in:
Brettflan 2012-03-14 13:06:38 -05:00
parent 7b9674dc4b
commit d8a39140fc
5 changed files with 128 additions and 32 deletions

View File

@ -65,16 +65,18 @@ public class Faction extends Entity implements EconomyParticipator
public void setDescription(String value) { this.description = value; } public void setDescription(String value) { this.description = value; }
// FIELD: home // FIELD: home
private Location home; private LazyLocation home;
public void setHome(Location home) { this.home = home; } public void setHome(Location home) { this.home = new LazyLocation(home); }
public Location getHome() { confirmValidHome(); return home; }
public boolean hasHome() { return this.getHome() != null; } public boolean hasHome() { return this.getHome() != null; }
public Location getHome()
{
confirmValidHome();
return (this.home != null) ? this.home.getLocation() : null;
}
public void confirmValidHome() 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; return;
}
msg("<b>Your faction home has been un-set since it is no longer in your territory."); msg("<b>Your faction home has been un-set since it is no longer in your territory.");
this.home = null; this.home = null;

View File

@ -37,6 +37,7 @@ import com.massivecraft.factions.struct.FFlag;
import com.massivecraft.factions.struct.FPerm; import com.massivecraft.factions.struct.FPerm;
import com.massivecraft.factions.struct.Rel; import com.massivecraft.factions.struct.Rel;
import com.massivecraft.factions.util.AutoLeaveTask; import com.massivecraft.factions.util.AutoLeaveTask;
import com.massivecraft.factions.util.LazyLocation;
import com.massivecraft.factions.zcore.MPlugin; import com.massivecraft.factions.zcore.MPlugin;
import com.massivecraft.factions.zcore.util.TextUtil; import com.massivecraft.factions.zcore.util.TextUtil;
@ -131,7 +132,7 @@ public class P extends MPlugin
.setPrettyPrinting() .setPrettyPrinting()
.disableHtmlEscaping() .disableHtmlEscaping()
.excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE) .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE)
.registerTypeAdapter(Location.class, new LocationTypeAdapter()) .registerTypeAdapter(LazyLocation.class, new LocationTypeAdapter())
.registerTypeAdapter(mapFLocToStringSetType, new FLocToStringSetTypeAdapter()) .registerTypeAdapter(mapFLocToStringSetType, new FLocToStringSetTypeAdapter())
.registerTypeAdapter(Rel.class, new RelTypeAdapter()) .registerTypeAdapter(Rel.class, new RelTypeAdapter())
.registerTypeAdapter(FPerm.class, new FPermTypeAdapter()) .registerTypeAdapter(FPerm.class, new FPermTypeAdapter())

View File

@ -3,8 +3,8 @@ package com.massivecraft.factions.adapters;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.logging.Level; import java.util.logging.Level;
import org.bukkit.Location; import com.massivecraft.factions.P;
import org.bukkit.World; import com.massivecraft.factions.util.LazyLocation;
import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer; import com.google.gson.JsonDeserializer;
@ -13,10 +13,9 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer; import com.google.gson.JsonSerializer;
import com.massivecraft.factions.P;
public class LocationTypeAdapter implements JsonDeserializer<Location>, JsonSerializer<Location> public class LocationTypeAdapter implements JsonDeserializer<LazyLocation>, JsonSerializer<LazyLocation>
{ {
private static final String WORLD = "world"; private static final String WORLD = "world";
private static final String X = "x"; private static final String X = "x";
@ -26,49 +25,37 @@ public class LocationTypeAdapter implements JsonDeserializer<Location>, JsonSeri
private static final String PITCH = "pitch"; private static final String PITCH = "pitch";
@Override @Override
public Location deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException public LazyLocation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
{ {
try try
{ {
JsonObject obj = json.getAsJsonObject(); JsonObject obj = json.getAsJsonObject();
String worldname = obj.get(WORLD).getAsString(); 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;
}
double x = obj.get(X).getAsDouble(); double x = obj.get(X).getAsDouble();
double y = obj.get(Y).getAsDouble(); double y = obj.get(Y).getAsDouble();
double z = obj.get(Z).getAsDouble(); double z = obj.get(Z).getAsDouble();
float yaw = obj.get(YAW).getAsFloat(); float yaw = obj.get(YAW).getAsFloat();
float pitch = obj.get(PITCH).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) catch (Exception ex)
{ {
ex.printStackTrace(); 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; return null;
} }
} }
@Override @Override
public JsonElement serialize(Location src, Type typeOfSrc, JsonSerializationContext context) { public JsonElement serialize(LazyLocation src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject obj = new JsonObject(); JsonObject obj = new JsonObject();
try try
{ {
if (src.getWorld() == null) obj.addProperty(WORLD, src.getWorldName());
{
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(X, src.getX()); obj.addProperty(X, src.getX());
obj.addProperty(Y, src.getY()); obj.addProperty(Y, src.getY());
obj.addProperty(Z, src.getZ()); obj.addProperty(Z, src.getZ());
@ -76,12 +63,11 @@ public class LocationTypeAdapter implements JsonDeserializer<Location>, JsonSeri
obj.addProperty(PITCH, src.getPitch()); obj.addProperty(PITCH, src.getPitch());
return obj; return obj;
} }
catch (Exception ex) catch (Exception ex)
{ {
ex.printStackTrace(); 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; return obj;
} }
} }

View File

@ -58,7 +58,7 @@ public class CmdHome extends FCommand
if ( ! myFaction.hasHome()) if ( ! myFaction.hasHome())
{ {
fme.msg("<b>You faction does not have a home. " + (fme.getRole().isLessThan(Rel.OFFICER) ? "<i> Ask your leader to:" : "<i>You should:")); fme.msg("<b>Your faction does not have a home. " + (fme.getRole().isLessThan(Rel.OFFICER) ? "<i> Ask your leader to:" : "<i>You should:"));
fme.sendMessage(p.cmdBase.cmdSethome.getUseageTemplate()); fme.sendMessage(p.cmdBase.cmdSethome.getUseageTemplate());
return; return;
} }

View File

@ -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;
}
}