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:50 -05:00
parent 2dbaee836b
commit 68f1319a98
5 changed files with 127 additions and 32 deletions

View File

@ -98,16 +98,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

@ -30,6 +30,7 @@ import com.massivecraft.factions.listeners.FactionsPlayerListener;
import com.massivecraft.factions.listeners.FactionsServerListener; import com.massivecraft.factions.listeners.FactionsServerListener;
import com.massivecraft.factions.struct.ChatMode; import com.massivecraft.factions.struct.ChatMode;
import com.massivecraft.factions.util.AutoLeaveTask; import com.massivecraft.factions.util.AutoLeaveTask;
import com.massivecraft.factions.util.LazyLocation;
import com.massivecraft.factions.util.MapFLocToStringSetTypeAdapter; import com.massivecraft.factions.util.MapFLocToStringSetTypeAdapter;
import com.massivecraft.factions.util.MyLocationTypeAdapter; import com.massivecraft.factions.util.MyLocationTypeAdapter;
import com.massivecraft.factions.zcore.MPlugin; import com.massivecraft.factions.zcore.MPlugin;
@ -126,7 +127,7 @@ public class P extends MPlugin
.setPrettyPrinting() .setPrettyPrinting()
.disableHtmlEscaping() .disableHtmlEscaping()
.excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE) .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE)
.registerTypeAdapter(Location.class, new MyLocationTypeAdapter()) .registerTypeAdapter(LazyLocation.class, new MyLocationTypeAdapter())
.registerTypeAdapter(mapFLocToStringSetType, new MapFLocToStringSetTypeAdapter()); .registerTypeAdapter(mapFLocToStringSetType, new MapFLocToStringSetTypeAdapter());
} }

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().value < Role.MODERATOR.value ? "<i> Ask your leader to:" : "<i>You should:")); fme.msg("<b>Your faction does not have a home. " + (fme.getRole().value < Role.MODERATOR.value ? "<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;
}
}

View File

@ -3,8 +3,7 @@ package com.massivecraft.factions.util;
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.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer; import com.google.gson.JsonDeserializer;
@ -13,10 +12,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 MyLocationTypeAdapter implements JsonDeserializer<Location>, JsonSerializer<Location> public class MyLocationTypeAdapter 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 +24,37 @@ public class MyLocationTypeAdapter implements JsonDeserializer<Location>, JsonSe
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 +62,11 @@ public class MyLocationTypeAdapter implements JsonDeserializer<Location>, JsonSe
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;
} }
} }