Changes :P

This commit is contained in:
Olof Larsson 2012-09-23 14:46:05 +02:00
parent a47df27b30
commit c670731a4e
14 changed files with 277 additions and 70 deletions

View File

@ -21,7 +21,6 @@ import com.massivecraft.mcore4.persist.IClassManager;
import com.massivecraft.mcore4.persist.Persist;
import com.massivecraft.mcore4.store.Coll;
import com.massivecraft.mcore4.store.PlayerColl;
import com.massivecraft.mcore4.util.MUtil;
public class InternalListener implements Listener
{
@ -30,6 +29,7 @@ public class InternalListener implements Listener
public InternalListener(MCore p)
{
this.p = p;
MCorePlayerLeaveEvent.player2event.clear();
Bukkit.getServer().getPluginManager().registerEvents(this, this.p);
}
@ -94,16 +94,53 @@ public class InternalListener implements Listener
}
// -------------------------------------------- //
// STORE SYSTEM: SYNC IN AND SYNC OUT
// PLAYER LEAVE EVENT
// -------------------------------------------- //
// There are some forced syncs of players in all collections so developers can rest assure the data is up to date.
// PlayerLoginEvent LOW. LOWEST is left for anti flood and bans.
// PlayerKickEvent MONITOR.
// PlayerQuitEvent MONITOR.
// Why do we sync at both PlayerKickEvent and PlayerQuitEvent you may wonder?
// PlayerQuitEvent do not always fire, for example due to a spoutcraft bug
// and it also fires AFTER the player left the server. In kick cases we can sync
// directly before the player leaves the server. That is great.
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void leaveEventKickCall(PlayerKickEvent event)
{
new MCorePlayerLeaveEvent(event.getPlayer(), true, "kick", event.getReason()).run();
}
@EventHandler(priority = EventPriority.MONITOR)
public void leaveEventQuitCall(PlayerQuitEvent event)
{
new MCorePlayerLeaveEvent(event.getPlayer(), false, "quit", null).run();
}
@EventHandler(priority = EventPriority.MONITOR)
public void leaveEventQuitClear(PlayerQuitEvent event)
{
// We do the schedule in order for the set to be correct through out the whole MONITOR priority state.
final String name = event.getPlayer().getName();
Bukkit.getScheduler().scheduleSyncDelayedTask(MCore.p, new Runnable()
{
@Override
public void run()
{
MCorePlayerLeaveEvent.player2event.remove(name);
}
});
}
// -------------------------------------------- //
// SYNC PLAYER ON LOGON AND LEAVE
// -------------------------------------------- //
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void syncOnPlayerLogin(PlayerLoginEvent event)
{
p.log("syncOnPlayerLogin", event.getPlayer().getName());
this.syncAllForPlayer(event.getPlayer());
}
@EventHandler(priority = EventPriority.MONITOR)
public void syncOnPlayerLeave(MCorePlayerLeaveEvent event)
{
p.log("syncOnPlayerLeave", event.getPlayer().getName());
this.syncAllForPlayer(event.getPlayer());
}
public void syncAllForPlayer(Player player)
{
@ -113,36 +150,6 @@ public class InternalListener implements Listener
if (!(coll instanceof PlayerColl)) continue;
PlayerColl<?> pcoll = (PlayerColl<?>)coll;
pcoll.syncId(playerName);
//ModificationState mstate = pcoll.syncId(playerName);
//p.log("syncAllForPlayer", coll.name(), playerName, pcoll.syncId(playerName), pcoll.syncId(playerName));
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void syncAllForPlayer(PlayerLoginEvent event)
{
//p.log("syncAllForPlayer PlayerLoginEvent LOW", event.getPlayer().getName());
this.syncAllForPlayer(event.getPlayer());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void syncAllForPlayer(PlayerKickEvent event)
{
//p.log("syncAllForPlayer PlayerKickEvent MONITOR", event.getPlayer().getName());
new MCorePlayerLeaveEvent(event.getPlayer(), true, event.getReason()).run();
this.syncAllForPlayer(event.getPlayer());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void syncAllForPlayer(PlayerQuitEvent event)
{
//p.log("syncAllForPlayer PlayerQuitEvent MONITOR", event.getPlayer().getName());
if (!MUtil.causedByKick(event))
{
new MCorePlayerLeaveEvent(event.getPlayer(), false, null).run();
}
this.syncAllForPlayer(event.getPlayer());
}
}

View File

@ -10,6 +10,7 @@ import org.bukkit.inventory.ItemStack;
import com.massivecraft.mcore4.adapter.InventoryAdapter;
import com.massivecraft.mcore4.adapter.ItemStackAdapter;
import com.massivecraft.mcore4.adapter.MongoURIAdapter;
import com.massivecraft.mcore4.adapter.PSAdapter;
import com.massivecraft.mcore4.persist.Persist;
import com.massivecraft.mcore4.store.Coll;
import com.massivecraft.mcore4.store.Db;
@ -24,6 +25,13 @@ import com.massivecraft.mcore4.xlib.mongodb.MongoURI;
public class MCore extends MPlugin
{
// -------------------------------------------- //
// COMMON CONSTANTS
// -------------------------------------------- //
public final static String INSTANCE = "instance";
public final static String DEFAULT = "default";
// -------------------------------------------- //
// STATIC
// -------------------------------------------- //
@ -39,7 +47,8 @@ public class MCore extends MPlugin
.excludeFieldsWithModifiers(Modifier.TRANSIENT)
.registerTypeAdapter(MongoURI.class, MongoURIAdapter.get())
.registerTypeAdapter(ItemStack.class, new ItemStackAdapter())
.registerTypeAdapter(Inventory.class, new InventoryAdapter());
.registerTypeAdapter(Inventory.class, new InventoryAdapter())
.registerTypeAdapter(PS.class, new PSAdapter());
}
public static String getServerId() { return Conf.serverid; }

View File

@ -1,14 +1,20 @@
package com.massivecraft.mcore4;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import com.massivecraft.mcore4.store.accessor.Accessor;
import com.massivecraft.mcore4.util.Txt;
import com.massivecraft.mcore4.xlib.gson.annotations.SerializedName;
/**
@ -421,13 +427,45 @@ public class PS implements Cloneable
return this;
}
// ---------------------
// TODO: This should be removed later on when my converting phase is complete.
public synchronized PS read(String str)
{
return this.readDefault().readTransparent(str);
}
public synchronized PS readTransparent(String str)
{
String[] parts = str.split("\\|");
if (parts.length == 4)
{
this.worldName = parts[0];
this.blockX = Integer.parseInt(parts[1]);
this.blockY = Integer.parseInt(parts[2]);
this.blockZ = Integer.parseInt(parts[3]);
}
else if (parts.length == 6)
{
this.worldName = parts[0];
this.locationX = Double.parseDouble(parts[1]);
this.locationY = Double.parseDouble(parts[2]);
this.locationZ = Double.parseDouble(parts[3]);
this.pitch = Float.parseFloat(parts[4]);
this.yaw = Float.parseFloat(parts[5]);
}
return this;
}
//----------------------------------------------//
// WRITERS
//----------------------------------------------//
public synchronized void write(Player player)
public synchronized void write(Entity entity)
{
teleporter.teleport(player, this);
teleporter.teleport(entity, this);
}
//----------------------------------------------//
@ -479,6 +517,71 @@ public class PS implements Cloneable
return this.getClass().getSimpleName()+MCore.gson.toJson(this);
}
protected final transient static DecimalFormat twoDForm = new DecimalFormat("#.##");
public List<String> getDesc()
{
// ret.add("<h>World <a>"+this.worldName);
return this.getDesc("<k>%s <v>%s");
}
public List<String> getDesc(String format)
{
List<String> ret = new ArrayList<String>();
if (this.worldName != null) ret.add(Txt.parse(format, "World", this.worldName));
if (this.blockX != null) ret.add(Txt.parse(format, "Block X", this.blockX));
if (this.blockY != null) ret.add(Txt.parse(format, "Block Y", this.blockY));
if (this.blockZ != null) ret.add(Txt.parse(format, "Block Z", this.blockZ));
if (this.locationX != null) ret.add(Txt.parse(format, "Location X", twoDForm.format(this.locationX)));
if (this.locationY != null) ret.add(Txt.parse(format, "Location Y", twoDForm.format(this.locationY)));
if (this.locationZ != null) ret.add(Txt.parse(format, "Location Z", twoDForm.format(this.locationZ)));
if (this.chunkX != null) ret.add(Txt.parse(format, "Chunk X", this.chunkX));
if (this.chunkZ != null) ret.add(Txt.parse(format, "Chunk Z", this.chunkZ));
if (this.pitch != null) ret.add(Txt.parse(format, "Pitch", twoDForm.format(this.pitch)));
if (this.yaw != null) ret.add(Txt.parse(format, "Yaw", twoDForm.format(this.yaw)));
if (this.velocityX != null) ret.add(Txt.parse(format, "Velocity X", twoDForm.format(this.velocityX)));
if (this.velocityY != null) ret.add(Txt.parse(format, "Velocity Y", twoDForm.format(this.velocityY)));
if (this.velocityZ != null) ret.add(Txt.parse(format, "Velocity Z", twoDForm.format(this.velocityZ)));
return ret;
}
public String getShortDesc()
{
return this.getShortDesc("<k>%s <v>%s ");
}
public String getShortDesc(String format)
{
List<String> ret = new ArrayList<String>();
if (this.worldName != null) ret.add(Txt.parse(format, "w", this.worldName));
if (this.blockX != null) ret.add(Txt.parse(format, "bx", this.blockX));
if (this.blockY != null) ret.add(Txt.parse(format, "by", this.blockY));
if (this.blockZ != null) ret.add(Txt.parse(format, "bz", this.blockZ));
if (this.locationX != null) ret.add(Txt.parse(format, "lx", twoDForm.format(this.locationX)));
if (this.locationY != null) ret.add(Txt.parse(format, "ly", twoDForm.format(this.locationY)));
if (this.locationZ != null) ret.add(Txt.parse(format, "lz", twoDForm.format(this.locationZ)));
if (this.chunkX != null) ret.add(Txt.parse(format, "cx", this.chunkX));
if (this.chunkZ != null) ret.add(Txt.parse(format, "cz", this.chunkZ));
if (this.pitch != null) ret.add(Txt.parse(format, "p", twoDForm.format(this.pitch)));
if (this.yaw != null) ret.add(Txt.parse(format, "y", twoDForm.format(this.yaw)));
if (this.velocityX != null) ret.add(Txt.parse(format, "vx", twoDForm.format(this.velocityX)));
if (this.velocityY != null) ret.add(Txt.parse(format, "vy", twoDForm.format(this.velocityY)));
if (this.velocityZ != null) ret.add(Txt.parse(format, "vz", twoDForm.format(this.velocityZ)));
return Txt.implode(ret, "").trim();
}
//----------------------------------------------//
// CLONE
//----------------------------------------------//

View File

@ -0,0 +1,53 @@
package com.massivecraft.mcore4.adapter;
import java.lang.reflect.Type;
import com.massivecraft.mcore4.PS;
import com.massivecraft.mcore4.xlib.gson.Gson;
import com.massivecraft.mcore4.xlib.gson.JsonDeserializationContext;
import com.massivecraft.mcore4.xlib.gson.JsonDeserializer;
import com.massivecraft.mcore4.xlib.gson.JsonElement;
import com.massivecraft.mcore4.xlib.gson.JsonParseException;
import com.massivecraft.mcore4.xlib.gson.JsonPrimitive;
import com.massivecraft.mcore4.xlib.mongodb.MongoURI;
public class PSAdapter implements JsonDeserializer<PS>
{
// -------------------------------------------- //
// IMPLEMENTATION
// -------------------------------------------- //
@Override
public PS deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
{
if (json.isJsonPrimitive())
{
return new PS().read(json.getAsString());
}
return new Gson().fromJson(json, typeOfT);
}
// -------------------------------------------- //
// STATIC LOGIC
// -------------------------------------------- //
public static JsonElement serialize(MongoURI mongoURI)
{
return new JsonPrimitive(mongoURI.toString());
}
public static MongoURI deserialize(JsonElement json)
{
return new MongoURI(json.getAsString());
}
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
protected static PSAdapter instance = new PSAdapter();
public static PSAdapter get()
{
return instance;
}
}

View File

@ -1,10 +1,15 @@
package com.massivecraft.mcore4.event;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import com.massivecraft.mcore4.MCore;
/**
* The MCorePlayerLeaveEvent is a non-cancellable event.
* It is run at the MONITOR of either PlayerKickEvent or PlayerQuitEvent.
@ -13,8 +18,7 @@ import org.bukkit.event.HandlerList;
*
* Use this even if you want to update a player entity as
* that player leaves. Automatic syncing will be guaranteed and the
* event will run the moment BEFORE the player leaves the server if possible
* due to the internal usage if the PlayerKickedEvent.
* event will run pre disconnect if possible due to the internal usage if the PlayerKickedEvent.
*/
public class MCorePlayerLeaveEvent extends Event implements Runnable
{
@ -32,22 +36,28 @@ public class MCorePlayerLeaveEvent extends Event implements Runnable
protected Player player;
public Player getPlayer() { return this.player; }
protected boolean kick;
public boolean isKick() { return this.kick; }
public boolean isQuit() { return !this.kick; }
protected boolean preDisconnect;
public boolean isPreDisconnect() { return this.preDisconnect; }
public boolean isPostDisconnect() { return !this.isPreDisconnect(); }
protected String kickReason;
public String getKickReason() { return this.kickReason; }
protected String caller;
public String getCaller() { return this.caller; }
public boolean isQuit() { return "quit".equals(caller); }
public boolean isKick() { return "kick".equals(caller); }
protected String message;
public String getMessage() { return this.message; }
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public MCorePlayerLeaveEvent(Player player, boolean kick, String kickReason)
public MCorePlayerLeaveEvent(Player player, boolean preDisconnect, String caller, String message)
{
this.player = player;
this.kick = kick;
this.kickReason = kickReason;
this.preDisconnect = preDisconnect;
this.caller = caller;
this.message = message;
}
// -------------------------------------------- //
@ -57,7 +67,23 @@ public class MCorePlayerLeaveEvent extends Event implements Runnable
@Override
public void run()
{
Bukkit.getPluginManager().callEvent(this);
// Someone may already have issued a player leave event for this disconnect.
// We ignore that since we want one leave event called per disconnect only.
boolean doit = !player2event.containsKey(this.player.getName());
//MCore.p.log("MCorePlayerLeaveEvent", "caller:", caller, "doit:", doit, "player:", player.getDisplayName(), "preDisconnect:", preDisconnect, "message:", message);
if (doit)
{
MCore.p.log("MCorePlayerLeaveEvent", caller, player.getDisplayName(), preDisconnect, message);
player2event.put(this.player.getName(), this);
Bukkit.getPluginManager().callEvent(this);
}
}
// -------------------------------------------- //
// STORING THE ACTIVE PLAYER EVENT
// -------------------------------------------- //
public static Map<String,MCorePlayerLeaveEvent> player2event = new HashMap<String,MCorePlayerLeaveEvent>();
}

View File

@ -579,6 +579,7 @@ public class Coll<E, L> implements CollInterface<E, L>
@Override
public void init()
{
if (instances.contains(this)) return;
this.syncAll();
this.examineThread = new ExamineThread<E, L>(this);
this.examineThread.start();

View File

@ -6,15 +6,16 @@ import java.util.List;
import java.util.Map;
import com.massivecraft.mcore4.usys.Aspect;
import com.massivecraft.mcore4.usys.Multiverse;
import com.massivecraft.mcore4.util.MUtil;
public abstract class Colls<C extends Coll<E, L>, E, L>
{
protected Map<String, C> name2coll = new HashMap<String, C>();
public abstract C createColl(String name);
public abstract Aspect aspect();
public abstract String basename();
public abstract C createColl(String name);
// -------------------------------------------- //
// CONSTRUCT
@ -28,7 +29,9 @@ public abstract class Colls<C extends Coll<E, L>, E, L>
public List<C> getColls()
{
List<C> ret = new ArrayList<C>();
for (String universe : this.aspect().multiverse().getUniverses())
Aspect a = this.aspect();
Multiverse m = a.multiverse();
for (String universe : m.getUniverses())
{
ret.add(this.getForUniverse(universe));
}
@ -75,6 +78,7 @@ public abstract class Colls<C extends Coll<E, L>, E, L>
if (ret == null)
{
ret = this.createColl(collname);
ret.init();
this.name2coll.put(collname, ret);
}
return ret;

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import com.massivecraft.mcore4.MCore;
import com.massivecraft.mcore4.store.Entity;
import com.massivecraft.mcore4.xlib.gson.annotations.SerializedName;
@ -48,7 +49,7 @@ public class Aspect extends Entity<Aspect, String>
public Multiverse multiverse()
{
Multiverse ret = MultiverseColl.i.get(this.multiverseId);
if (ret == null) ret = MultiverseColl.i.get(Multiverse.DEFAULT);
if (ret == null) ret = MultiverseColl.i.get(MCore.DEFAULT);
return ret;
}
public void multiverse(Multiverse val) { this.multiverseId = val.getId(); }

View File

@ -8,6 +8,7 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.massivecraft.mcore4.MCore;
import com.massivecraft.mcore4.cmd.arg.ARUniverse;
import com.massivecraft.mcore4.store.Entity;
import com.massivecraft.mcore4.util.MUtil;
@ -33,8 +34,6 @@ public class Multiverse extends Entity<Multiverse, String>
// FIELDS
// -------------------------------------------- //
public static final transient String DEFAULT = "default";
protected Map<String, Set<String>> uw = new HashMap<String, Set<String>>();
@ -72,7 +71,7 @@ public class Multiverse extends Entity<Multiverse, String>
public Set<String> newUniverse(String universe)
{
if (universe.equals(Multiverse.DEFAULT)) return null;
if (universe.equals(MCore.DEFAULT)) return null;
Set<String> ret = this.uw.get(universe);
if (ret == null)
{
@ -91,7 +90,7 @@ public class Multiverse extends Entity<Multiverse, String>
{
Set<String> ret = new LinkedHashSet<String>();
ret.addAll(this.uw.keySet());
ret.add(Multiverse.DEFAULT);
ret.add(MCore.DEFAULT);
return ret;
}
@ -103,7 +102,7 @@ public class Multiverse extends Entity<Multiverse, String>
Set<String> worlds = entry.getValue();
if (worlds.contains(worldName)) return universe;
}
return Multiverse.DEFAULT;
return MCore.DEFAULT;
}
public String getUniverse(Object worldNameExtractable)
@ -128,7 +127,7 @@ public class Multiverse extends Entity<Multiverse, String>
{
if (this.getUniverseForWorldName(worldName).equals(universe)) return false;
this.removeWorld(worldName);
if (!universe.equals(Multiverse.DEFAULT))
if (!universe.equals(MCore.DEFAULT))
{
this.newUniverse(universe).add(worldName);
}

View File

@ -21,7 +21,7 @@ public class MultiverseColl extends Coll<Multiverse, String>
super.init();
// Ensure the default multiverse exits
this.get(Multiverse.DEFAULT, true);
this.get(MCore.DEFAULT, true);
}
}

View File

@ -1,5 +1,6 @@
package com.massivecraft.mcore4.usys.cmd;
import com.massivecraft.mcore4.MCore;
import com.massivecraft.mcore4.Permission;
import com.massivecraft.mcore4.cmd.arg.ARMultiverse;
import com.massivecraft.mcore4.cmd.req.ReqHasPerm;
@ -23,7 +24,7 @@ public class CmdUsysMultiverseDel extends UsysCommand
String id = multiverse.getId();
if (id.equals(Multiverse.DEFAULT))
if (id.equals(MCore.DEFAULT))
{
msg("<b>You can't delete the default multiverse.");
return;

View File

@ -3,6 +3,7 @@ package com.massivecraft.mcore4.usys.cmd;
import java.util.ArrayList;
import java.util.List;
import com.massivecraft.mcore4.MCore;
import com.massivecraft.mcore4.Permission;
import com.massivecraft.mcore4.cmd.arg.ARMultiverse;
import com.massivecraft.mcore4.cmd.req.ReqHasPerm;
@ -30,7 +31,7 @@ public class CmdUsysMultiverseShow extends UsysCommand
for (String universe : multiverse.getUniverses())
{
if (universe.equals(Multiverse.DEFAULT)) continue;
if (universe.equals(MCore.DEFAULT)) continue;
msg("<aqua>"+universe+"<i>: "+Txt.implodeCommaAndDot(multiverse.getWorlds(universe), "<h>%s", "<i>, ", " <i>and ", "<i>."));
}
msg("<aqua>default<i>: for all other worlds.");

View File

@ -1,5 +1,6 @@
package com.massivecraft.mcore4.usys.cmd;
import com.massivecraft.mcore4.MCore;
import com.massivecraft.mcore4.Permission;
import com.massivecraft.mcore4.cmd.arg.ARMultiverse;
import com.massivecraft.mcore4.cmd.req.ReqHasPerm;
@ -24,7 +25,7 @@ public class CmdUsysUniverseClear extends UsysCommand
String universe = this.arg(0);
if (universe.equals(Multiverse.DEFAULT))
if (universe.equals(MCore.DEFAULT))
{
msg("<b>You can't clear the default universe.");
msg("<b>It contains the worlds that aren't assigned to a universe.");

View File

@ -1,5 +1,6 @@
package com.massivecraft.mcore4.usys.cmd;
import com.massivecraft.mcore4.MCore;
import com.massivecraft.mcore4.Permission;
import com.massivecraft.mcore4.cmd.arg.ARMultiverse;
import com.massivecraft.mcore4.cmd.req.ReqHasPerm;
@ -24,7 +25,7 @@ public class CmdUsysUniverseDel extends UsysCommand
String universe = this.arg(0);
if (universe.equals(Multiverse.DEFAULT))
if (universe.equals(MCore.DEFAULT))
{
msg("<b>You can't remove the default universe.");
msg("<b>Each multiverse contains a default universe.");