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; }
// 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("<b>Your faction home has been un-set since it is no longer in your territory.");
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.struct.ChatMode;
import com.massivecraft.factions.util.AutoLeaveTask;
import com.massivecraft.factions.util.LazyLocation;
import com.massivecraft.factions.util.MapFLocToStringSetTypeAdapter;
import com.massivecraft.factions.util.MyLocationTypeAdapter;
import com.massivecraft.factions.zcore.MPlugin;
@ -126,7 +127,7 @@ public class P extends MPlugin
.setPrettyPrinting()
.disableHtmlEscaping()
.excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE)
.registerTypeAdapter(Location.class, new MyLocationTypeAdapter())
.registerTypeAdapter(LazyLocation.class, new MyLocationTypeAdapter())
.registerTypeAdapter(mapFLocToStringSetType, new MapFLocToStringSetTypeAdapter());
}

View File

@ -58,7 +58,7 @@ public class CmdHome extends FCommand
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());
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.util.logging.Level;
import org.bukkit.Location;
import org.bukkit.World;
import com.massivecraft.factions.P;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
@ -13,10 +12,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 MyLocationTypeAdapter implements JsonDeserializer<Location>, JsonSerializer<Location>
public class MyLocationTypeAdapter implements JsonDeserializer<LazyLocation>, JsonSerializer<LazyLocation>
{
private static final String WORLD = "world";
private static final String X = "x";
@ -26,49 +24,37 @@ public class MyLocationTypeAdapter implements JsonDeserializer<Location>, JsonSe
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 +62,11 @@ public class MyLocationTypeAdapter implements JsonDeserializer<Location>, JsonSe
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;
}
}