mcore5
This commit is contained in:
29
src/com/massivecraft/mcore5/Conf.java
Normal file
29
src/com/massivecraft/mcore5/Conf.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.massivecraft.mcore5.usys.cmd.CmdUsys;
|
||||
import com.massivecraft.mcore5.util.MUtil;
|
||||
|
||||
public class Conf extends SimpleConfig
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// CONTENT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static String dburi = "gson://./mstore";
|
||||
public static String serverid = UUID.randomUUID().toString();
|
||||
public static Map<String, List<String>> cmdaliases = MUtil.map(CmdUsys.USYS, MUtil.list(CmdUsys.USYS));
|
||||
|
||||
// -------------------------------------------- //
|
||||
// META
|
||||
// -------------------------------------------- //
|
||||
public static transient Conf i = new Conf();
|
||||
private Conf()
|
||||
{
|
||||
super(MCore.p, new File("plugins/mcore/conf.json"));
|
||||
}
|
||||
}
|
||||
154
src/com/massivecraft/mcore5/InternalListener.java
Normal file
154
src/com/massivecraft/mcore5/InternalListener.java
Normal file
@@ -0,0 +1,154 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerKickEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
import com.massivecraft.mcore5.event.MCoreAfterPlayerRespawnEvent;
|
||||
import com.massivecraft.mcore5.event.MCoreAfterPlayerTeleportEvent;
|
||||
import com.massivecraft.mcore5.event.MCorePlayerLeaveEvent;
|
||||
import com.massivecraft.mcore5.store.Coll;
|
||||
import com.massivecraft.mcore5.store.PlayerColl;
|
||||
|
||||
public class InternalListener implements Listener
|
||||
{
|
||||
MCore p;
|
||||
|
||||
public InternalListener(MCore p)
|
||||
{
|
||||
this.p = p;
|
||||
MCorePlayerLeaveEvent.player2event.clear();
|
||||
Bukkit.getServer().getPluginManager().registerEvents(this, this.p);
|
||||
}
|
||||
|
||||
/*
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerLogin(PlayerLoginEvent event)
|
||||
{
|
||||
String id = event.getPlayer().getName();
|
||||
|
||||
for (Persist instance : Persist.instances)
|
||||
{
|
||||
for (IClassManager<?> manager : instance.getClassManagers().values())
|
||||
{
|
||||
if (manager.idCanFix(Player.class) == false) continue;
|
||||
if (manager.containsId(id)) continue;
|
||||
manager.create(id);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// -------------------------------------------- //
|
||||
// AFTER EVENTS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void after(PlayerTeleportEvent event)
|
||||
{
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(p, new MCoreAfterPlayerTeleportEvent(event), 0);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void after(PlayerRespawnEvent event)
|
||||
{
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(p, new MCoreAfterPlayerRespawnEvent(event, event.getPlayer().getLocation()), 0);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// EVENT TOOL: causedByKick
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Map<String,String> kickedPlayerReasons = new HashMap<String,String>();
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void causedByKick(PlayerKickEvent event)
|
||||
{
|
||||
final String name = event.getPlayer().getName();
|
||||
kickedPlayerReasons.put(name, event.getReason());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void causedByKick(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()
|
||||
{
|
||||
kickedPlayerReasons.remove(name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// PLAYER LEAVE EVENT
|
||||
// -------------------------------------------- //
|
||||
|
||||
@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)
|
||||
{
|
||||
String playerName = player.getName();
|
||||
for (Coll<?, ?> coll : Coll.instances)
|
||||
{
|
||||
if (!(coll instanceof PlayerColl)) continue;
|
||||
PlayerColl<?> pcoll = (PlayerColl<?>)coll;
|
||||
pcoll.syncId(playerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/com/massivecraft/mcore5/Lang.java
Normal file
12
src/com/massivecraft/mcore5/Lang.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
public class Lang
|
||||
{
|
||||
public static final String permForbidden = "<b>You don't have permission to %s.";
|
||||
public static final String permDoThat = "do that";
|
||||
|
||||
public static final String commandSenderMustBePlayer = "<b>This command can only be used by ingame players.";
|
||||
public static final String commandToFewArgs = "<b>To few arguments. <i>Use like this:";
|
||||
public static final String commandToManyArgs = "<b>Strange arguments %s<b>.";
|
||||
public static final String commandToManyArgs2 = "<i>Use the command like this:";
|
||||
}
|
||||
119
src/com/massivecraft/mcore5/MCore.java
Normal file
119
src/com/massivecraft/mcore5/MCore.java
Normal file
@@ -0,0 +1,119 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Random;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.massivecraft.mcore5.adapter.InventoryAdapter;
|
||||
import com.massivecraft.mcore5.adapter.ItemStackAdapter;
|
||||
import com.massivecraft.mcore5.adapter.MongoURIAdapter;
|
||||
import com.massivecraft.mcore5.adapter.PSAdapter;
|
||||
import com.massivecraft.mcore5.store.Coll;
|
||||
import com.massivecraft.mcore5.store.Db;
|
||||
import com.massivecraft.mcore5.store.MStore;
|
||||
import com.massivecraft.mcore5.usys.AspectColl;
|
||||
import com.massivecraft.mcore5.usys.MultiverseColl;
|
||||
import com.massivecraft.mcore5.usys.cmd.CmdUsys;
|
||||
import com.massivecraft.mcore5.util.PlayerUtil;
|
||||
import com.massivecraft.mcore5.xlib.gson.Gson;
|
||||
import com.massivecraft.mcore5.xlib.gson.GsonBuilder;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.MongoURI;
|
||||
|
||||
public class MCore extends MPlugin
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// COMMON CONSTANTS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public final static String INSTANCE = "instance";
|
||||
public final static String DEFAULT = "default";
|
||||
|
||||
// -------------------------------------------- //
|
||||
// STATIC
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Random random = new Random();
|
||||
public static Gson gson = getMCoreGsonBuilder().create();
|
||||
|
||||
public static GsonBuilder getMCoreGsonBuilder()
|
||||
{
|
||||
return new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.excludeFieldsWithModifiers(Modifier.TRANSIENT)
|
||||
.registerTypeAdapter(MongoURI.class, MongoURIAdapter.get())
|
||||
.registerTypeAdapter(ItemStack.class, new ItemStackAdapter())
|
||||
.registerTypeAdapter(Inventory.class, new InventoryAdapter())
|
||||
.registerTypeAdapter(PS.class, new PSAdapter());
|
||||
}
|
||||
|
||||
public static String getServerId() { return Conf.serverid; }
|
||||
private static Db<?> db;
|
||||
public static Db<?> getDb() { return db; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static MCore p;
|
||||
public MCore()
|
||||
{
|
||||
p = this;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// NON STATIC :)
|
||||
// -------------------------------------------- //
|
||||
|
||||
private Runnable collTickTask = new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
for (Coll<?, ?> coll : Coll.instances)
|
||||
{
|
||||
coll.onTick();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public InternalListener internalListener;
|
||||
public CmdUsys cmdUsys;
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
// This is safe since all plugins using Persist should bukkit-depend this plugin.
|
||||
// Note this one must be before preEnable. dooh.
|
||||
Coll.instances.clear();
|
||||
|
||||
if ( ! preEnable()) return;
|
||||
|
||||
Conf.i.load();
|
||||
|
||||
// Setup the default database
|
||||
db = MStore.getDb(Conf.dburi);
|
||||
|
||||
// Setup PlayerUtil and it's events
|
||||
new PlayerUtil(this);
|
||||
|
||||
// Register events
|
||||
this.internalListener = new InternalListener(this);
|
||||
|
||||
// Schedule the collection ticker.
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, this.collTickTask, 1, 1);
|
||||
|
||||
// Init internal collections
|
||||
MultiverseColl.i.init();
|
||||
AspectColl.i.init();
|
||||
|
||||
// Register commands
|
||||
this.cmdUsys = new CmdUsys();
|
||||
this.cmdUsys.register(true);
|
||||
|
||||
this.postEnable();
|
||||
}
|
||||
|
||||
}
|
||||
116
src/com/massivecraft/mcore5/MPlugin.java
Normal file
116
src/com/massivecraft/mcore5/MPlugin.java
Normal file
@@ -0,0 +1,116 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.massivecraft.mcore5.integration.Integration;
|
||||
import com.massivecraft.mcore5.integration.IntegrationFeatures;
|
||||
import com.massivecraft.mcore5.store.Coll;
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
import com.massivecraft.mcore5.xlib.gson.Gson;
|
||||
import com.massivecraft.mcore5.xlib.gson.GsonBuilder;
|
||||
|
||||
public abstract class MPlugin extends JavaPlugin implements Listener
|
||||
{
|
||||
// Gson
|
||||
public Gson gson;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ENABLE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private long timeEnableStart;
|
||||
public boolean preEnable()
|
||||
{
|
||||
timeEnableStart = System.currentTimeMillis();
|
||||
|
||||
this.logPrefixColored = Txt.parse("<teal>[<aqua>%s %s<teal>] <i>", this.getDescription().getName(), this.getDescription().getVersion());
|
||||
this.logPrefixPlain = ChatColor.stripColor(this.logPrefixColored);
|
||||
|
||||
log("=== ENABLE START ===");
|
||||
|
||||
// Create Gson
|
||||
this.gson = this.getGsonBuilder().create();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void postEnable()
|
||||
{
|
||||
log(Txt.parse("=== ENABLE <g>COMPLETE <i>(Took <h>"+(System.currentTimeMillis()-timeEnableStart)+"ms<i>) ==="));
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// DISABLE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void onDisable()
|
||||
{
|
||||
// Collection shutdowns.
|
||||
for (Coll<?, ?> coll : Coll.instances)
|
||||
{
|
||||
if (coll.getMplugin() != this) continue;
|
||||
coll.examineThread().interrupt();
|
||||
coll.syncAll(); // TODO: Save outwards only? We may want to avoid loads at this stage...
|
||||
Coll.instances.remove(coll);
|
||||
}
|
||||
|
||||
log("Disabled");
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// GSON
|
||||
// -------------------------------------------- //
|
||||
|
||||
public GsonBuilder getGsonBuilder()
|
||||
{
|
||||
return MCore.getMCoreGsonBuilder();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONVENIENCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void suicide()
|
||||
{
|
||||
log(Txt.parse("<b>Now I suicide!"));
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
}
|
||||
|
||||
public void integrate(IntegrationFeatures... features)
|
||||
{
|
||||
for (IntegrationFeatures f : features)
|
||||
{
|
||||
new Integration(this, f);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// LOGGING
|
||||
// -------------------------------------------- //
|
||||
private String logPrefixColored = null;
|
||||
private String logPrefixPlain = null;
|
||||
public void log(Object... msg)
|
||||
{
|
||||
log(Level.INFO, msg);
|
||||
}
|
||||
public void log(Level level, Object... msg)
|
||||
{
|
||||
String imploded = Txt.implode(msg, " ");
|
||||
ConsoleCommandSender sender = Bukkit.getConsoleSender();
|
||||
if (level == Level.INFO && sender != null)
|
||||
{
|
||||
Bukkit.getConsoleSender().sendMessage(this.logPrefixColored + imploded);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.getLogger("Minecraft").log(level, this.logPrefixPlain + imploded);
|
||||
}
|
||||
}
|
||||
}
|
||||
614
src/com/massivecraft/mcore5/PS.java
Normal file
614
src/com/massivecraft/mcore5/PS.java
Normal file
@@ -0,0 +1,614 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
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.util.Vector;
|
||||
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
import com.massivecraft.mcore5.xlib.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* PS stands for PhysicalState.
|
||||
* This class stores data related to just that.
|
||||
* When coding plugins you may find yourself wanting to store a player location.
|
||||
* Another time you may want to store the player location but without the worldName info.
|
||||
* Another time you may want to store pitch and yaw only.
|
||||
* This class is supposed to be usable in all those cases.
|
||||
* Hopefully this class will save you from implementing special classes for all those combinations.
|
||||
*/
|
||||
|
||||
@EqualsAndHashCode
|
||||
public class PS implements Cloneable
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// TELEPORTER
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static transient PSTeleporter teleporter = PSTeleporterDefault.get();
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
// Field: worldName
|
||||
@SerializedName("w")
|
||||
@Getter @Setter protected String worldName = null;
|
||||
|
||||
// FakeField: world
|
||||
public World getWorld()
|
||||
{
|
||||
if (this.worldName == null) return null;
|
||||
return Bukkit.getWorld(this.worldName);
|
||||
}
|
||||
public void setWorld(World val)
|
||||
{
|
||||
this.worldName = val.getName();
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
// Field: blockX
|
||||
@SerializedName("bx")
|
||||
@Getter @Setter protected Integer blockX = null;
|
||||
public Integer calcBlockX()
|
||||
{
|
||||
return calcBlock(this.locationX, this.blockX, this.chunkX);
|
||||
}
|
||||
|
||||
// Field: blockY
|
||||
@SerializedName("by")
|
||||
@Getter @Setter protected Integer blockY = null;
|
||||
public Integer calcBlockY()
|
||||
{
|
||||
return calcBlock(this.locationY, this.blockY, null);
|
||||
}
|
||||
|
||||
// Field: blockZ
|
||||
@SerializedName("bz")
|
||||
@Getter @Setter protected Integer blockZ = null;
|
||||
public Integer calcBlockZ()
|
||||
{
|
||||
return calcBlock(this.locationZ, this.blockZ, this.chunkZ);
|
||||
}
|
||||
|
||||
protected static synchronized Integer calcBlock(Double location, Integer block, Integer chunk)
|
||||
{
|
||||
if (block != null) return block;
|
||||
if (location != null) return (int) Math.floor(location);
|
||||
if (chunk != null) return chunk * 16;
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
// Field: locationX
|
||||
@SerializedName("lx")
|
||||
@Getter @Setter protected Double locationX = null;
|
||||
public Double calcLocationX()
|
||||
{
|
||||
return calcLocation(this.locationX, this.blockX, this.chunkX);
|
||||
}
|
||||
|
||||
// Field: locationY
|
||||
@SerializedName("ly")
|
||||
@Getter @Setter protected Double locationY = null;
|
||||
public Double calcLocationY()
|
||||
{
|
||||
return calcLocation(this.locationY, this.blockY, null);
|
||||
}
|
||||
|
||||
// Field: locationZ
|
||||
@SerializedName("lz")
|
||||
@Getter @Setter protected Double locationZ = null;
|
||||
public Double calclocationZ()
|
||||
{
|
||||
return calcLocation(this.locationZ, this.blockZ, this.chunkZ);
|
||||
}
|
||||
|
||||
protected static synchronized Double calcLocation(Double location, Integer block, Integer chunk)
|
||||
{
|
||||
if (location != null) return location;
|
||||
if (block != null) return (double) block;
|
||||
if (chunk != null) return chunk * 16D;
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
// Field: chunkX
|
||||
@SerializedName("cx")
|
||||
@Getter @Setter protected Integer chunkX = null;
|
||||
public Integer calcChunkX()
|
||||
{
|
||||
return calcChunk(this.locationX, this.blockX, this.chunkX);
|
||||
}
|
||||
|
||||
// Field: chunkZ
|
||||
@SerializedName("xz")
|
||||
@Getter @Setter protected Integer chunkZ = null;
|
||||
public Integer calcChunkZ()
|
||||
{
|
||||
return calcChunk(this.locationZ, this.blockZ, this.chunkZ);
|
||||
}
|
||||
|
||||
protected static synchronized Integer calcChunk(Double location, Integer block, Integer chunk)
|
||||
{
|
||||
if (chunk != null) return chunk;
|
||||
if (location != null) return location.intValue() >> 4;
|
||||
if (block != null) return block >> 4;
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
// Field: pitch
|
||||
@SerializedName("p")
|
||||
@Getter protected Float pitch = null;
|
||||
public void setPitch(Float val)
|
||||
{
|
||||
if (val == null)
|
||||
{
|
||||
this.pitch = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.pitch = (val + 360F) % 360F;
|
||||
}
|
||||
}
|
||||
|
||||
// Field: yaw
|
||||
@SerializedName("y")
|
||||
@Getter @Setter protected Float yaw = null;
|
||||
|
||||
// ---------------------
|
||||
|
||||
// Field: velocityX
|
||||
@SerializedName("vx")
|
||||
@Getter @Setter protected Double velocityX = null;
|
||||
public Double calcVelocityX()
|
||||
{
|
||||
return calcVelocity(this.locationX, this.blockX, this.chunkX, this.velocityX);
|
||||
}
|
||||
|
||||
// Field: velocityY
|
||||
@SerializedName("vy")
|
||||
@Getter @Setter protected Double velocityY = null;
|
||||
public Double calcVelocityY()
|
||||
{
|
||||
return calcVelocity(this.locationY, this.blockY, 0, this.velocityY);
|
||||
}
|
||||
|
||||
// Field: velocityZ
|
||||
@SerializedName("vz")
|
||||
@Getter @Setter protected Double velocityZ = null;
|
||||
public Double calcVelocityZ()
|
||||
{
|
||||
return calcVelocity(this.locationZ, this.blockZ, this.chunkZ, this.velocityZ);
|
||||
}
|
||||
|
||||
protected static synchronized Double calcVelocity(Double location, Integer block, Integer chunk, Double velocity)
|
||||
{
|
||||
if (velocity != null) return velocity;
|
||||
if (location != null) return location;
|
||||
if (block != null) return (double) block;
|
||||
if (chunk != null) return chunk * 16D;
|
||||
return null;
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// GET / CALC
|
||||
//----------------------------------------------//
|
||||
|
||||
public synchronized Location getLocation()
|
||||
{
|
||||
return this.innerLocation(this.getLocationX(), this.getLocationY(), this.getLocationZ());
|
||||
}
|
||||
public synchronized Location calcLocation()
|
||||
{
|
||||
return this.innerLocation(this.calcLocationX(), this.calcLocationY(), this.calclocationZ());
|
||||
}
|
||||
protected synchronized Location innerLocation(Double x, Double y, Double z)
|
||||
{
|
||||
World world = this.getWorld();
|
||||
|
||||
if (x == null) return null;
|
||||
if (y == null) return null;
|
||||
if (z == null) return null;
|
||||
|
||||
Float pitch = this.getPitch();
|
||||
if (pitch == null) pitch = 0F;
|
||||
|
||||
Float yaw = this.getYaw();
|
||||
if (yaw == null) yaw = 0F;
|
||||
|
||||
return new Location(world, x, y, z, pitch, yaw);
|
||||
}
|
||||
|
||||
public synchronized Block getBlock()
|
||||
{
|
||||
return this.innerBlock(this.getBlockX(), this.getBlockY(), this.getBlockZ());
|
||||
}
|
||||
public synchronized Block calcBlock()
|
||||
{
|
||||
return this.innerBlock(this.calcBlockX(), this.calcBlockY(), this.calcBlockZ());
|
||||
}
|
||||
protected synchronized Block innerBlock(Integer x, Integer y, Integer z)
|
||||
{
|
||||
World world = this.getWorld();
|
||||
if (world == null) return null;
|
||||
|
||||
if (x == null) return null;
|
||||
if (y == null) return null;
|
||||
if (z == null) return null;
|
||||
|
||||
return world.getBlockAt(x, y, z);
|
||||
}
|
||||
|
||||
public synchronized Chunk getChunk()
|
||||
{
|
||||
return this.innerChunk(this.getChunkX(), this.getChunkZ());
|
||||
}
|
||||
public synchronized Chunk calcChunk()
|
||||
{
|
||||
return this.innerChunk(this.calcChunkX(), this.calcChunkZ());
|
||||
}
|
||||
protected synchronized Chunk innerChunk(Integer x, Integer z)
|
||||
{
|
||||
World world = this.getWorld();
|
||||
if (world == null) return null;
|
||||
|
||||
if (x == null) return null;
|
||||
if (z == null) return null;
|
||||
|
||||
return world.getChunkAt(x, z);
|
||||
}
|
||||
|
||||
public synchronized Vector getVelocity()
|
||||
{
|
||||
return this.innerVelocity(this.getVelocityX(), this.getVelocityY(), this.getVelocityZ());
|
||||
}
|
||||
public synchronized Vector calcVelocity()
|
||||
{
|
||||
return this.innerVelocity(this.calcVelocityX(), this.calcVelocityY(), this.calcVelocityZ());
|
||||
}
|
||||
protected synchronized Vector innerVelocity(Double x, Double y, Double z)
|
||||
{
|
||||
if (x == null) return null;
|
||||
if (y == null) return null;
|
||||
if (z == null) return null;
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// SET
|
||||
//----------------------------------------------//
|
||||
|
||||
public synchronized void setDefault()
|
||||
{
|
||||
this.worldName = null;
|
||||
|
||||
this.blockX = null;
|
||||
this.blockY = null;
|
||||
this.blockZ = null;
|
||||
|
||||
this.locationX = null;
|
||||
this.locationY = null;
|
||||
this.locationZ = null;
|
||||
|
||||
this.chunkX = null;
|
||||
this.chunkZ = null;
|
||||
|
||||
this.pitch = null;
|
||||
this.yaw = null;
|
||||
|
||||
this.velocityX = null;
|
||||
this.velocityY = null;
|
||||
this.velocityZ = null;
|
||||
}
|
||||
|
||||
public synchronized void setPSTransparent(PS ps)
|
||||
{
|
||||
if (ps.worldName != null) this.worldName = ps.worldName;
|
||||
|
||||
if (ps.blockX != null) this.blockX = ps.blockX;
|
||||
if (ps.blockY != null) this.blockY = ps.blockY;
|
||||
if (ps.blockZ != null) this.blockZ = ps.blockZ;
|
||||
|
||||
if (ps.locationX != null) this.locationX = ps.locationX;
|
||||
if (ps.locationY != null) this.locationY = ps.locationY;
|
||||
if (ps.locationZ != null) this.locationZ = ps.locationZ;
|
||||
|
||||
if (ps.chunkX != null) this.chunkX = ps.chunkX;
|
||||
if (ps.chunkZ != null) this.chunkZ = ps.chunkZ;
|
||||
|
||||
if (ps.pitch != null) this.pitch = ps.pitch;
|
||||
if (ps.yaw != null) this.yaw = ps.yaw;
|
||||
|
||||
if (ps.velocityX != null) this.velocityX = ps.velocityX;
|
||||
if (ps.velocityY != null) this.velocityY = ps.velocityY;
|
||||
if (ps.velocityZ != null) this.velocityZ = ps.velocityZ;
|
||||
}
|
||||
|
||||
public synchronized void setPS(PS ps)
|
||||
{
|
||||
this.worldName = ps.worldName;
|
||||
|
||||
this.blockX = ps.blockX;
|
||||
this.blockY = ps.blockY;
|
||||
this.blockZ = ps.blockZ;
|
||||
|
||||
this.locationX = ps.locationX;
|
||||
this.locationY = ps.locationY;
|
||||
this.locationZ = ps.locationZ;
|
||||
|
||||
this.chunkX = ps.chunkX;
|
||||
this.chunkZ = ps.chunkZ;
|
||||
|
||||
this.pitch = ps.pitch;
|
||||
this.yaw = ps.yaw;
|
||||
|
||||
this.velocityX = ps.velocityX;
|
||||
this.velocityY = ps.velocityY;
|
||||
this.velocityZ = ps.velocityZ;
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
public synchronized void setLocation(Location location)
|
||||
{
|
||||
this.setDefault();
|
||||
this.setLocationTransparent(location);
|
||||
}
|
||||
|
||||
public synchronized void setLocationTransparent(Location location)
|
||||
{
|
||||
this.worldName = location.getWorld().getName();
|
||||
this.locationX = location.getX();
|
||||
this.locationY = location.getY();
|
||||
this.locationZ = location.getZ();
|
||||
this.setPitch(location.getPitch());
|
||||
this.yaw = location.getYaw();
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
public synchronized void setVelocity(Vector vector)
|
||||
{
|
||||
this.setDefault();
|
||||
this.setVelocityTransparent(vector);
|
||||
}
|
||||
|
||||
public synchronized void setVelocityTransparent(Vector vector)
|
||||
{
|
||||
this.velocityX = vector.getX();
|
||||
this.velocityY = vector.getY();
|
||||
this.velocityZ = vector.getZ();
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
public synchronized void setEntity(Entity entity)
|
||||
{
|
||||
this.setDefault();
|
||||
this.setEntityTransparent(entity);
|
||||
}
|
||||
|
||||
public synchronized void setEntityTransparent(Entity entity)
|
||||
{
|
||||
this.setLocationTransparent(entity.getLocation());
|
||||
this.setVelocityTransparent(entity.getVelocity());
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
public synchronized void setBlock(Block block)
|
||||
{
|
||||
this.setDefault();
|
||||
this.setBlockTransparent(block);
|
||||
}
|
||||
|
||||
public synchronized void setBlockTransparent(Block block)
|
||||
{
|
||||
this.worldName = block.getWorld().getName();
|
||||
this.blockX = block.getX();
|
||||
this.blockY = block.getY();
|
||||
this.blockZ = block.getZ();
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
public synchronized void setChunk(Chunk chunk)
|
||||
{
|
||||
this.setDefault();
|
||||
this.setChunkTransparent(chunk);
|
||||
}
|
||||
|
||||
public synchronized void setChunkTransparent(Chunk chunk)
|
||||
{
|
||||
this.worldName = chunk.getWorld().getName();
|
||||
this.chunkX = chunk.getX();
|
||||
this.chunkZ = chunk.getZ();
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
|
||||
public synchronized void setOldString(String str)
|
||||
{
|
||||
this.setDefault();
|
||||
this.setOldStringTransparent(str);
|
||||
}
|
||||
|
||||
public synchronized void setOldStringTransparent(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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------//
|
||||
// WRITERS
|
||||
//----------------------------------------------//
|
||||
|
||||
public synchronized void write(Entity entity)
|
||||
{
|
||||
teleporter.teleport(entity, this);
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// CONSTRUCTORS
|
||||
//----------------------------------------------//
|
||||
|
||||
public PS()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public PS(PS ps)
|
||||
{
|
||||
this.setPS(ps);
|
||||
}
|
||||
|
||||
public PS(Location location)
|
||||
{
|
||||
this.setLocationTransparent(location);
|
||||
}
|
||||
|
||||
public PS(Vector velocity)
|
||||
{
|
||||
this.setVelocityTransparent(velocity);
|
||||
}
|
||||
|
||||
public PS(Entity entity)
|
||||
{
|
||||
this.setEntityTransparent(entity);
|
||||
}
|
||||
|
||||
public PS(Block block)
|
||||
{
|
||||
this.setBlockTransparent(block);
|
||||
}
|
||||
|
||||
public PS(Chunk chunk)
|
||||
{
|
||||
this.setChunkTransparent(chunk);
|
||||
}
|
||||
|
||||
public PS(String oldString)
|
||||
{
|
||||
this.setOldStringTransparent(oldString);
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// TO STRING
|
||||
//----------------------------------------------//
|
||||
|
||||
@Override
|
||||
public synchronized String toString()
|
||||
{
|
||||
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
|
||||
//----------------------------------------------//
|
||||
|
||||
@Override
|
||||
public PS clone()
|
||||
{
|
||||
return new PS(this);
|
||||
}
|
||||
|
||||
}
|
||||
8
src/com/massivecraft/mcore5/PSTeleporter.java
Normal file
8
src/com/massivecraft/mcore5/PSTeleporter.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public interface PSTeleporter
|
||||
{
|
||||
public void teleport(Entity entity, PS ps);
|
||||
}
|
||||
28
src/com/massivecraft/mcore5/PSTeleporterDefault.java
Normal file
28
src/com/massivecraft/mcore5/PSTeleporterDefault.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class PSTeleporterDefault implements PSTeleporter
|
||||
{
|
||||
@Override
|
||||
public void teleport(Entity entity, PS ps)
|
||||
{
|
||||
Location location = ps.calcLocation();
|
||||
if (location != null) entity.teleport(location);
|
||||
|
||||
Vector velocity = ps.getVelocity();
|
||||
if (velocity != null) entity.setVelocity(velocity);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected static PSTeleporterDefault instance = new PSTeleporterDefault();
|
||||
public static PSTeleporterDefault get()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
42
src/com/massivecraft/mcore5/Permission.java
Normal file
42
src/com/massivecraft/mcore5/Permission.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.massivecraft.mcore5.util.Perm;
|
||||
|
||||
public enum Permission
|
||||
{
|
||||
USYS("usys"),
|
||||
USYS_MULTIVERSE("usys.multiverse"),
|
||||
USYS_MULTIVERSE_LIST("usys.multiverse.list"),
|
||||
USYS_MULTIVERSE_SHOW("usys.multiverse.show"),
|
||||
USYS_MULTIVERSE_NEW("usys.multiverse.new"),
|
||||
USYS_MULTIVERSE_DEL("usys.multiverse.del"),
|
||||
USYS_UNIVERSE("usys.universe"),
|
||||
USYS_UNIVERSE_NEW("usys.universe.new"),
|
||||
USYS_UNIVERSE_DEL("usys.universe.del"),
|
||||
USYS_UNIVERSE_CLEAR("usys.universe.clear"),
|
||||
USYS_WORLD("usys.world"),
|
||||
USYS_ASPECT("usys.aspect"),
|
||||
USYS_ASPECT_LIST("usys.aspect.list"),
|
||||
USYS_ASPECT_SHOW("usys.aspect.show"),
|
||||
USYS_ASPECT_USE("usys.aspect.use"),
|
||||
;
|
||||
|
||||
public final String node;
|
||||
|
||||
Permission(final String permissionNode)
|
||||
{
|
||||
this.node = "mcore."+permissionNode;
|
||||
}
|
||||
|
||||
public boolean has(CommandSender sender, boolean informSenderIfNot)
|
||||
{
|
||||
return Perm.has(sender, this.node, informSenderIfNot);
|
||||
}
|
||||
|
||||
public boolean has(CommandSender sender)
|
||||
{
|
||||
return has(sender, false);
|
||||
}
|
||||
}
|
||||
6
src/com/massivecraft/mcore5/Predictate.java
Normal file
6
src/com/massivecraft/mcore5/Predictate.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
public interface Predictate<T>
|
||||
{
|
||||
public boolean apply(T type);
|
||||
}
|
||||
81
src/com/massivecraft/mcore5/SimpleConfig.java
Normal file
81
src/com/massivecraft/mcore5/SimpleConfig.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package com.massivecraft.mcore5;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.massivecraft.mcore5.store.accessor.Accessor;
|
||||
import com.massivecraft.mcore5.util.DiscUtil;
|
||||
|
||||
public class SimpleConfig
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
protected transient MPlugin mplugin;
|
||||
protected MPlugin getMplugin() { return this.mplugin; }
|
||||
|
||||
protected transient File file;
|
||||
protected File getFile() { return this.file; }
|
||||
|
||||
public SimpleConfig(MPlugin mplugin, File file)
|
||||
{
|
||||
this.mplugin = mplugin;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public SimpleConfig(MPlugin mplugin, String confname)
|
||||
{
|
||||
this(mplugin, new File(mplugin.getDataFolder(), confname+".json"));
|
||||
}
|
||||
|
||||
public SimpleConfig(MPlugin mplugin)
|
||||
{
|
||||
this(mplugin, "conf");
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IO
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected static boolean contentRequestsDefaults(String content)
|
||||
{
|
||||
if (content == null) return false;
|
||||
char c = content.charAt(0);
|
||||
return c == 'd' || c == 'D';
|
||||
}
|
||||
|
||||
public void load()
|
||||
{
|
||||
if (this.getFile().isFile())
|
||||
{
|
||||
String content = DiscUtil.readCatch(this.getFile());
|
||||
Object toShallowLoad = null;
|
||||
if (contentRequestsDefaults(content))
|
||||
{
|
||||
try
|
||||
{
|
||||
toShallowLoad = this.getClass().newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
toShallowLoad = this.getMplugin().gson.fromJson(content, this.getClass());
|
||||
}
|
||||
Accessor.get(this.getClass()).copy(toShallowLoad, this);
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
String content = DiscUtil.readCatch(this.getFile());
|
||||
if (contentRequestsDefaults(content)) return;
|
||||
content = this.getMplugin().gson.toJson(this);
|
||||
DiscUtil.writeCatch(file, content);
|
||||
}
|
||||
}
|
||||
|
||||
104
src/com/massivecraft/mcore5/adapter/InventoryAdapter.java
Normal file
104
src/com/massivecraft/mcore5/adapter/InventoryAdapter.java
Normal file
@@ -0,0 +1,104 @@
|
||||
package com.massivecraft.mcore5.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryCustom;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonElement;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonObject;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonParseException;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonPrimitive;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonSerializationContext;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonSerializer;
|
||||
|
||||
public class InventoryAdapter implements JsonDeserializer<Inventory>, JsonSerializer<Inventory>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELD NAME CONSTANTS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static final String SIZE = "size";
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Inventory src, Type typeOfSrc, JsonSerializationContext context)
|
||||
{
|
||||
return toJson(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
return fromJson(json);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// JSON
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static JsonElement toJson(Inventory src)
|
||||
{
|
||||
JsonObject jsonInventory = new JsonObject();
|
||||
ItemStack[] itemStacks = src.getContents();
|
||||
jsonInventory.add(SIZE, new JsonPrimitive(itemStacks.length));
|
||||
|
||||
for (int i = 0; i < itemStacks.length; i++)
|
||||
{
|
||||
ItemStack itemStack = itemStacks[i];
|
||||
JsonObject jsonItemStack = ItemStackAdapter.toJson(itemStack);
|
||||
if (jsonItemStack == null) continue;
|
||||
jsonInventory.add(String.valueOf(i), jsonItemStack);
|
||||
}
|
||||
|
||||
return jsonInventory;
|
||||
}
|
||||
|
||||
public static Inventory fromJson(JsonElement json)
|
||||
{
|
||||
if ( ! json.isJsonObject()) return null;
|
||||
JsonObject jsonInventory = json.getAsJsonObject();
|
||||
|
||||
if ( ! jsonInventory.has(SIZE)) return null;
|
||||
int size = jsonInventory.get(SIZE).getAsInt();
|
||||
|
||||
ItemStack[] itemStacks = new ItemStack[size];
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
// Fetch the jsonItemStack or mark it as empty and continue
|
||||
String stackIdx = String.valueOf(i);
|
||||
JsonElement jsonItemStack = jsonInventory.get(stackIdx);
|
||||
ItemStack itemStack = ItemStackAdapter.fromJson(jsonItemStack);
|
||||
itemStacks[i] = itemStack;
|
||||
}
|
||||
|
||||
Inventory ret = new CraftInventoryCustom(null, size, "items");
|
||||
ret.setContents(itemStacks);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// UTIL
|
||||
// -------------------------------------------- //
|
||||
|
||||
// This utility is nice to have in many cases :)
|
||||
public static boolean isInventoryEmpty(Inventory inv)
|
||||
{
|
||||
if (inv == null) return true;
|
||||
for (ItemStack stack : inv.getContents())
|
||||
{
|
||||
if (stack == null) continue;
|
||||
if (stack.getAmount() == 0) continue;
|
||||
if (stack.getTypeId() == 0) continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
171
src/com/massivecraft/mcore5/adapter/ItemStackAdapter.java
Normal file
171
src/com/massivecraft/mcore5/adapter/ItemStackAdapter.java
Normal file
@@ -0,0 +1,171 @@
|
||||
package com.massivecraft.mcore5.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.minecraft.server.NBTBase;
|
||||
import net.minecraft.server.NBTTagCompound;
|
||||
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonElement;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonObject;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonParseException;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonSerializationContext;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonSerializer;
|
||||
|
||||
public class ItemStackAdapter implements JsonDeserializer<ItemStack>, JsonSerializer<ItemStack>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELD NAME CONSTANTS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static final String TYPE = "type";
|
||||
public static final String AMOUNT = "amount";
|
||||
public static final String DAMAGE = "damage";
|
||||
public static final String ENCHANTMENTS = "enchantments";
|
||||
public static final String TAG = "tag";
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(ItemStack itemStack, Type typeOfSrc, JsonSerializationContext context)
|
||||
{
|
||||
return toJson(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
return fromJson(json);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// JSON
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static JsonObject toJson(ItemStack stack)
|
||||
{
|
||||
// Check for "nothing"
|
||||
if (stack == null || stack.getTypeId() == 0 || stack.getAmount() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
JsonObject jsonItemStack = new JsonObject();
|
||||
|
||||
// Add type id
|
||||
jsonItemStack.addProperty(TYPE, stack.getTypeId());
|
||||
|
||||
// Add amount
|
||||
if (stack.getAmount() != 1)
|
||||
{
|
||||
jsonItemStack.addProperty(AMOUNT, stack.getAmount());
|
||||
}
|
||||
|
||||
// Add damage
|
||||
if (stack.getDurability() != 0) // Durability is a weird name since it is the amount of damage.
|
||||
{
|
||||
jsonItemStack.addProperty(DAMAGE, stack.getDurability());
|
||||
}
|
||||
|
||||
// Add enchantments
|
||||
if (stack.getEnchantments().size() > 0)
|
||||
{
|
||||
JsonObject jsonEnchantments = new JsonObject();
|
||||
for (Entry<Enchantment, Integer> entry : stack.getEnchantments().entrySet())
|
||||
{
|
||||
jsonEnchantments.addProperty(String.valueOf(entry.getKey().getId()), entry.getValue());
|
||||
}
|
||||
jsonItemStack.add(ItemStackAdapter.ENCHANTMENTS, jsonEnchantments);
|
||||
}
|
||||
|
||||
// Add the tag if there is one
|
||||
JsonObject tag = getEnchFreeGsonTagFromItemStack(stack);
|
||||
if (tag != null)
|
||||
{
|
||||
jsonItemStack.add(TAG, tag);
|
||||
}
|
||||
|
||||
return jsonItemStack;
|
||||
}
|
||||
|
||||
// Used by method toJson
|
||||
public static JsonObject getEnchFreeGsonTagFromItemStack(ItemStack stack)
|
||||
{
|
||||
if (!(stack instanceof CraftItemStack)) return null;
|
||||
CraftItemStack craftItemStack = (CraftItemStack)stack;
|
||||
|
||||
NBTTagCompound nbt = craftItemStack.getHandle().tag;
|
||||
if (nbt == null) return null;
|
||||
|
||||
JsonObject gsonbt = (JsonObject) NbtGsonConverter.nbtToGsonVal(nbt);
|
||||
gsonbt.remove("ench");
|
||||
if (gsonbt.entrySet().size() == 0) return null;
|
||||
|
||||
return gsonbt;
|
||||
}
|
||||
|
||||
public static ItemStack fromJson(JsonElement json)
|
||||
{
|
||||
// Check for "nothing"
|
||||
if (json == null || ! json.isJsonObject()) return null;
|
||||
|
||||
JsonObject jsonItemStack = json.getAsJsonObject();
|
||||
|
||||
// Populate values
|
||||
int type = 0;
|
||||
int amount = 1;
|
||||
short damage = 0;
|
||||
|
||||
if (jsonItemStack.has(TYPE))
|
||||
{
|
||||
type = jsonItemStack.get(TYPE).getAsInt();
|
||||
}
|
||||
|
||||
if (jsonItemStack.has(AMOUNT))
|
||||
{
|
||||
amount = jsonItemStack.get(AMOUNT).getAsInt();
|
||||
}
|
||||
|
||||
if (jsonItemStack.has(DAMAGE))
|
||||
{
|
||||
damage = jsonItemStack.get(DAMAGE).getAsShort();
|
||||
}
|
||||
|
||||
// Create Non enchanted stack
|
||||
ItemStack stack = new ItemStack(type, amount, damage);
|
||||
|
||||
// Add tag
|
||||
if (jsonItemStack.has(TAG))
|
||||
{
|
||||
JsonObject jsonbt = jsonItemStack.get(TAG).getAsJsonObject();
|
||||
|
||||
CraftItemStack craftItemStack = new CraftItemStack(stack);
|
||||
stack = craftItemStack;
|
||||
|
||||
NBTBase nbt = NbtGsonConverter.gsonValToNbt(jsonbt, null, NBType.COMPOUND, NBType.UNKNOWN);
|
||||
craftItemStack.getHandle().tag = (NBTTagCompound) nbt;
|
||||
}
|
||||
|
||||
// Add enchantments if there are any
|
||||
if (jsonItemStack.has(ENCHANTMENTS))
|
||||
{
|
||||
JsonObject jsonEnchantments = jsonItemStack.get(ENCHANTMENTS).getAsJsonObject();
|
||||
for (Entry<String, JsonElement> enchantmentEntry: jsonEnchantments.entrySet())
|
||||
{
|
||||
int enchantmentId = Integer.valueOf(enchantmentEntry.getKey());
|
||||
Integer enchantmentLevel = Integer.valueOf(enchantmentEntry.getValue().getAsString());
|
||||
stack.addUnsafeEnchantment(Enchantment.getById(enchantmentId), enchantmentLevel);
|
||||
}
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
55
src/com/massivecraft/mcore5/adapter/MongoURIAdapter.java
Normal file
55
src/com/massivecraft/mcore5/adapter/MongoURIAdapter.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package com.massivecraft.mcore5.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonElement;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonParseException;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonPrimitive;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonSerializationContext;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonSerializer;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.MongoURI;
|
||||
|
||||
public class MongoURIAdapter implements JsonDeserializer<MongoURI>, JsonSerializer<MongoURI>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(MongoURI mongoURI, Type typeOfSrc, JsonSerializationContext context)
|
||||
{
|
||||
return serialize(mongoURI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoURI deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
return deserialize(json);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// 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 MongoURIAdapter instance = new MongoURIAdapter();
|
||||
public static MongoURIAdapter get()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
93
src/com/massivecraft/mcore5/adapter/NBType.java
Normal file
93
src/com/massivecraft/mcore5/adapter/NBType.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package com.massivecraft.mcore5.adapter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.server.NBTBase;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public enum NBType
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// VALUES
|
||||
// -------------------------------------------- //
|
||||
|
||||
END(0, "end"),
|
||||
BYTE(1, "byte"),
|
||||
SHORT(2, "short"),
|
||||
INT(3, "int"),
|
||||
LONG(4, "long"),
|
||||
FLOAT(5, "float"),
|
||||
DOUBLE(6, "double"),
|
||||
BYTEARRAY(7, "bytearray"),
|
||||
STRING(8, "string"),
|
||||
LIST(9, "list"),
|
||||
COMPOUND(10, "compound"),
|
||||
INTARRAY(11, "intarray"),
|
||||
UNKNOWN(-1, "unknown"),
|
||||
;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Getter final byte id;
|
||||
@Getter final String name;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
private NBType(int id, String name)
|
||||
{
|
||||
this.id = (byte)id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// STATIC UTILS
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected final static transient Map<String, NBType> tagnameToEnum = new HashMap<String, NBType>();
|
||||
protected final static transient Map<Byte, NBType> byteToEnum = new HashMap<Byte, NBType>();
|
||||
|
||||
static
|
||||
{
|
||||
for (NBType value : values())
|
||||
{
|
||||
tagnameToEnum.put(value.getName(), value);
|
||||
byteToEnum.put(value.getId(), value);
|
||||
}
|
||||
}
|
||||
|
||||
public static NBType getByName(String name)
|
||||
{
|
||||
NBType ret = tagnameToEnum.get(name);
|
||||
if (ret == null)
|
||||
{
|
||||
ret = UNKNOWN;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static NBType getById(byte id)
|
||||
{
|
||||
NBType ret = byteToEnum.get(id);
|
||||
if (ret == null)
|
||||
{
|
||||
ret = UNKNOWN;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static NBType getByTag(NBTBase tag)
|
||||
{
|
||||
NBType ret = byteToEnum.get(tag.getTypeId());
|
||||
if (ret == null)
|
||||
{
|
||||
ret = UNKNOWN;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
328
src/com/massivecraft/mcore5/adapter/NbtGsonConverter.java
Normal file
328
src/com/massivecraft/mcore5/adapter/NbtGsonConverter.java
Normal file
@@ -0,0 +1,328 @@
|
||||
package com.massivecraft.mcore5.adapter;
|
||||
|
||||
import net.minecraft.server.NBTBase;
|
||||
import net.minecraft.server.NBTTagByte;
|
||||
import net.minecraft.server.NBTTagByteArray;
|
||||
import net.minecraft.server.NBTTagCompound;
|
||||
import net.minecraft.server.NBTTagDouble;
|
||||
import net.minecraft.server.NBTTagEnd;
|
||||
import net.minecraft.server.NBTTagFloat;
|
||||
import net.minecraft.server.NBTTagInt;
|
||||
import net.minecraft.server.NBTTagIntArray;
|
||||
import net.minecraft.server.NBTTagList;
|
||||
import net.minecraft.server.NBTTagLong;
|
||||
import net.minecraft.server.NBTTagShort;
|
||||
import net.minecraft.server.NBTTagString;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonArray;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonElement;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonObject;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonPrimitive;
|
||||
|
||||
public class NbtGsonConverter
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// CONSTANTS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public final static String TYPE = "type";
|
||||
public final static String ELEMTYPE = "elemtype";
|
||||
public final static String VAL = "val";
|
||||
public final static String NAME = "name";
|
||||
|
||||
// -------------------------------------------- //
|
||||
// GSON TO NBT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static NBTBase gsonToNbt(JsonElement jsonElement)
|
||||
{
|
||||
return gsonToNbt(jsonElement, null);
|
||||
}
|
||||
|
||||
public static NBTBase gsonToNbt(JsonElement jsonElement, String name)
|
||||
{
|
||||
// Verify and cast the jsonElement into a jsonObject.
|
||||
// We could have used jsonObject as parameter type but this method signature is more flexible.
|
||||
if (!jsonElement.isJsonObject())
|
||||
{
|
||||
// must be a json object
|
||||
return null;
|
||||
}
|
||||
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
||||
|
||||
// Use the internal name if there is one
|
||||
JsonElement nameElement = jsonObject.get(NAME);
|
||||
if (nameElement != null)
|
||||
{
|
||||
name = nameElement.getAsString();
|
||||
}
|
||||
|
||||
// Fetch the type-info
|
||||
JsonElement typeElement = jsonObject.get(TYPE);
|
||||
if (typeElement == null)
|
||||
{
|
||||
// must have a type
|
||||
return null;
|
||||
}
|
||||
NBType type = NBType.getByName(typeElement.getAsString());
|
||||
|
||||
// Fetch the elemtype-info (used by NBTTagList only)
|
||||
NBType elemtype = NBType.UNKNOWN;
|
||||
if (type == NBType.LIST)
|
||||
{
|
||||
JsonElement elemtypeElement = jsonObject.get(ELEMTYPE);
|
||||
if (elemtypeElement == null)
|
||||
{
|
||||
// must have an elemtype
|
||||
return null;
|
||||
}
|
||||
elemtype = NBType.getByName(elemtypeElement.getAsString());
|
||||
}
|
||||
|
||||
// Fetch the value field
|
||||
JsonElement val = jsonObject.get(VAL);
|
||||
|
||||
// Convert the value based on the info we gathered
|
||||
return gsonValToNbt(val, name, type, elemtype);
|
||||
}
|
||||
|
||||
public static NBTBase gsonValToNbt(JsonElement val, String name, NBType type, NBType elemtype)
|
||||
{
|
||||
NBTBase ret = null;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case END:
|
||||
ret = new NBTTagEnd();
|
||||
break;
|
||||
|
||||
case BYTE:
|
||||
ret = new NBTTagByte(name, val.getAsByte());
|
||||
break;
|
||||
|
||||
case SHORT:
|
||||
ret = new NBTTagShort(name, val.getAsShort());
|
||||
break;
|
||||
|
||||
case INT:
|
||||
ret = new NBTTagInt(name, val.getAsInt());
|
||||
break;
|
||||
|
||||
case LONG:
|
||||
ret = new NBTTagLong(name, val.getAsLong());
|
||||
break;
|
||||
|
||||
case FLOAT:
|
||||
ret = new NBTTagFloat(name, val.getAsFloat());
|
||||
break;
|
||||
|
||||
case DOUBLE:
|
||||
ret = new NBTTagDouble(name, val.getAsDouble());
|
||||
break;
|
||||
|
||||
case BYTEARRAY:
|
||||
JsonArray jsonBytes = val.getAsJsonArray();
|
||||
int jsonBytesSize = jsonBytes.size();
|
||||
byte[] byteArray = new byte[jsonBytesSize];
|
||||
for (int index = 0 ; index < jsonBytesSize ; index++)
|
||||
{
|
||||
byte b = jsonBytes.get(index).getAsByte();
|
||||
byteArray[index] = b;
|
||||
}
|
||||
ret = new NBTTagByteArray(name, byteArray);
|
||||
break;
|
||||
|
||||
case INTARRAY:
|
||||
JsonArray jsonInts = val.getAsJsonArray();
|
||||
int jsonIntsSize = jsonInts.size();
|
||||
int[] intArray = new int[jsonIntsSize];
|
||||
for (int index = 0 ; index < jsonIntsSize ; index++)
|
||||
{
|
||||
int i = jsonInts.get(index).getAsInt();
|
||||
intArray[index] = i;
|
||||
}
|
||||
ret = new NBTTagIntArray(name, intArray);
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
ret = new NBTTagString(name, val.getAsString());
|
||||
break;
|
||||
|
||||
case LIST:
|
||||
NBTTagList nbtlist = new NBTTagList(name);
|
||||
|
||||
if (!val.isJsonArray())
|
||||
{
|
||||
// must be an array
|
||||
return null;
|
||||
}
|
||||
|
||||
Iterator<JsonElement> iter = val.getAsJsonArray().iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
nbtlist.add(gsonValToNbt(iter.next(), null, elemtype, NBType.UNKNOWN));
|
||||
}
|
||||
ret = nbtlist;
|
||||
break;
|
||||
|
||||
case COMPOUND:
|
||||
NBTTagCompound compound = new NBTTagCompound(name);
|
||||
|
||||
if (!val.isJsonObject())
|
||||
{
|
||||
// must be an object
|
||||
return null;
|
||||
}
|
||||
|
||||
JsonObject jsonCompound = val.getAsJsonObject();
|
||||
|
||||
for(Entry<String, JsonElement> entry : jsonCompound.entrySet())
|
||||
{
|
||||
String childName = entry.getKey();
|
||||
JsonElement childJson = entry.getValue();
|
||||
NBTBase child = gsonToNbt(childJson, childName);
|
||||
if (child == null) continue;
|
||||
compound.set(childName, child);
|
||||
}
|
||||
|
||||
ret = compound;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// NBT TO GSON
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static JsonObject nbtToGson(NBTBase nbt, boolean includeName)
|
||||
{
|
||||
JsonObject ret = new JsonObject();
|
||||
|
||||
String name = nbt.getName();
|
||||
if (includeName && name != null)
|
||||
{
|
||||
ret.addProperty(NAME, name);
|
||||
}
|
||||
|
||||
NBType type = NBType.getById(nbt.getTypeId());
|
||||
ret.addProperty(TYPE, type.getName());
|
||||
|
||||
if (type == NBType.LIST)
|
||||
{
|
||||
ret.addProperty(ELEMTYPE, NBType.getByTag(((NBTTagList)nbt).get(0)).getName());
|
||||
}
|
||||
|
||||
JsonElement val = nbtToGsonVal(nbt);
|
||||
if (val == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ret.add(VAL, val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static JsonElement nbtToGsonVal(NBTBase nbt)
|
||||
{
|
||||
JsonElement val = null;
|
||||
|
||||
NBType type = NBType.getByTag(nbt);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case END:
|
||||
// this should never happen
|
||||
break;
|
||||
|
||||
case BYTE:
|
||||
val = new JsonPrimitive(((NBTTagByte) nbt).data);
|
||||
break;
|
||||
|
||||
case SHORT:
|
||||
val = new JsonPrimitive(((NBTTagShort) nbt).data);
|
||||
break;
|
||||
|
||||
case INT:
|
||||
val = new JsonPrimitive(((NBTTagInt) nbt).data);
|
||||
break;
|
||||
|
||||
case LONG:
|
||||
val = new JsonPrimitive(((NBTTagLong) nbt).data);
|
||||
break;
|
||||
|
||||
case FLOAT:
|
||||
val = new JsonPrimitive(((NBTTagFloat) nbt).data);
|
||||
break;
|
||||
|
||||
case DOUBLE:
|
||||
val = new JsonPrimitive(((NBTTagDouble) nbt).data);
|
||||
break;
|
||||
|
||||
case BYTEARRAY:
|
||||
JsonArray jsonBytes = new JsonArray();
|
||||
for (byte elem : ((NBTTagByteArray) nbt).data)
|
||||
{
|
||||
jsonBytes.add(new JsonPrimitive(elem));
|
||||
}
|
||||
val = jsonBytes;
|
||||
break;
|
||||
|
||||
case INTARRAY:
|
||||
JsonArray jsonInts = new JsonArray();
|
||||
for (int elem : ((NBTTagIntArray) nbt).data)
|
||||
{
|
||||
jsonInts.add(new JsonPrimitive(elem));
|
||||
}
|
||||
val = jsonInts;
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
val = new JsonPrimitive(((NBTTagString) nbt).data);
|
||||
break;
|
||||
|
||||
case LIST:
|
||||
NBTTagList nbtlist = (NBTTagList)nbt;
|
||||
int size = nbtlist.size();
|
||||
if (size <= 0)
|
||||
{
|
||||
// NBTTagList may not be empty
|
||||
return null;
|
||||
}
|
||||
|
||||
JsonArray jsonElems = new JsonArray();
|
||||
for (int i = 0 ; i < size ; i++)
|
||||
{
|
||||
jsonElems.add(nbtToGsonVal(nbtlist.get(i)));
|
||||
}
|
||||
val = jsonElems;
|
||||
break;
|
||||
|
||||
case COMPOUND:
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
for (NBTBase child : getCompoundChildren((NBTTagCompound)nbt))
|
||||
{
|
||||
jsonObject.add(child.getName(), nbtToGson(child, false));
|
||||
}
|
||||
val = jsonObject;
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// UTILS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Collection<NBTBase> getCompoundChildren(NBTTagCompound compound)
|
||||
{
|
||||
return (Collection<NBTBase>)compound.c();
|
||||
}
|
||||
}
|
||||
53
src/com/massivecraft/mcore5/adapter/PSAdapter.java
Normal file
53
src/com/massivecraft/mcore5/adapter/PSAdapter.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.massivecraft.mcore5.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.massivecraft.mcore5.PS;
|
||||
import com.massivecraft.mcore5.xlib.gson.Gson;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonElement;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonParseException;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonPrimitive;
|
||||
import com.massivecraft.mcore5.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(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;
|
||||
}
|
||||
}
|
||||
28
src/com/massivecraft/mcore5/cmd/BukkitGlueCommand.java
Normal file
28
src/com/massivecraft/mcore5/cmd/BukkitGlueCommand.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.massivecraft.mcore5.cmd;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
|
||||
public class BukkitGlueCommand extends Command
|
||||
{
|
||||
protected MCommand mcommand;
|
||||
public BukkitGlueCommand(MCommand mcommand)
|
||||
{
|
||||
super(mcommand.getAliases().get(0), mcommand.getDesc(), mcommand.getUseageTemplate(), mcommand.getAliases());
|
||||
this.mcommand = mcommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String commandLabel, String[] args)
|
||||
{
|
||||
if ( ! mcommand.p().isEnabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this.mcommand.execute(sender, Txt.tokenizeArguments(Txt.implode(args, " ")));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
58
src/com/massivecraft/mcore5/cmd/HelpCommand.java
Normal file
58
src/com/massivecraft/mcore5/cmd/HelpCommand.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.massivecraft.mcore5.cmd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.massivecraft.mcore5.MPlugin;
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.cmd.arg.ARInteger;
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
|
||||
public class HelpCommand extends MCommand
|
||||
{
|
||||
private HelpCommand()
|
||||
{
|
||||
super();
|
||||
this.addAliases("?", "h", "help");
|
||||
this.setDesc("");
|
||||
this.addOptionalArg("page","1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform()
|
||||
{
|
||||
if (this.commandChain.size() == 0) return;
|
||||
MCommand parentCommand = this.commandChain.get(this.commandChain.size()-1);
|
||||
|
||||
ArrayList<String> lines = new ArrayList<String>();
|
||||
|
||||
for (String helpline : parentCommand.getHelp())
|
||||
{
|
||||
lines.add(Txt.parse("<a>#<i> "+helpline));
|
||||
}
|
||||
|
||||
for(MCommand subCommand : parentCommand.getSubCommands())
|
||||
{
|
||||
if (subCommand.visibleTo(sender))
|
||||
{
|
||||
lines.add(subCommand.getUseageTemplate(this.commandChain, true, true));
|
||||
}
|
||||
}
|
||||
|
||||
Integer pagenumber = this.arg(0, ARInteger.get(), 1);
|
||||
if (pagenumber == null) return;
|
||||
sendMessage(Txt.getPage(lines, pagenumber, "Help for command \""+parentCommand.getAliases().get(0)+"\""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MPlugin p()
|
||||
{
|
||||
if (this.commandChain.size() == 0) return null;
|
||||
return this.commandChain.get(this.commandChain.size()-1).p();
|
||||
}
|
||||
|
||||
private static HelpCommand instance = new HelpCommand();
|
||||
public static HelpCommand getInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
520
src/com/massivecraft/mcore5/cmd/MCommand.java
Normal file
520
src/com/massivecraft/mcore5/cmd/MCommand.java
Normal file
@@ -0,0 +1,520 @@
|
||||
package com.massivecraft.mcore5.cmd;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.SimpleCommandMap;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.massivecraft.mcore5.Lang;
|
||||
import com.massivecraft.mcore5.MPlugin;
|
||||
import com.massivecraft.mcore5.cmd.arg.ArgReader;
|
||||
import com.massivecraft.mcore5.cmd.arg.ArgResult;
|
||||
import com.massivecraft.mcore5.cmd.req.IReq;
|
||||
import com.massivecraft.mcore5.cmd.req.ReqHasPerm;
|
||||
import com.massivecraft.mcore5.util.BukkitCommandUtil;
|
||||
import com.massivecraft.mcore5.util.Perm;
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
|
||||
public abstract class MCommand
|
||||
{
|
||||
public abstract MPlugin p();
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COMMAND BEHAVIOR
|
||||
// -------------------------------------------- //
|
||||
|
||||
// FIELD: subCommands
|
||||
// The sub-commands to this command
|
||||
@Getter @Setter protected List<MCommand> subCommands;
|
||||
public void addSubCommand(MCommand subCommand)
|
||||
{
|
||||
subCommand.commandChain.addAll(this.commandChain);
|
||||
subCommand.commandChain.add(this);
|
||||
this.subCommands.add(subCommand);
|
||||
}
|
||||
|
||||
// FIELD: aliases
|
||||
// The different names this commands will react to
|
||||
@Getter @Setter protected List<String> aliases;
|
||||
public void addAliases(String... aliases) { this.aliases.addAll(Arrays.asList(aliases)); }
|
||||
public void addAliases(List<String> aliases) { this.aliases.addAll(aliases); }
|
||||
|
||||
// FIELD: requiredArgs
|
||||
// These args must always be sent
|
||||
@Getter @Setter protected List<String> requiredArgs;
|
||||
public void addRequiredArg(String arg) { this.requiredArgs.add(arg); }
|
||||
|
||||
// FIELD: optionalArgs
|
||||
// These args are optional
|
||||
@Getter @Setter protected Map<String, String> optionalArgs;
|
||||
public void addOptionalArg(String arg, String def) { this.optionalArgs.put(arg, def); }
|
||||
|
||||
// FIELD: errorOnToManyArgs
|
||||
// Should an error be thrown if "to many" args are sent.
|
||||
protected boolean errorOnToManyArgs;
|
||||
public boolean getErrorOnToManyArgs() { return this.errorOnToManyArgs; }
|
||||
public void setErrorOnToManyArgs(boolean val) { this.errorOnToManyArgs = val; }
|
||||
|
||||
// FIELD: requirements
|
||||
// All these requirements must be met for the command to be executable;
|
||||
@Getter @Setter protected List<IReq> requirements;
|
||||
public void addRequirements(IReq... requirements) { this.requirements.addAll(Arrays.asList(requirements)); }
|
||||
|
||||
// FIELD: desc
|
||||
// This field may be left blank and will in such case be loaded from the permissions node instead.
|
||||
// Thus make sure the permissions node description is an action description like "eat hamburgers" or "do admin stuff".
|
||||
@Setter protected String desc = null;
|
||||
public String getDesc()
|
||||
{
|
||||
if (this.desc != null) return this.desc;
|
||||
|
||||
String perm = this.getDescPermission();
|
||||
if (perm != null)
|
||||
{
|
||||
String pdesc = Perm.getPermissionDescription(this.getDescPermission());
|
||||
if (pdesc != null)
|
||||
{
|
||||
return pdesc;
|
||||
}
|
||||
}
|
||||
|
||||
return "*info unavailable*";
|
||||
}
|
||||
|
||||
// FIELD: descPermission
|
||||
// This permission node IS NOT TESTED AT ALL. It is rather used in the method above.
|
||||
@Setter protected String descPermission;
|
||||
public String getDescPermission()
|
||||
{
|
||||
if (this.descPermission != null) return this.descPermission;
|
||||
// Otherwise we try to find one.
|
||||
for (IReq req : this.requirements)
|
||||
{
|
||||
if ( ! (req instanceof ReqHasPerm)) continue;
|
||||
return ((ReqHasPerm)req).getPerm();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// FIELD: help
|
||||
// This is a multi-line help text for the command.
|
||||
protected List<String> help = new ArrayList<String>();
|
||||
public void setHelp(List<String> val) { this.help = val; }
|
||||
public void setHelp(String... val) { this.help = Arrays.asList(val); }
|
||||
public List<String> getHelp() { return this.help; }
|
||||
|
||||
// FIELD: visibilityMode
|
||||
@Getter @Setter protected VisibilityMode visibilityMode;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// EXECUTION INFO
|
||||
// -------------------------------------------- //
|
||||
|
||||
// FIELD: args
|
||||
// Will contain the arguments, or and empty list if there are none.
|
||||
@Getter @Setter protected List<String> args;
|
||||
|
||||
// FIELD: commandChain
|
||||
// The command chain used to execute this command
|
||||
@Getter @Setter protected List<MCommand> commandChain = new ArrayList<MCommand>();
|
||||
|
||||
// FIELDS: sender, me, senderIsConsole
|
||||
public CommandSender sender;
|
||||
public Player me;
|
||||
public boolean senderIsConsole;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// BUKKIT INTEGRATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
public boolean register()
|
||||
{
|
||||
return register(false);
|
||||
}
|
||||
|
||||
public boolean register(boolean override)
|
||||
{
|
||||
BukkitGlueCommand bgc = new BukkitGlueCommand(this);
|
||||
SimpleCommandMap scm = BukkitCommandUtil.getBukkitCommandMap();
|
||||
|
||||
if (override)
|
||||
{
|
||||
// Our commands are more important than your commands :P
|
||||
Map<String, Command> knownCommands = BukkitCommandUtil.getKnownCommandsFromSimpleCommandMap(scm);
|
||||
String lowerLabel = bgc.getName().trim().toLowerCase();
|
||||
knownCommands.remove(lowerLabel);
|
||||
}
|
||||
|
||||
return scm.register("mcore", bgc);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCTORS AND EXECUTOR
|
||||
// -------------------------------------------- //
|
||||
|
||||
public MCommand()
|
||||
{
|
||||
this.descPermission = null;
|
||||
|
||||
this.subCommands = new ArrayList<MCommand>();
|
||||
this.aliases = new ArrayList<String>();
|
||||
|
||||
this.requiredArgs = new ArrayList<String>();
|
||||
this.optionalArgs = new LinkedHashMap<String, String>();
|
||||
|
||||
this.requirements = new ArrayList<IReq>();
|
||||
|
||||
this.errorOnToManyArgs = true;
|
||||
|
||||
this.desc = null;
|
||||
|
||||
this.visibilityMode = VisibilityMode.VISIBLE;
|
||||
}
|
||||
|
||||
// The commandChain is a list of the parent command chain used to get to this command.
|
||||
public void execute(CommandSender sender, List<String> args, List<MCommand> commandChain)
|
||||
{
|
||||
// Set the execution-time specific variables
|
||||
this.sender = sender;
|
||||
this.senderIsConsole = true;
|
||||
this.me = null;
|
||||
if (sender instanceof Player)
|
||||
{
|
||||
this.me = (Player) sender;
|
||||
this.senderIsConsole = false;
|
||||
}
|
||||
|
||||
this.fixSenderVars();
|
||||
|
||||
this.args = args;
|
||||
this.commandChain = commandChain;
|
||||
|
||||
// Is there a matching sub command?
|
||||
if (args.size() > 0 )
|
||||
{
|
||||
for (MCommand subCommand: this.subCommands)
|
||||
{
|
||||
if (subCommand.aliases.contains(args.get(0)))
|
||||
{
|
||||
args.remove(0);
|
||||
commandChain.add(this);
|
||||
subCommand.execute(sender, args, commandChain);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! validCall(this.sender, this.args)) return;
|
||||
|
||||
perform();
|
||||
}
|
||||
|
||||
public void fixSenderVars() {};
|
||||
|
||||
public void execute(CommandSender sender, List<String> args)
|
||||
{
|
||||
execute(sender, args, new ArrayList<MCommand>());
|
||||
}
|
||||
|
||||
// This is where the command action is performed.
|
||||
public abstract void perform();
|
||||
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Call Validation
|
||||
// -------------------------------------------- //
|
||||
|
||||
/**
|
||||
* In this method we validate that all prerequisites to perform this command has been met.
|
||||
*/
|
||||
public boolean validCall(CommandSender sender, List<String> args)
|
||||
{
|
||||
if ( ! this.requirementsAreMet(sender, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! this.validArgs(args, sender))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visibleTo(CommandSender sender)
|
||||
{
|
||||
if (this.getVisibilityMode() == VisibilityMode.VISIBLE) return true;
|
||||
if (this.getVisibilityMode() == VisibilityMode.INVISIBLE) return false;
|
||||
return this.requirementsAreMet(sender, false);
|
||||
}
|
||||
|
||||
public boolean requirementsAreMet(CommandSender sender, boolean informSenderIfNot)
|
||||
{
|
||||
for (IReq req : this.getRequirements())
|
||||
{
|
||||
if ( ! req.test(sender, this))
|
||||
{
|
||||
if (informSenderIfNot)
|
||||
{
|
||||
this.msg(req.createErrorMessage(sender, this));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean validArgs(List<String> args, CommandSender sender)
|
||||
{
|
||||
if (args.size() < this.requiredArgs.size())
|
||||
{
|
||||
if (sender != null)
|
||||
{
|
||||
msg(Lang.commandToFewArgs);
|
||||
sender.sendMessage(this.getUseageTemplate());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.size() > this.requiredArgs.size() + this.optionalArgs.size() && this.errorOnToManyArgs)
|
||||
{
|
||||
if (sender != null)
|
||||
{
|
||||
// Get the to many string slice
|
||||
List<String> theToMany = args.subList(this.requiredArgs.size() + this.optionalArgs.size(), args.size());
|
||||
msg(Lang.commandToManyArgs, Txt.implodeCommaAndDot(theToMany, Txt.parse("<aqua>%s"), Txt.parse("<b>, "), Txt.parse("<b> and "), ""));
|
||||
msg(Lang.commandToManyArgs2);
|
||||
sender.sendMessage(this.getUseageTemplate());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public boolean validArgs(List<String> args)
|
||||
{
|
||||
return this.validArgs(args, null);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Help and Usage information
|
||||
// -------------------------------------------- //
|
||||
|
||||
public String getUseageTemplate(List<MCommand> commandChain, boolean addDesc, boolean onlyFirstAlias)
|
||||
{
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ret.append(Txt.parse("<c>"));
|
||||
ret.append('/');
|
||||
|
||||
boolean first = true;
|
||||
for (MCommand mc : commandChain)
|
||||
{
|
||||
if (first && onlyFirstAlias)
|
||||
{
|
||||
ret.append(mc.aliases.get(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.append(Txt.implode(mc.aliases, ","));
|
||||
}
|
||||
ret.append(' ');
|
||||
first = false;
|
||||
}
|
||||
|
||||
ret.append(Txt.implode(this.aliases, ","));
|
||||
|
||||
List<String> args = new ArrayList<String>();
|
||||
|
||||
for (String requiredArg : this.requiredArgs)
|
||||
{
|
||||
args.add("<"+requiredArg+">");
|
||||
}
|
||||
|
||||
for (Entry<String, String> optionalArg : this.optionalArgs.entrySet())
|
||||
{
|
||||
String val = optionalArg.getValue();
|
||||
if (val == null)
|
||||
{
|
||||
val = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
val = "="+val;
|
||||
}
|
||||
args.add("["+optionalArg.getKey()+val+"]");
|
||||
}
|
||||
|
||||
if (args.size() > 0)
|
||||
{
|
||||
ret.append(Txt.parse("<p>"));
|
||||
ret.append(' ');
|
||||
ret.append(Txt.implode(args, " "));
|
||||
}
|
||||
|
||||
if (addDesc)
|
||||
{
|
||||
ret.append(' ');
|
||||
ret.append(Txt.parse("<i>"));
|
||||
ret.append(this.getDesc());
|
||||
}
|
||||
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
public String getUseageTemplate(List<MCommand> commandChain, boolean addDesc)
|
||||
{
|
||||
return getUseageTemplate(commandChain, addDesc, false);
|
||||
}
|
||||
|
||||
public String getUseageTemplate(boolean addDesc)
|
||||
{
|
||||
return getUseageTemplate(this.commandChain, addDesc);
|
||||
}
|
||||
|
||||
public String getUseageTemplate()
|
||||
{
|
||||
return getUseageTemplate(false);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Message Sending Helpers
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void msg(String str, Object... args)
|
||||
{
|
||||
sender.sendMessage(Txt.parse(str, args));
|
||||
}
|
||||
|
||||
public void msg(String str)
|
||||
{
|
||||
sender.sendMessage(Txt.parse(str));
|
||||
}
|
||||
|
||||
public void msg(Collection<String> msgs)
|
||||
{
|
||||
for(String msg : msgs)
|
||||
{
|
||||
this.msg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(String msg)
|
||||
{
|
||||
sender.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void sendMessage(Collection<String> msgs)
|
||||
{
|
||||
for(String msg : msgs)
|
||||
{
|
||||
this.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Argument Readers
|
||||
// -------------------------------------------- //
|
||||
|
||||
public String argConcatFrom(int idx)
|
||||
{
|
||||
if ( ! this.argIsSet(idx)) return null;
|
||||
int from = idx;
|
||||
int to = args.size();
|
||||
if (to <= from) return "";
|
||||
return Txt.implode(this.args.subList(from, to), " ");
|
||||
}
|
||||
|
||||
public boolean argIsSet(int idx)
|
||||
{
|
||||
if (this.args.size() < idx+1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String arg(int idx)
|
||||
{
|
||||
if ( ! this.argIsSet(idx)) return null;
|
||||
return this.args.get(idx);
|
||||
}
|
||||
|
||||
public <T> T arg(int idx, ArgReader<T> ar)
|
||||
{
|
||||
return this.arg(idx, ar, null);
|
||||
}
|
||||
|
||||
public <T> T arg(int idx, ArgReader<T> argReader, T defaultNotSet)
|
||||
{
|
||||
String str = this.arg(idx);
|
||||
if (str == null) return defaultNotSet;
|
||||
ArgResult<T> result = argReader.read(str, this);
|
||||
if (result.hasErrors()) this.msg(result.getErrors());
|
||||
return result.getResult();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Argument Readers DEPRACATED TODO
|
||||
// -------------------------------------------- //
|
||||
|
||||
/*@Deprecated
|
||||
public synchronized <T> T argAs(int idx, Class<T> clazz, String style, T defaultNotSet, T defaultNotFound)
|
||||
{
|
||||
if ( ! this.argIsSet(idx))
|
||||
{
|
||||
return defaultNotSet;
|
||||
}
|
||||
IArgHandler<T> handler = p().cmd.getArgHandler(clazz);
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
p().log(Level.SEVERE, "There is no ArgHandler for " + clazz.getName());
|
||||
}
|
||||
|
||||
T ret = handler.parse(this.arg(idx), style, this.sender, p());
|
||||
if (ret == null)
|
||||
{
|
||||
this.msg(handler.getErrors());
|
||||
return defaultNotFound;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public <T> T argAs(int idx, Class<T> clazz, T defaultNotSet, T defaultNotFound)
|
||||
{
|
||||
return this.argAs(idx, clazz, null, defaultNotSet, defaultNotFound);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public <T> T argAs(int idx, Class<T> clazz, String style, T defaultNotSet)
|
||||
{
|
||||
return this.argAs(idx, clazz, style, defaultNotSet, null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public <T> T argAs(int idx, Class<T> clazz, T defaultNotSet)
|
||||
{
|
||||
return this.argAs(idx, clazz, null, defaultNotSet, null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public <T> T argAs(int idx, Class<T> clazz, String style)
|
||||
{
|
||||
return this.argAs(idx, clazz, style, null, null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public <T> T argAs(int idx, Class<T> clazz)
|
||||
{
|
||||
return this.argAs(idx, clazz, (T)null, null);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
9
src/com/massivecraft/mcore5/cmd/VisibilityMode.java
Normal file
9
src/com/massivecraft/mcore5/cmd/VisibilityMode.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package com.massivecraft.mcore5.cmd;
|
||||
|
||||
public enum VisibilityMode
|
||||
{
|
||||
VISIBLE, // Visible commands are visible to anyone. Even those who don't have permission to use it or is of invalid sender type.
|
||||
SECRET, // Secret commands are visible only to those who can use the command. These commands are usually some kind of admin commands.
|
||||
INVISIBLE, // Invisible commands are invisible to everyone, even those who can use the command.
|
||||
;
|
||||
}
|
||||
26
src/com/massivecraft/mcore5/cmd/arg/ARAbstractPrimitive.java
Normal file
26
src/com/massivecraft/mcore5/cmd/arg/ARAbstractPrimitive.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
|
||||
public abstract class ARAbstractPrimitive<T> implements ArgReader<T>
|
||||
{
|
||||
public abstract String typename();
|
||||
public abstract T convert(String str) throws Exception;
|
||||
|
||||
@Override
|
||||
public ArgResult<T> read(String str, MCommand mcommand)
|
||||
{
|
||||
ArgResult<T> result = new ArgResult<T>();
|
||||
|
||||
try
|
||||
{
|
||||
result.setResult(this.convert(str));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.getErrors().add("<b>Invalid "+this.typename()+" \"<h>"+str+"\"<b>.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
39
src/com/massivecraft/mcore5/cmd/arg/ARAbstractSelect.java
Normal file
39
src/com/massivecraft/mcore5/cmd/arg/ARAbstractSelect.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
|
||||
public abstract class ARAbstractSelect<T> implements ArgReader<T>
|
||||
{
|
||||
public abstract String typename();
|
||||
public abstract T select(String str, MCommand mcommand);
|
||||
public abstract Collection<String> altNames(MCommand mcommand);
|
||||
public boolean canList(MCommand mcommand) { return true; }
|
||||
|
||||
@Override
|
||||
public ArgResult<T> read(String str, MCommand mcommand)
|
||||
{
|
||||
ArgResult<T> result = new ArgResult<T>(this.select(str, mcommand));
|
||||
|
||||
if (!result.hasResult())
|
||||
{
|
||||
result.getErrors().add("<b>No "+this.typename()+" matches \"<h>"+str+"<b>\".");
|
||||
if (this.canList(mcommand))
|
||||
{
|
||||
Collection<String> names = this.altNames(mcommand);
|
||||
if (names.size() == 0)
|
||||
{
|
||||
result.getErrors().add("<i>Note: There is no "+this.typename()+" available.");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.getErrors().add("<i>Use "+Txt.implodeCommaAndDot(names, "<h>%s", "<i>, ", " <i>or ", "<i>."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
|
||||
public abstract class ARAbstractStringMatch implements ArgReader<String>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public ArgResult<String> read(String str, MCommand mcommand)
|
||||
{
|
||||
ArgResult<String> result = new ArgResult<String>();
|
||||
|
||||
// Find all matches
|
||||
Set<String> matches = new HashSet<String>();
|
||||
String perfectMatch = null;
|
||||
|
||||
outerloop:
|
||||
for (Collection<String> altColl : this.altColls())
|
||||
{
|
||||
for (String alt : altColl)
|
||||
{
|
||||
Integer matchDistance = this.matches(str, alt);
|
||||
if (matchDistance == null) continue;
|
||||
if (matchDistance == 0)
|
||||
{
|
||||
perfectMatch = alt;
|
||||
break outerloop;
|
||||
}
|
||||
else
|
||||
{
|
||||
matches.add(alt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set result and errors
|
||||
if (perfectMatch != null)
|
||||
{
|
||||
result.setResult(perfectMatch);
|
||||
}
|
||||
else if (matches.size() == 1)
|
||||
{
|
||||
result.setResult(matches.iterator().next());
|
||||
}
|
||||
else if (matches.size() > 1)
|
||||
{
|
||||
result.getErrors().add("<b>"+Txt.upperCaseFirst(this.typename())+" matching \"<h>"+str+"<b>\" is ambigious.");
|
||||
result.getErrors().add("<b>Did you mean "+Txt.implodeCommaAndDot(matches, "<h>%s", "<b>, ", " <b>or ", "<b>?"));
|
||||
}
|
||||
else if (matches.size() == 0)
|
||||
{
|
||||
result.getErrors().add("<b>No "+this.typename()+" matching \"<h>"+str+"<b>\".");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ABSTRACT
|
||||
// -------------------------------------------- //
|
||||
|
||||
// return null if no match
|
||||
// return 0 if perfect match
|
||||
// return >0 to declare distance from perfect match
|
||||
public abstract Integer matches(String arg, String alt);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected String typename;
|
||||
public String typename() { return this.typename; }
|
||||
|
||||
protected Collection<Collection<String>> altColls;
|
||||
public Collection<Collection<String>> altColls() { return this.altColls; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public ARAbstractStringMatch(String typename, Collection<Collection<String>> altColls)
|
||||
{
|
||||
this.typename = typename;
|
||||
this.altColls = altColls;
|
||||
}
|
||||
}
|
||||
43
src/com/massivecraft/mcore5/cmd/arg/ARAspect.java
Normal file
43
src/com/massivecraft/mcore5/cmd/arg/ARAspect.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.massivecraft.mcore5.Permission;
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.usys.Aspect;
|
||||
import com.massivecraft.mcore5.usys.AspectColl;
|
||||
|
||||
public class ARAspect extends ARAbstractSelect<Aspect>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "aspect";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Aspect select(String str, MCommand mcommand)
|
||||
{
|
||||
return AspectColl.i.get(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canList(MCommand mcommand)
|
||||
{
|
||||
return Permission.USYS_ASPECT_LIST.has(mcommand.sender, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> altNames(MCommand mcommand)
|
||||
{
|
||||
return AspectColl.i.getIds();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARAspect i = new ARAspect();
|
||||
public static ARAspect get() { return i; }
|
||||
|
||||
}
|
||||
29
src/com/massivecraft/mcore5/cmd/arg/ARBoolean.java
Normal file
29
src/com/massivecraft/mcore5/cmd/arg/ARBoolean.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
public class ARBoolean extends ARAbstractPrimitive<Boolean>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "boolean";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean convert(String str) throws Exception
|
||||
{
|
||||
str = str.toLowerCase();
|
||||
if (str.startsWith("y") || str.startsWith("t") || str.startsWith("on") || str.startsWith("+") || str.startsWith("1"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARBoolean i = new ARBoolean();
|
||||
public static ARBoolean get() { return i; }
|
||||
|
||||
}
|
||||
24
src/com/massivecraft/mcore5/cmd/arg/ARByte.java
Normal file
24
src/com/massivecraft/mcore5/cmd/arg/ARByte.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
public class ARByte extends ARAbstractPrimitive<Byte>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "byte";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte convert(String str) throws Exception
|
||||
{
|
||||
return Byte.parseByte(str);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARByte i = new ARByte();
|
||||
public static ARByte get() { return i; }
|
||||
|
||||
}
|
||||
30
src/com/massivecraft/mcore5/cmd/arg/ARDate.java
Normal file
30
src/com/massivecraft/mcore5/cmd/arg/ARDate.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class ARDate extends ARAbstractPrimitive<Date>
|
||||
{
|
||||
protected static DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "YYYY-MM-DD date";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date convert(String str) throws Exception
|
||||
{
|
||||
return df.parse(str);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARDate i = new ARDate();
|
||||
public static ARDate get() { return i; }
|
||||
|
||||
}
|
||||
24
src/com/massivecraft/mcore5/cmd/arg/ARDouble.java
Normal file
24
src/com/massivecraft/mcore5/cmd/arg/ARDouble.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
public class ARDouble extends ARAbstractPrimitive<Double>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double convert(String str) throws Exception
|
||||
{
|
||||
return Double.parseDouble(str);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARDouble i = new ARDouble();
|
||||
public static ARDouble get() { return i; }
|
||||
|
||||
}
|
||||
60
src/com/massivecraft/mcore5/cmd/arg/AREnvironment.java
Normal file
60
src/com/massivecraft/mcore5/cmd/arg/AREnvironment.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.World.Environment;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.util.MUtil;
|
||||
|
||||
public class AREnvironment extends ARAbstractSelect<Environment>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "environment";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Environment select(String str, MCommand mcommand)
|
||||
{
|
||||
Environment ret = null;
|
||||
|
||||
// "THE_END" --> "end"
|
||||
str = str.toLowerCase();
|
||||
str = str.replace("_", "");
|
||||
str = str.replace("the", "");
|
||||
|
||||
if (str.startsWith("no") || str.startsWith("d"))
|
||||
{
|
||||
// "normal" or "default"
|
||||
ret = Environment.NORMAL;
|
||||
}
|
||||
else if (str.startsWith("ne"))
|
||||
{
|
||||
// "nether"
|
||||
ret = Environment.NETHER;
|
||||
}
|
||||
else if (str.startsWith("e"))
|
||||
{
|
||||
// "end"
|
||||
ret = Environment.THE_END;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> altNames(MCommand mcommand)
|
||||
{
|
||||
return MUtil.list("normal", "end", "nether");
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static AREnvironment i = new AREnvironment();
|
||||
public static AREnvironment get() { return i; }
|
||||
|
||||
}
|
||||
24
src/com/massivecraft/mcore5/cmd/arg/ARFloat.java
Normal file
24
src/com/massivecraft/mcore5/cmd/arg/ARFloat.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
public class ARFloat extends ARAbstractPrimitive<Float>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "integer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float convert(String str) throws Exception
|
||||
{
|
||||
return Float.parseFloat(str);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARFloat i = new ARFloat();
|
||||
public static ARFloat get() { return i; }
|
||||
|
||||
}
|
||||
24
src/com/massivecraft/mcore5/cmd/arg/ARInteger.java
Normal file
24
src/com/massivecraft/mcore5/cmd/arg/ARInteger.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
public class ARInteger extends ARAbstractPrimitive<Integer>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "integer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer convert(String str) throws Exception
|
||||
{
|
||||
return Integer.parseInt(str);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARInteger i = new ARInteger();
|
||||
public static ARInteger get() { return i; }
|
||||
|
||||
}
|
||||
24
src/com/massivecraft/mcore5/cmd/arg/ARLong.java
Normal file
24
src/com/massivecraft/mcore5/cmd/arg/ARLong.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
public class ARLong extends ARAbstractPrimitive<Long>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "long";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long convert(String str) throws Exception
|
||||
{
|
||||
return Long.parseLong(str);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARLong i = new ARLong();
|
||||
public static ARLong get() { return i; }
|
||||
|
||||
}
|
||||
28
src/com/massivecraft/mcore5/cmd/arg/ARMaterial.java
Normal file
28
src/com/massivecraft/mcore5/cmd/arg/ARMaterial.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
|
||||
public class ARMaterial implements ArgReader<Material>
|
||||
{
|
||||
@Override
|
||||
public ArgResult<Material> read(String str, MCommand mcommand)
|
||||
{
|
||||
ArgResult<Material> result = new ArgResult<Material>(Material.matchMaterial(str));
|
||||
if (!result.hasResult())
|
||||
{
|
||||
result.getErrors().add("<b>No material matches <h>"+str+"<b>.");
|
||||
result.getErrors().add("<i>Suggestion: <aqua>http://www.minecraftwiki.net/wiki/Data_values");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARMaterial i = new ARMaterial();
|
||||
public static ARMaterial get() { return i; }
|
||||
|
||||
}
|
||||
43
src/com/massivecraft/mcore5/cmd/arg/ARMultiverse.java
Normal file
43
src/com/massivecraft/mcore5/cmd/arg/ARMultiverse.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.massivecraft.mcore5.Permission;
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.usys.Multiverse;
|
||||
import com.massivecraft.mcore5.usys.MultiverseColl;
|
||||
|
||||
public class ARMultiverse extends ARAbstractSelect<Multiverse>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "multiverse";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multiverse select(String str, MCommand mcommand)
|
||||
{
|
||||
return MultiverseColl.i.get(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canList(MCommand mcommand)
|
||||
{
|
||||
return Permission.USYS_MULTIVERSE_LIST.has(mcommand.sender, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> altNames(MCommand mcommand)
|
||||
{
|
||||
return MultiverseColl.i.getIds();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARMultiverse i = new ARMultiverse();
|
||||
public static ARMultiverse get() { return i; }
|
||||
|
||||
}
|
||||
32
src/com/massivecraft/mcore5/cmd/arg/AROnlinePlayerExact.java
Normal file
32
src/com/massivecraft/mcore5/cmd/arg/AROnlinePlayerExact.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
|
||||
public class AROnlinePlayerExact implements ArgReader<Player>
|
||||
{
|
||||
@Override
|
||||
public ArgResult<Player> read(String str, MCommand mcommand)
|
||||
{
|
||||
ArgResult<Player> result = new ArgResult<Player>();
|
||||
Player player = Bukkit.getServer().getPlayerExact(str);
|
||||
result.setResult(player);
|
||||
|
||||
if (!result.hasResult())
|
||||
{
|
||||
result.getErrors().add("<b>No online player with exact name \"<h>"+str+"<b\">.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static AROnlinePlayerExact i = new AROnlinePlayerExact();
|
||||
public static AROnlinePlayerExact get() { return i; }
|
||||
|
||||
}
|
||||
49
src/com/massivecraft/mcore5/cmd/arg/AROnlinePlayerMatch.java
Normal file
49
src/com/massivecraft/mcore5/cmd/arg/AROnlinePlayerMatch.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
|
||||
public class AROnlinePlayerMatch implements ArgReader<Player>
|
||||
{
|
||||
@Override
|
||||
public ArgResult<Player> read(String str, MCommand mcommand)
|
||||
{
|
||||
ArgResult<Player> result = new ArgResult<Player>();
|
||||
|
||||
List<Player> players = Bukkit.getServer().matchPlayer(str);
|
||||
if (players.size() == 1)
|
||||
{
|
||||
result.setResult(players.get(0));
|
||||
}
|
||||
else if (players.size() > 1)
|
||||
{
|
||||
List<String> names = new ArrayList<String>();
|
||||
for (Player player : players)
|
||||
{
|
||||
names.add(player.getName());
|
||||
}
|
||||
result.getErrors().add("<b>Online player matching \"<h>"+str+"<b>\" is ambigious.");
|
||||
result.getErrors().add("<b>Did you mean "+Txt.implodeCommaAndDot(names, "<h>%s", "<b>, ", " <b>or ", "<b>?"));
|
||||
}
|
||||
else if (players.size() == 0)
|
||||
{
|
||||
result.getErrors().add("<b>No online player matching \"<h>"+str+"<b\">.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static AROnlinePlayerMatch i = new AROnlinePlayerMatch();
|
||||
public static AROnlinePlayerMatch get() { return i; }
|
||||
|
||||
}
|
||||
24
src/com/massivecraft/mcore5/cmd/arg/ARString.java
Normal file
24
src/com/massivecraft/mcore5/cmd/arg/ARString.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
public class ARString extends ARAbstractPrimitive<String>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "string";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convert(String str) throws Exception
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARString i = new ARString();
|
||||
public static ARString get() { return i; }
|
||||
|
||||
}
|
||||
53
src/com/massivecraft/mcore5/cmd/arg/ARStringEntity.java
Normal file
53
src/com/massivecraft/mcore5/cmd/arg/ARStringEntity.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.store.Coll;
|
||||
import com.massivecraft.mcore5.store.Entity;
|
||||
|
||||
public class ARStringEntity<E extends Entity<E, String>> implements ArgReader<E>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public ArgResult<E> read(String str, MCommand mcommand)
|
||||
{
|
||||
ArgResult<E> result = new ArgResult<E>();
|
||||
ArgResult<String> innerResult = this.stringReader().read(str, mcommand);
|
||||
|
||||
if (innerResult.hasResult())
|
||||
{
|
||||
String playerName = innerResult.getResult();
|
||||
E entity = this.coll().get(playerName);
|
||||
result.setResult(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.setErrors(innerResult.getErrors());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected ArgReader<String> stringReader;
|
||||
public ArgReader<String> stringReader() { return this.stringReader; }
|
||||
|
||||
protected Coll<E, String> coll;
|
||||
public Coll<E, String> coll() { return this.coll; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public ARStringEntity(ArgReader<String> stringReader, Coll<E, String> coll)
|
||||
{
|
||||
this.stringReader = stringReader;
|
||||
this.coll = coll;
|
||||
}
|
||||
|
||||
}
|
||||
25
src/com/massivecraft/mcore5/cmd/arg/ARStringMatchFullCI.java
Normal file
25
src/com/massivecraft/mcore5/cmd/arg/ARStringMatchFullCI.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ARStringMatchFullCI extends ARAbstractStringMatch
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public Integer matches(String arg, String alt)
|
||||
{
|
||||
return alt.equalsIgnoreCase(arg) ? 0 : null;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public ARStringMatchFullCI(String typename, Collection<Collection<String>> altColls)
|
||||
{
|
||||
super(typename, altColls);
|
||||
}
|
||||
}
|
||||
25
src/com/massivecraft/mcore5/cmd/arg/ARStringMatchFullCS.java
Normal file
25
src/com/massivecraft/mcore5/cmd/arg/ARStringMatchFullCS.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ARStringMatchFullCS extends ARAbstractStringMatch
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public Integer matches(String arg, String alt)
|
||||
{
|
||||
return alt.equals(arg) ? 0 : null;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public ARStringMatchFullCS(String typename, Collection<Collection<String>> altColls)
|
||||
{
|
||||
super(typename, altColls);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ARStringMatchStartCI extends ARAbstractStringMatch
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public Integer matches(String arg, String alt)
|
||||
{
|
||||
arg = arg.toLowerCase();
|
||||
alt = alt.toLowerCase();
|
||||
if (alt.startsWith(arg))
|
||||
{
|
||||
return alt.length() - arg.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public ARStringMatchStartCI(String typename, Collection<Collection<String>> altColls)
|
||||
{
|
||||
super(typename, altColls);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ARStringMatchStartCS extends ARAbstractStringMatch
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public Integer matches(String arg, String alt)
|
||||
{
|
||||
if (alt.startsWith(arg))
|
||||
{
|
||||
return alt.length() - arg.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public ARStringMatchStartCS(String typename, Collection<Collection<String>> altColls)
|
||||
{
|
||||
super(typename, altColls);
|
||||
}
|
||||
}
|
||||
51
src/com/massivecraft/mcore5/cmd/arg/ARUniverse.java
Normal file
51
src/com/massivecraft/mcore5/cmd/arg/ARUniverse.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.usys.Multiverse;
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
|
||||
public class ARUniverse implements ArgReader<String>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public ArgResult<String> read(String str, MCommand mcommand)
|
||||
{
|
||||
ArgResult<String> result = new ArgResult<String>();
|
||||
|
||||
if (multiverse.containsUniverse(str))
|
||||
{
|
||||
result.setResult(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.getErrors().add("<b>No universe \"<h>"+str+"<b>\" exists in multiverse <h>"+this.multiverse.getId()+"<b>.");
|
||||
|
||||
Collection<String> names = new ArrayList<String>(multiverse.getUniverses());
|
||||
result.getErrors().add("<i>Use "+Txt.implodeCommaAndDot(names, "<h>%s", "<i>, ", " <i>or ", "<i>."));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected Multiverse multiverse;
|
||||
public Multiverse multiverse() { return this.multiverse; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public ARUniverse(Multiverse multiverse)
|
||||
{
|
||||
this.multiverse = multiverse;
|
||||
}
|
||||
}
|
||||
43
src/com/massivecraft/mcore5/cmd/arg/ARWorld.java
Normal file
43
src/com/massivecraft/mcore5/cmd/arg/ARWorld.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
|
||||
public class ARWorld extends ARAbstractSelect<World>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "world";
|
||||
}
|
||||
|
||||
@Override
|
||||
public World select(String str, MCommand mcommand)
|
||||
{
|
||||
return Bukkit.getWorld(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> altNames(MCommand mcommand)
|
||||
{
|
||||
List<String> ret = new ArrayList<String>();
|
||||
for (World world : Bukkit.getWorlds())
|
||||
{
|
||||
ret.add(world.getName());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARWorld i = new ARWorld();
|
||||
public static ARWorld get() { return i; }
|
||||
|
||||
}
|
||||
70
src/com/massivecraft/mcore5/cmd/arg/ARWorldType.java
Normal file
70
src/com/massivecraft/mcore5/cmd/arg/ARWorldType.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.WorldType;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.util.MUtil;
|
||||
|
||||
public class ARWorldType extends ARAbstractSelect<WorldType>
|
||||
{
|
||||
@Override
|
||||
public String typename()
|
||||
{
|
||||
return "world type";
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldType select(String str, MCommand mcommand)
|
||||
{
|
||||
WorldType ret = null;
|
||||
|
||||
// "DEFAULT_1_1" --> "11"
|
||||
// "LARGE_BIOMES" --> "large"
|
||||
// "Default" --> ""
|
||||
str = str.toLowerCase();
|
||||
str = str.replace("_", "");
|
||||
str = str.replace(".", "");
|
||||
str = str.replace("normal", "");
|
||||
str = str.replace("default", "");
|
||||
str = str.replace("large", "");
|
||||
|
||||
if (str.equals(""))
|
||||
{
|
||||
// "normal" or "default"
|
||||
ret = WorldType.NORMAL;
|
||||
}
|
||||
else if (str.startsWith("flat"))
|
||||
{
|
||||
// "flat"
|
||||
ret = WorldType.FLAT;
|
||||
}
|
||||
else if (str.contains("11"))
|
||||
{
|
||||
// "VERSION_1_1"
|
||||
ret = WorldType.VERSION_1_1;
|
||||
}
|
||||
else if (str.contains("large"))
|
||||
{
|
||||
// "LARGE_BIOMES"
|
||||
ret = WorldType.LARGE_BIOMES;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> altNames(MCommand mcommand)
|
||||
{
|
||||
return MUtil.list("normal", "flat", "1.1", "largebiomes");
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ARWorldType i = new ARWorldType();
|
||||
public static ARWorldType get() { return i; }
|
||||
|
||||
}
|
||||
8
src/com/massivecraft/mcore5/cmd/arg/ArgReader.java
Normal file
8
src/com/massivecraft/mcore5/cmd/arg/ArgReader.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
|
||||
public interface ArgReader<T>
|
||||
{
|
||||
public ArgResult<T> read(String str, MCommand mcommand);
|
||||
}
|
||||
75
src/com/massivecraft/mcore5/cmd/arg/ArgResult.java
Normal file
75
src/com/massivecraft/mcore5/cmd/arg/ArgResult.java
Normal file
@@ -0,0 +1,75 @@
|
||||
package com.massivecraft.mcore5.cmd.arg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class ArgResult<T>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELD: RESULT
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Getter @Setter protected T result = null;
|
||||
public boolean hasResult()
|
||||
{
|
||||
return this.getResult() != null;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELD: ERRORS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Getter protected List<String> errors = new ArrayList<String>();
|
||||
|
||||
public void setErrors(List<String> val)
|
||||
{
|
||||
if (val == null)
|
||||
{
|
||||
this.errors = new ArrayList<String>();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.errors = val;
|
||||
}
|
||||
}
|
||||
|
||||
public void setErrors(String... val)
|
||||
{
|
||||
this.setErrors(Arrays.asList(val));
|
||||
}
|
||||
|
||||
public boolean hasErrors()
|
||||
{
|
||||
return this.errors.size() > 0;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public ArgResult()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ArgResult(T result)
|
||||
{
|
||||
this.setResult(result);
|
||||
}
|
||||
|
||||
public ArgResult(T result, List<String> errors)
|
||||
{
|
||||
this.setResult(result);
|
||||
this.setErrors(errors);
|
||||
}
|
||||
|
||||
public ArgResult(T result, String... errors)
|
||||
{
|
||||
this.setResult(result);
|
||||
this.setErrors(errors);
|
||||
}
|
||||
}
|
||||
14
src/com/massivecraft/mcore5/cmd/req/IReq.java
Normal file
14
src/com/massivecraft/mcore5/cmd/req/IReq.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.massivecraft.mcore5.cmd.req;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
|
||||
public interface IReq
|
||||
{
|
||||
// This just tests wether the requirement is met or not.
|
||||
public boolean test(CommandSender sender, MCommand command);
|
||||
|
||||
// This just composes the error message and does NOT test the requirement at all.
|
||||
public String createErrorMessage(CommandSender sender, MCommand command);
|
||||
}
|
||||
37
src/com/massivecraft/mcore5/cmd/req/ReqHasPerm.java
Normal file
37
src/com/massivecraft/mcore5/cmd/req/ReqHasPerm.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.massivecraft.mcore5.cmd.req;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
import com.massivecraft.mcore5.util.Perm;
|
||||
|
||||
public class ReqHasPerm implements IReq
|
||||
{
|
||||
@Getter @Setter private String perm;
|
||||
|
||||
public ReqHasPerm(String perm)
|
||||
{
|
||||
this.perm = perm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(CommandSender sender, MCommand command)
|
||||
{
|
||||
return sender.hasPermission(this.perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createErrorMessage(CommandSender sender, MCommand command)
|
||||
{
|
||||
return Perm.getForbiddenMessage(this.perm);
|
||||
}
|
||||
|
||||
public static ReqHasPerm get(String perm)
|
||||
{
|
||||
return new ReqHasPerm(perm);
|
||||
}
|
||||
|
||||
}
|
||||
33
src/com/massivecraft/mcore5/cmd/req/ReqIsPlayer.java
Normal file
33
src/com/massivecraft/mcore5/cmd/req/ReqIsPlayer.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.massivecraft.mcore5.cmd.req;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.massivecraft.mcore5.Lang;
|
||||
import com.massivecraft.mcore5.cmd.MCommand;
|
||||
|
||||
public class ReqIsPlayer implements IReq
|
||||
{
|
||||
@Override
|
||||
public boolean test(CommandSender sender, MCommand command)
|
||||
{
|
||||
return sender instanceof Player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createErrorMessage(CommandSender sender, MCommand command)
|
||||
{
|
||||
return Lang.commandSenderMustBePlayer;
|
||||
}
|
||||
|
||||
protected static ReqIsPlayer instance= new ReqIsPlayer();
|
||||
public static ReqIsPlayer getInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static ReqIsPlayer get()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.massivecraft.mcore5.event;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
|
||||
public class MCoreAfterPlayerRespawnEvent extends Event implements Runnable
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// REQUIRED EVENT CODE
|
||||
// -------------------------------------------- //
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
@Override public HandlerList getHandlers() { return handlers; }
|
||||
public static HandlerList getHandlerList() { return handlers; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELD
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Getter protected final Location deathLocation;
|
||||
|
||||
@Getter protected final PlayerRespawnEvent bukkitEvent;
|
||||
|
||||
public Location getRespawnLocation() { return this.bukkitEvent.getRespawnLocation(); }
|
||||
public Player getPlayer() { return this.bukkitEvent.getPlayer(); }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public MCoreAfterPlayerRespawnEvent(PlayerRespawnEvent bukkitEvent, Location deathLocation)
|
||||
{
|
||||
this.bukkitEvent = bukkitEvent;
|
||||
this.deathLocation = deathLocation;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// HANDY RUN SHORTCUT
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Bukkit.getPluginManager().callEvent(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.massivecraft.mcore5.event;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
public class MCoreAfterPlayerTeleportEvent extends Event implements Runnable
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// REQUIRED EVENT CODE
|
||||
// -------------------------------------------- //
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
@Override public HandlerList getHandlers() { return handlers; }
|
||||
public static HandlerList getHandlerList() { return handlers; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELD
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Getter protected final PlayerTeleportEvent bukkitEvent;
|
||||
|
||||
public Location getFrom() { return this.bukkitEvent.getFrom(); }
|
||||
public Location getTo() { return this.bukkitEvent.getTo(); }
|
||||
public Player getPlayer() { return this.bukkitEvent.getPlayer(); }
|
||||
public TeleportCause getCause() { return this.bukkitEvent.getCause(); }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public MCoreAfterPlayerTeleportEvent(PlayerTeleportEvent bukkitEvent)
|
||||
{
|
||||
this.bukkitEvent = bukkitEvent;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// HANDY RUN SHORTCUT
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Bukkit.getPluginManager().callEvent(this);
|
||||
}
|
||||
}
|
||||
85
src/com/massivecraft/mcore5/event/MCorePlayerLeaveEvent.java
Normal file
85
src/com/massivecraft/mcore5/event/MCorePlayerLeaveEvent.java
Normal file
@@ -0,0 +1,85 @@
|
||||
package com.massivecraft.mcore5.event;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
/**
|
||||
* The MCorePlayerLeaveEvent is a non-cancellable event.
|
||||
* It is run at the MONITOR of either PlayerKickEvent or PlayerQuitEvent.
|
||||
* It is also guaranteed to run before the MCore "store" module syncs
|
||||
* all entities related to the player that is leaving the server.
|
||||
*
|
||||
* 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 pre disconnect if possible due to the internal usage if the PlayerKickedEvent.
|
||||
*/
|
||||
public class MCorePlayerLeaveEvent extends Event implements Runnable
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// REQUIRED EVENT CODE
|
||||
// -------------------------------------------- //
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
@Override public HandlerList getHandlers() { return handlers; }
|
||||
public static HandlerList getHandlerList() { return handlers; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELD
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Getter protected final Player player;
|
||||
|
||||
@Getter protected final boolean preDisconnect;
|
||||
public boolean isPostDisconnect() { return !this.isPreDisconnect(); }
|
||||
|
||||
@Getter protected final String caller;
|
||||
public boolean isQuit() { return "quit".equals(caller); }
|
||||
public boolean isKick() { return "kick".equals(caller); }
|
||||
|
||||
@Getter protected final String message;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public MCorePlayerLeaveEvent(Player player, boolean preDisconnect, String caller, String message)
|
||||
{
|
||||
this.player = player;
|
||||
this.preDisconnect = preDisconnect;
|
||||
this.caller = caller;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// HANDY RUN SHORTCUT
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
// 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>();
|
||||
|
||||
}
|
||||
108
src/com/massivecraft/mcore5/integration/Integration.java
Normal file
108
src/com/massivecraft/mcore5/integration/Integration.java
Normal file
@@ -0,0 +1,108 @@
|
||||
package com.massivecraft.mcore5.integration;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.massivecraft.mcore5.MPlugin;
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
|
||||
public class Integration implements Listener
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected MPlugin ourPlugin;
|
||||
protected IntegrationFeatures features;
|
||||
|
||||
@Getter protected boolean active = false;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public Integration(MPlugin ourPlugin, IntegrationFeatures features)
|
||||
{
|
||||
this.ourPlugin = ourPlugin;
|
||||
this.features = features;
|
||||
|
||||
Bukkit.getServer().getPluginManager().registerEvents(this, this.ourPlugin);
|
||||
this.tick();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// LOGIC
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void tick()
|
||||
{
|
||||
if (pluginEnabled(this.features.getTargetPluginName()))
|
||||
{
|
||||
if (!this.active)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.features.activate();
|
||||
this.active = true;
|
||||
this.ourPlugin.log(Txt.parse("<g>Activated <i>integration with <h>%s<i>.", this.features.getTargetPluginName()));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.ourPlugin.log(Txt.parse("<b>Failed to activate <i>integration with <h>%s<i>.", this.features.getTargetPluginName()));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.active)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.active = false;
|
||||
this.features.deactivate();
|
||||
this.ourPlugin.log(Txt.parse("Deactivated integration with <h>%s<i>.", this.features.getTargetPluginName()));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.ourPlugin.log(Txt.parse("<b>Failed to deactivate <i>integration with <h>%s<i>.", this.features.getTargetPluginName()));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// UTIL
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static boolean pluginEnabled(String pluginName)
|
||||
{
|
||||
Plugin plugin = Bukkit.getPluginManager().getPlugin(pluginName);
|
||||
if (plugin == null) return false;
|
||||
return plugin.isEnabled();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// EVENT LISTENERS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPluginDisable(PluginDisableEvent event)
|
||||
{
|
||||
this.tick();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPluginEnable(PluginEnableEvent event)
|
||||
{
|
||||
this.tick();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.massivecraft.mcore5.integration;
|
||||
|
||||
public interface IntegrationFeatures
|
||||
{
|
||||
public String getTargetPluginName();
|
||||
public void activate();
|
||||
public void deactivate();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.massivecraft.mcore5.integration;
|
||||
|
||||
public abstract class IntegrationFeaturesAbstract implements IntegrationFeatures
|
||||
{
|
||||
@Override
|
||||
public String getTargetPluginName()
|
||||
{
|
||||
// "SpoutFeatures" --> "Spout"
|
||||
String ret = this.getClass().getSimpleName();
|
||||
ret = ret.substring(0, ret.length()-8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
614
src/com/massivecraft/mcore5/store/Coll.java
Normal file
614
src/com/massivecraft/mcore5/store/Coll.java
Normal file
@@ -0,0 +1,614 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import com.massivecraft.mcore5.MCore;
|
||||
import com.massivecraft.mcore5.MPlugin;
|
||||
import com.massivecraft.mcore5.Predictate;
|
||||
import com.massivecraft.mcore5.store.accessor.Accessor;
|
||||
import com.massivecraft.mcore5.store.idstrategy.IdStrategy;
|
||||
import com.massivecraft.mcore5.store.storeadapter.StoreAdapter;
|
||||
|
||||
public class Coll<E, L> implements CollInterface<E, L>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// GLOBAL REGISTRY
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static List<Coll<?, ?>> instances = new CopyOnWriteArrayList<Coll<?, ?>>();
|
||||
|
||||
// -------------------------------------------- //
|
||||
// WHAT DO WE HANDLE?
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected final String name;
|
||||
@Override public String getName() { return this.name; }
|
||||
|
||||
protected final String basename;
|
||||
@Override public String getBasename() { return this.basename; }
|
||||
|
||||
protected final String universe;
|
||||
@Override public String getUniverse() { return this.universe; }
|
||||
|
||||
protected final Class<E> entityClass;
|
||||
@Override public Class<E> getEntityClass() { return this.entityClass; }
|
||||
|
||||
protected final Class<L> idClass;
|
||||
@Override public Class<L> getIdClass() { return this.idClass; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SUPPORTING SYSTEM
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected MPlugin mplugin;
|
||||
@Override public MPlugin getMplugin() { return this.mplugin; }
|
||||
|
||||
protected Db<?> db;
|
||||
@Override public Db<?> getDb() { return this.db; }
|
||||
@Override public Driver<?> getDriver() { return this.db.getDriver(); }
|
||||
|
||||
protected IdStrategy<L, ?> idStrategy;
|
||||
@Override public IdStrategy<L, ?> getIdStrategy() { return this.idStrategy; }
|
||||
|
||||
protected StoreAdapter storeAdapter;
|
||||
@Override public StoreAdapter getStoreAdapter() { return this.storeAdapter; }
|
||||
|
||||
protected Object collDriverObject;
|
||||
@Override public Object getCollDriverObject() { return this.collDriverObject; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// STORAGE
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected Set<L> ids = Collections.newSetFromMap(new ConcurrentHashMap<L, Boolean>());
|
||||
@Override public Collection<L> getIds() { return Collections.unmodifiableCollection(this.ids); }
|
||||
@Override public Collection<L> getIdsRemote() { return this.getDb().getDriver().getIds(this); }
|
||||
@Override public boolean containsEntity(E entity) { return this.entities.contains(entity); };
|
||||
@Override
|
||||
public boolean containsId(Object oid)
|
||||
{
|
||||
L id = this.fixId(oid);
|
||||
if (id == null) return false;
|
||||
return this.ids.contains(id);
|
||||
}
|
||||
|
||||
|
||||
protected Set<E> entities = Collections.newSetFromMap(new ConcurrentHashMap<E, Boolean>());
|
||||
@Override public Collection<E> getAll() { return Collections.unmodifiableCollection(this.entities); }
|
||||
@Override public Collection<E> getAll(Predictate<E> where) { return MStoreUtil.uglySQL(this.getAll(), where, null, null, null); }
|
||||
@Override public Collection<E> getAll(Predictate<E> where, Comparator<E> orderby) { return MStoreUtil.uglySQL(this.getAll(), where, orderby, null, null); }
|
||||
@Override public Collection<E> getAll(Predictate<E> where, Comparator<E> orderby, Integer limit) { return MStoreUtil.uglySQL(this.getAll(), where, orderby, limit, null); }
|
||||
@Override public Collection<E> getAll(Predictate<E> where, Comparator<E> orderby, Integer limit, Integer offset) { return MStoreUtil.uglySQL(this.getAll(), where, orderby, limit, offset); }
|
||||
|
||||
protected Map<L, E> id2entity = new ConcurrentHashMap<L, E>();
|
||||
@Override public Map<L, E> getId2entity() { return Collections.unmodifiableMap(this.id2entity); }
|
||||
@Override
|
||||
public E get(Object oid)
|
||||
{
|
||||
return this.get(oid, this.isCreative());
|
||||
}
|
||||
@Override
|
||||
public E get(Object oid, boolean creative)
|
||||
{
|
||||
return this.get(oid, creative, true);
|
||||
}
|
||||
protected E get(Object oid, boolean creative, boolean noteChange)
|
||||
{
|
||||
L id = this.fixId(oid);
|
||||
if (id == null) return null;
|
||||
E ret = this.id2entity.get(id);
|
||||
if (ret != null) return ret;
|
||||
if ( ! creative) return null;
|
||||
return this.create(id, noteChange);
|
||||
}
|
||||
|
||||
// Get the id for this entity.
|
||||
protected Map<E, L> entity2id = new ConcurrentHashMap<E, L>();
|
||||
@Override public Map<E, L> getEntity2id() { return Collections.unmodifiableMap(this.entity2id); }
|
||||
@Override public L getId(E entity) { return this.entity2id.get(entity); }
|
||||
|
||||
@Override
|
||||
public L fixId(Object oid)
|
||||
{
|
||||
if (oid == null) return null;
|
||||
if (oid.getClass() == this.idClass) return this.idClass.cast(oid);
|
||||
if (oid.getClass() == this.entityClass) return this.entity2id.get(oid);
|
||||
return null;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// BAHAVIOR
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected boolean creative;
|
||||
@Override public boolean isCreative() { return this.creative; }
|
||||
@Override public void setCreative(boolean val) { this.creative = val; }
|
||||
|
||||
// Should that instance be saved or not?
|
||||
// If it is default it should not be saved.
|
||||
@Override public boolean isDefault(E entity) { return false; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COPY AND CREATE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void copy(Object ofrom, Object oto)
|
||||
{
|
||||
if (ofrom instanceof Entity)
|
||||
{
|
||||
Entity efrom = (Entity)ofrom;
|
||||
Entity eto = (Entity)oto;
|
||||
eto.load(efrom);
|
||||
}
|
||||
else
|
||||
{
|
||||
Accessor.get(this.getEntityClass()).copy(ofrom, oto);
|
||||
}
|
||||
}
|
||||
|
||||
// This simply creates and returns a new instance
|
||||
// It does not detach/attach or anything. Just creates a new instance.
|
||||
@Override
|
||||
public E createNewInstance()
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.entityClass.newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new instance with automatic id
|
||||
@Override
|
||||
public E create()
|
||||
{
|
||||
return this.create(null);
|
||||
}
|
||||
|
||||
// Create new instance with the requested id
|
||||
@Override
|
||||
public synchronized E create(Object oid)
|
||||
{
|
||||
return this.create(oid, true);
|
||||
}
|
||||
|
||||
public synchronized E create(Object oid, boolean noteChange)
|
||||
{
|
||||
E entity = this.createNewInstance();
|
||||
if (this.attach(entity, oid, noteChange) == null) return null;
|
||||
return entity;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public L attach(E entity)
|
||||
{
|
||||
return this.attach(entity, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized L attach(E entity, Object oid)
|
||||
{
|
||||
return this.attach(entity, oid, true);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
protected synchronized L attach(E entity, Object oid, boolean noteChange)
|
||||
{
|
||||
// Check entity
|
||||
if (entity == null) return null;
|
||||
L id = this.getId(entity);
|
||||
if (id != null) return id;
|
||||
|
||||
// Check/Fix id
|
||||
if (oid == null)
|
||||
{
|
||||
id = this.getIdStrategy().generate(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
id = this.fixId(oid);
|
||||
if (id == null) return null;
|
||||
if (this.ids.contains(id)) return null;
|
||||
}
|
||||
|
||||
// Attach
|
||||
this.ids.add(id);
|
||||
this.entities.add(entity);
|
||||
this.id2entity.put(id, entity);
|
||||
this.entity2id.put(entity, id);
|
||||
|
||||
// Set this as the coll if possible.
|
||||
if (entity instanceof Entity)
|
||||
{
|
||||
((Entity)entity).setColl(this);
|
||||
}
|
||||
|
||||
// Make note of the change
|
||||
if (noteChange)
|
||||
{
|
||||
this.localAttachIds.add(id);
|
||||
this.changedIds.add(id);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public synchronized E detach(Object o)
|
||||
{
|
||||
// What id is this?
|
||||
L id = null;
|
||||
if (this.idClass.isInstance(o))
|
||||
{
|
||||
id = (L)o;
|
||||
}
|
||||
else if (this.entityClass.isInstance(o))
|
||||
{
|
||||
id = this.entity2id.get(o);
|
||||
}
|
||||
else
|
||||
{
|
||||
id = this.fixId(o);
|
||||
}
|
||||
if (id == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove @ local
|
||||
E ret = this.removeAtLocal(id);
|
||||
|
||||
// Identify the change
|
||||
this.localDetachIds.add(id);
|
||||
this.changedIds.add(id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IDENTIFIED CHANGES
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected Set<L> localAttachIds = Collections.newSetFromMap(new ConcurrentHashMap<L, Boolean>());
|
||||
protected Set<L> localDetachIds = Collections.newSetFromMap(new ConcurrentHashMap<L, Boolean>());
|
||||
protected Set<L> changedIds = Collections.newSetFromMap(new ConcurrentHashMap<L, Boolean>());
|
||||
|
||||
protected synchronized void clearIdentifiedChanges(L id)
|
||||
{
|
||||
this.localAttachIds.remove(id);
|
||||
this.localDetachIds.remove(id);
|
||||
this.changedIds.remove(id);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNCLOG
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected Map<L, Long> lastMtime = new ConcurrentHashMap<L, Long>();
|
||||
protected Map<L, Object> lastRaw = new ConcurrentHashMap<L, Object>();
|
||||
protected Set<L> lastDefault = Collections.newSetFromMap(new ConcurrentHashMap<L, Boolean>());
|
||||
|
||||
protected synchronized void clearSynclog(L id)
|
||||
{
|
||||
this.lastMtime.remove(id);
|
||||
this.lastRaw.remove(id);
|
||||
this.lastDefault.remove(id);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC LOWLEVEL IO ACTIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public synchronized E removeAtLocal(L id)
|
||||
{
|
||||
this.clearIdentifiedChanges(id);
|
||||
this.clearSynclog(id);
|
||||
|
||||
this.ids.remove(id);
|
||||
E entity = this.id2entity.remove(id);
|
||||
if (entity == null) return null;
|
||||
|
||||
this.entity2id.remove(entity);
|
||||
this.entities.remove(entity);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void removeAtRemote(L id)
|
||||
{
|
||||
this.clearIdentifiedChanges(id);
|
||||
this.clearSynclog(id);
|
||||
|
||||
this.getDb().getDriver().delete(this, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void saveToRemote(L id)
|
||||
{
|
||||
this.clearIdentifiedChanges(id);
|
||||
this.clearSynclog(id);
|
||||
|
||||
E entity = this.id2entity.get(id);
|
||||
if (entity == null) return;
|
||||
|
||||
Object raw = this.getStoreAdapter().read(this, entity);
|
||||
this.lastRaw.put(id, raw);
|
||||
|
||||
if (this.isDefault(entity))
|
||||
{
|
||||
this.db.getDriver().delete(this, id);
|
||||
this.lastDefault.add(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
Long mtime = this.db.getDriver().save(this, id, raw);
|
||||
if (mtime == null) return; // This fail should not happen often. We could handle it better though.
|
||||
this.lastMtime.put(id, mtime);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void loadFromRemote(L id)
|
||||
{
|
||||
this.clearIdentifiedChanges(id);
|
||||
|
||||
Entry<?, Long> entry = this.getDb().getDriver().load(this, id);
|
||||
if (entry == null) return;
|
||||
|
||||
Object raw = entry.getKey();
|
||||
if (raw == null) return;
|
||||
|
||||
Long mtime = entry.getValue();
|
||||
if (mtime == null) return;
|
||||
|
||||
E entity = this.get(id, true, false);
|
||||
|
||||
this.getStoreAdapter().write(this, raw, entity);
|
||||
|
||||
// Store adapter again since result of a database read may be "different" from entity read.
|
||||
this.lastRaw.put(id, this.getStoreAdapter().read(this, entity));
|
||||
this.lastMtime.put(id, mtime);
|
||||
this.lastDefault.remove(id);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC DECIDE AND BASIC DO
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public ModificationState examineId(L id)
|
||||
{
|
||||
return this.examineId(id, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModificationState examineId(L id, Long remoteMtime)
|
||||
{
|
||||
return this.examineId(id, remoteMtime, true);
|
||||
}
|
||||
|
||||
protected ModificationState examineId(L id, Long remoteMtime, boolean remoteMtimeSupplied)
|
||||
{
|
||||
if (this.localDetachIds.contains(id)) return ModificationState.LOCAL_DETACH;
|
||||
if (this.localAttachIds.contains(id)) return ModificationState.LOCAL_ATTACH;
|
||||
|
||||
E localEntity = this.id2entity.get(id);
|
||||
if ( ! remoteMtimeSupplied)
|
||||
{
|
||||
remoteMtime = this.getDriver().getMtime(this, id);
|
||||
}
|
||||
|
||||
boolean existsLocal = (localEntity != null);
|
||||
boolean existsRemote = (remoteMtime != null);
|
||||
|
||||
if ( ! existsLocal && ! existsRemote) return ModificationState.UNKNOWN;
|
||||
|
||||
if (existsLocal && existsRemote)
|
||||
{
|
||||
Long lastMtime = this.lastMtime.get(id);
|
||||
if (remoteMtime.equals(lastMtime) == false) return ModificationState.REMOTE_ALTER;
|
||||
|
||||
if (this.examineHasLocalAlter(id, localEntity)) return ModificationState.LOCAL_ALTER;
|
||||
}
|
||||
else if (existsLocal)
|
||||
{
|
||||
if (this.lastDefault.contains(id))
|
||||
{
|
||||
if (this.examineHasLocalAlter(id, localEntity)) return ModificationState.LOCAL_ALTER;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ModificationState.REMOTE_DETACH;
|
||||
}
|
||||
}
|
||||
else if (existsRemote)
|
||||
{
|
||||
return ModificationState.REMOTE_ATTACH;
|
||||
}
|
||||
|
||||
return ModificationState.NONE;
|
||||
}
|
||||
protected boolean examineHasLocalAlter(L id, E entity)
|
||||
{
|
||||
Object lastRaw = this.lastRaw.get(id);
|
||||
Object currentRaw = this.storeAdapter.read(this, entity);
|
||||
return (currentRaw.equals(lastRaw) == false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModificationState syncId(L id)
|
||||
{
|
||||
ModificationState mstate = this.examineId(id);
|
||||
|
||||
//mplugin.log("syncId: It seems", id, "has state", mstate);
|
||||
|
||||
switch (mstate)
|
||||
{
|
||||
case LOCAL_ALTER:
|
||||
case LOCAL_ATTACH:
|
||||
this.saveToRemote(id);
|
||||
break;
|
||||
case LOCAL_DETACH:
|
||||
this.removeAtRemote(id);
|
||||
break;
|
||||
case REMOTE_ALTER:
|
||||
case REMOTE_ATTACH:
|
||||
this.loadFromRemote(id);
|
||||
break;
|
||||
case REMOTE_DETACH:
|
||||
this.removeAtLocal(id);
|
||||
break;
|
||||
default:
|
||||
this.clearIdentifiedChanges(id);
|
||||
break;
|
||||
}
|
||||
|
||||
return mstate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncSuspects()
|
||||
{
|
||||
for (L id : this.changedIds)
|
||||
{
|
||||
this.syncId(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncAll()
|
||||
{
|
||||
// Find all ids
|
||||
Set<L> allids = new HashSet<L>(this.ids);
|
||||
allids.addAll(this.getDriver().getIds(this));
|
||||
for (L id : allids)
|
||||
{
|
||||
this.syncId(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findSuspects()
|
||||
{
|
||||
// Get remote id and mtime snapshot
|
||||
Map<L, Long> id2RemoteMtime = this.getDb().getDriver().getId2mtime(this);
|
||||
|
||||
// Compile a list of all ids (both remote and local)
|
||||
Set<L> allids = new HashSet<L>();
|
||||
allids.addAll(id2RemoteMtime.keySet());
|
||||
allids.addAll(this.ids);
|
||||
|
||||
// Check for modifications
|
||||
for (L id : allids)
|
||||
{
|
||||
Long remoteMtime = id2RemoteMtime.get(id);
|
||||
ModificationState state = this.examineId(id, remoteMtime);
|
||||
//mplugin.log("findSuspects: It seems", id, "has state", state);
|
||||
if (state.isModified())
|
||||
{
|
||||
//System.out.println("It seems "+id+" has state "+state);
|
||||
this.changedIds.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC RUNNABLES / SCHEDULING
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected Runnable tickTask;
|
||||
@Override public Runnable getTickTask() { return this.tickTask; }
|
||||
@Override
|
||||
public void onTick()
|
||||
{
|
||||
this.syncSuspects();
|
||||
}
|
||||
|
||||
protected ExamineThread<E, L> examineThread;
|
||||
@Override public Thread examineThread() { return this.examineThread; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public Coll(Db<?> db, MPlugin mplugin, String idStrategyName, String name, Class<E> entityClass, Class<L> idClass, boolean creative)
|
||||
{
|
||||
// Setup the name and the parsed parts
|
||||
this.name = name;
|
||||
String[] nameParts = this.name.split("\\@");
|
||||
this.basename = nameParts[0];
|
||||
if (nameParts.length > 1)
|
||||
{
|
||||
this.universe = nameParts[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
this.universe = null;
|
||||
}
|
||||
|
||||
this.entityClass = entityClass;
|
||||
this.idClass = idClass;
|
||||
this.creative = creative;
|
||||
|
||||
this.mplugin = mplugin;
|
||||
this.db = db;
|
||||
this.storeAdapter = this.db.getDriver().getStoreAdapter();
|
||||
this.idStrategy = this.db.getDriver().getIdStrategy(idStrategyName);
|
||||
if (this.idStrategy == null)
|
||||
{
|
||||
throw new IllegalArgumentException("UNKNOWN: The id stragegy \""+idStrategyName+"\" is unknown to the driver \""+db.getDriver().getName()+"\".");
|
||||
}
|
||||
else if (this.idStrategy.getLocalClass() != idClass)
|
||||
{
|
||||
throw new IllegalArgumentException("MISSMATCH: The id stragegy \""+idStrategyName+"\" for the driver \""+db.getDriver().getName()+"\" uses \""+this.idStrategy.getLocalClass().getSimpleName()+"\" but the collection "+this.name+"/"+this.getClass().getSimpleName()+" uses \""+idClass.getSimpleName()+"\".");
|
||||
}
|
||||
this.collDriverObject = db.getCollDriverObject(this);
|
||||
|
||||
final Coll<E, L> me = this;
|
||||
this.tickTask = new Runnable()
|
||||
{
|
||||
@Override public void run() { me.onTick(); }
|
||||
};
|
||||
}
|
||||
|
||||
public Coll(MPlugin mplugin, String idStrategyName, String name, Class<E> entityClass, Class<L> idClass, boolean creative)
|
||||
{
|
||||
this(MCore.getDb(), mplugin, idStrategyName, name, entityClass, idClass, creative);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
if (this.inited()) return;
|
||||
this.syncAll();
|
||||
this.examineThread = new ExamineThread<E, L>(this);
|
||||
this.examineThread.start();
|
||||
instances.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inited()
|
||||
{
|
||||
return instances.contains(this);
|
||||
}
|
||||
}
|
||||
149
src/com/massivecraft/mcore5/store/CollInterface.java
Normal file
149
src/com/massivecraft/mcore5/store/CollInterface.java
Normal file
@@ -0,0 +1,149 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
|
||||
import com.massivecraft.mcore5.MPlugin;
|
||||
import com.massivecraft.mcore5.Predictate;
|
||||
import com.massivecraft.mcore5.store.idstrategy.IdStrategy;
|
||||
import com.massivecraft.mcore5.store.storeadapter.StoreAdapter;
|
||||
|
||||
public interface CollInterface<E, L>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// WHAT DO WE HANDLE?
|
||||
// -------------------------------------------- //
|
||||
public String getName();
|
||||
public String getBasename();
|
||||
public String getUniverse();
|
||||
public Class<E> getEntityClass();
|
||||
public Class<L> getIdClass();
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SUPPORTING SYSTEM
|
||||
// -------------------------------------------- //
|
||||
public MPlugin getMplugin();
|
||||
|
||||
public Db<?> getDb();
|
||||
public Driver<?> getDriver();
|
||||
public StoreAdapter getStoreAdapter();
|
||||
public IdStrategy<L, ?> getIdStrategy();
|
||||
public Object getCollDriverObject();
|
||||
|
||||
// -------------------------------------------- //
|
||||
// STORAGE
|
||||
// -------------------------------------------- //
|
||||
public Collection<L> getIds();
|
||||
public Collection<L> getIdsRemote();
|
||||
public boolean containsId(Object oid);
|
||||
public boolean containsEntity(E entity);
|
||||
|
||||
public Collection<E> getAll();
|
||||
public Collection<E> getAll(Predictate<E> where);
|
||||
public Collection<E> getAll(Predictate<E> where, Comparator<E> orderby);
|
||||
public Collection<E> getAll(Predictate<E> where, Comparator<E> orderby, Integer limit);
|
||||
public Collection<E> getAll(Predictate<E> where, Comparator<E> orderby, Integer limit, Integer offset);
|
||||
|
||||
public Map<L, E> getId2entity();
|
||||
public E get(Object oid);
|
||||
public E get(Object oid, boolean creative);
|
||||
|
||||
public Map<E, L> getEntity2id();
|
||||
public L getId(E entity);
|
||||
public L fixId(Object oid);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// BAHAVIOR
|
||||
// -------------------------------------------- //
|
||||
public boolean isCreative();
|
||||
public void setCreative(boolean val);
|
||||
|
||||
// A default entity will not be saved.
|
||||
// This is often used together with creative collections to save disc space.
|
||||
public boolean isDefault(E entity);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COPY AND CREATE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void copy(Object fromo, Object too);
|
||||
|
||||
// This simply creates and returns a new instance
|
||||
// It does not detach/attach or anything. Just creates a new instance.
|
||||
public E createNewInstance();
|
||||
|
||||
// Create new instance with automatic id
|
||||
public E create();
|
||||
// Create new instance with the requested id
|
||||
public E create(Object oid);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
public L attach(E entity);
|
||||
public L attach(E entity, Object oid);
|
||||
public E detach(Object o);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IDENTIFIED CHANGES
|
||||
// -------------------------------------------- //
|
||||
|
||||
/*
|
||||
public Set<L> localAttachIds();
|
||||
public Set<L> localDetachIds();
|
||||
public Set<L> changedIds();
|
||||
public void clearIdentifiedChanges(L id);
|
||||
*/
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC LOG
|
||||
// -------------------------------------------- //
|
||||
|
||||
/*
|
||||
public Map<L, Long> lastMtime();
|
||||
public Map<L, Object> lastRaw();
|
||||
public Set<L> lastDefault();
|
||||
public void clearSynclog(L id);
|
||||
*/
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC LOWLEVEL IO ACTIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public E removeAtLocal(L id);
|
||||
public void removeAtRemote(L id);
|
||||
public void saveToRemote(L id);
|
||||
public void loadFromRemote(L id);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC EXAMINE AND DO
|
||||
// -------------------------------------------- //
|
||||
|
||||
public ModificationState examineId(L id);
|
||||
public ModificationState examineId(L id, Long remoteMtime);
|
||||
|
||||
public ModificationState syncId(L id);
|
||||
public void syncSuspects();
|
||||
public void syncAll();
|
||||
public void findSuspects();
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC RUNNABLES / SCHEDULING
|
||||
// -------------------------------------------- //
|
||||
|
||||
// The tickTask simply runs the onTick method.
|
||||
public Runnable getTickTask();
|
||||
public void onTick();
|
||||
|
||||
public Thread examineThread();
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void init();
|
||||
public boolean inited();
|
||||
|
||||
|
||||
}
|
||||
99
src/com/massivecraft/mcore5/store/Colls.java
Normal file
99
src/com/massivecraft/mcore5/store/Colls.java
Normal file
@@ -0,0 +1,99 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.massivecraft.mcore5.usys.Aspect;
|
||||
import com.massivecraft.mcore5.usys.Multiverse;
|
||||
import com.massivecraft.mcore5.util.MUtil;
|
||||
|
||||
public abstract class Colls<C extends Coll<E, L>, E, L>
|
||||
{
|
||||
protected Map<String, C> name2coll = new HashMap<String, C>();
|
||||
|
||||
public abstract Aspect getAspect();
|
||||
public abstract String getBasename();
|
||||
public abstract C createColl(String name);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void init()
|
||||
{
|
||||
this.getColls();
|
||||
}
|
||||
|
||||
public List<C> getColls()
|
||||
{
|
||||
List<C> ret = new ArrayList<C>();
|
||||
Aspect a = this.getAspect();
|
||||
Multiverse m = a.multiverse();
|
||||
for (String universe : m.getUniverses())
|
||||
{
|
||||
ret.add(this.getForUniverse(universe));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// UTIL
|
||||
// -------------------------------------------- //
|
||||
|
||||
public String collnameForUniverse(String universe)
|
||||
{
|
||||
return this.getBasename() + "@" + universe;
|
||||
}
|
||||
|
||||
public String universeFromWorldName(String worldName)
|
||||
{
|
||||
if (worldName == null) throw new IllegalArgumentException("worldName may not be null.");
|
||||
|
||||
return this.getAspect().multiverse().getUniverseForWorldName(worldName);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// GET
|
||||
// -------------------------------------------- //
|
||||
|
||||
public C getForWorld(String worldName)
|
||||
{
|
||||
if (worldName == null) throw new IllegalArgumentException("worldName may not be null.");
|
||||
|
||||
return this.getForUniverse(this.universeFromWorldName(worldName));
|
||||
}
|
||||
|
||||
public C getForUniverse(String universe)
|
||||
{
|
||||
if (universe == null) throw new IllegalArgumentException("universe may not be null.");
|
||||
String collname = this.collnameForUniverse(universe);
|
||||
return this.getForCollname(collname);
|
||||
}
|
||||
|
||||
public C getForCollname(String collname)
|
||||
{
|
||||
C ret = this.name2coll.get(collname);
|
||||
if (ret == null)
|
||||
{
|
||||
ret = this.createColl(collname);
|
||||
ret.init();
|
||||
this.name2coll.put(collname, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public C get(Object worldNameExtractable)
|
||||
{
|
||||
String worldName = MUtil.extract(String.class, "worldName", worldNameExtractable);
|
||||
return this.getForWorld(worldName);
|
||||
}
|
||||
|
||||
public E get2(Object worldNameExtractable)
|
||||
{
|
||||
C coll = this.get(worldNameExtractable);
|
||||
if (coll == null) return null;
|
||||
return coll.get(worldNameExtractable);
|
||||
}
|
||||
}
|
||||
16
src/com/massivecraft/mcore5/store/Db.java
Normal file
16
src/com/massivecraft/mcore5/store/Db.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface Db<R>
|
||||
{
|
||||
public String getName();
|
||||
|
||||
public boolean drop();
|
||||
|
||||
public Set<String> getCollnames();
|
||||
|
||||
public Driver<R> getDriver();
|
||||
|
||||
public Object getCollDriverObject(Coll<?, ?> coll);
|
||||
}
|
||||
12
src/com/massivecraft/mcore5/store/DbAbstract.java
Normal file
12
src/com/massivecraft/mcore5/store/DbAbstract.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class DbAbstract<R> implements Db<R>
|
||||
{
|
||||
@Override
|
||||
public Set<String> getCollnames()
|
||||
{
|
||||
return this.getDriver().getCollnames(this);
|
||||
}
|
||||
}
|
||||
57
src/com/massivecraft/mcore5/store/DbGson.java
Normal file
57
src/com/massivecraft/mcore5/store/DbGson.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.massivecraft.mcore5.util.DiscUtil;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonElement;
|
||||
|
||||
public class DbGson extends DbAbstract<JsonElement>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public File dir;
|
||||
|
||||
protected DriverGson driver;
|
||||
@Override public DriverGson getDriver() { return driver; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCTORS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public DbGson(DriverGson driver, File folder)
|
||||
{
|
||||
this.driver = driver;
|
||||
this.dir = folder;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return dir.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drop()
|
||||
{
|
||||
try
|
||||
{
|
||||
return DiscUtil.deleteRecursive(this.dir);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCollDriverObject(Coll<?, ?> coll)
|
||||
{
|
||||
return new File(dir, coll.getName());
|
||||
}
|
||||
}
|
||||
56
src/com/massivecraft/mcore5/store/DbMongo.java
Normal file
56
src/com/massivecraft/mcore5/store/DbMongo.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import com.massivecraft.mcore5.xlib.mongodb.BasicDBObject;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.DB;
|
||||
|
||||
public class DbMongo extends DbAbstract<BasicDBObject>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public DB db;
|
||||
|
||||
protected DriverMongo driver;
|
||||
@Override public DriverMongo getDriver() { return driver; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCTORS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public DbMongo(DriverMongo driver, DB db)
|
||||
{
|
||||
this.driver = driver;
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return db.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drop()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.db.dropDatabase();
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCollDriverObject(Coll<?, ?> coll)
|
||||
{
|
||||
return db.getCollection(coll.getName());
|
||||
}
|
||||
}
|
||||
55
src/com/massivecraft/mcore5/store/Driver.java
Normal file
55
src/com/massivecraft/mcore5/store/Driver.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.massivecraft.mcore5.store.idstrategy.IdStrategy;
|
||||
import com.massivecraft.mcore5.store.storeadapter.StoreAdapter;
|
||||
|
||||
public interface Driver<R>
|
||||
{
|
||||
// Returns the name of the driver.
|
||||
public String getName();
|
||||
|
||||
// This is the rawdata format this driver works with.
|
||||
// Could for example be JsonElement or DBObject
|
||||
public Class<R> getRawdataClass();
|
||||
|
||||
// This is some sort of database specific id strategy with built in adapter
|
||||
public boolean registerIdStrategy(IdStrategy<?, ?> idStrategy);
|
||||
public <L> IdStrategy<L, ?> getIdStrategy(String idStrategyName);
|
||||
|
||||
// Get the default store adapter for the driver.
|
||||
public StoreAdapter getStoreAdapter();
|
||||
|
||||
// Get a database instance from the driver
|
||||
public Db<R> getDb(String uri);
|
||||
|
||||
// What collections are in the database?
|
||||
public Set<String> getCollnames(Db<?> db);
|
||||
|
||||
// Is id X in the collection?
|
||||
public <L> boolean containsId(Coll<?, L> coll, L id);
|
||||
|
||||
// When was X last altered?
|
||||
public <L> Long getMtime(Coll<?, L> coll, L id);
|
||||
|
||||
// What ids are in the collection?
|
||||
public <L> Collection<L> getIds(Coll<?, L> coll);
|
||||
|
||||
// Return a map of all ids with their corresponding mtimes
|
||||
public <L> Map<L, Long> getId2mtime(Coll<?, L> coll);
|
||||
|
||||
// Load the raw data for X. The second part of the entry is the remote mtime at the load.
|
||||
public <L> Entry<R, Long> load(Coll<?, L> coll, L id);
|
||||
|
||||
// Save raw data as X
|
||||
// Return value is the new mtime (we caused the change).
|
||||
// If the mtime is null something failed.
|
||||
public <L> Long save(Coll<?, L> coll, L id, final Object rawData);
|
||||
|
||||
// Delete X
|
||||
public <L> void delete(Coll<?, L> coll, L id);
|
||||
}
|
||||
34
src/com/massivecraft/mcore5/store/DriverAbstract.java
Normal file
34
src/com/massivecraft/mcore5/store/DriverAbstract.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.massivecraft.mcore5.store.idstrategy.IdStrategy;
|
||||
|
||||
public abstract class DriverAbstract<R> implements Driver<R>
|
||||
{
|
||||
public DriverAbstract(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected String name;
|
||||
@Override public String getName() { return this.name; }
|
||||
|
||||
protected Map<String, IdStrategy<?, ?>> idStrategies = new HashMap<String, IdStrategy<?, ?>>();
|
||||
@Override
|
||||
public boolean registerIdStrategy(IdStrategy<?, ?> idStrategy)
|
||||
{
|
||||
if (idStrategies.containsKey(idStrategy.getName())) return false;
|
||||
idStrategies.put(idStrategy.getName(), idStrategy);
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <L> IdStrategy<L, ?> getIdStrategy(String idStrategyName)
|
||||
{
|
||||
IdStrategy<?, ?> idStrategy = idStrategies.get(idStrategyName);
|
||||
return (IdStrategy<L, ?>) idStrategy;
|
||||
}
|
||||
}
|
||||
196
src/com/massivecraft/mcore5/store/DriverGson.java
Normal file
196
src/com/massivecraft/mcore5/store/DriverGson.java
Normal file
@@ -0,0 +1,196 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.massivecraft.mcore5.store.idstrategy.IdStrategyAiGson;
|
||||
import com.massivecraft.mcore5.store.idstrategy.IdStrategyOidGson;
|
||||
import com.massivecraft.mcore5.store.idstrategy.IdStrategyUuidMongoAndGson;
|
||||
import com.massivecraft.mcore5.store.storeadapter.StoreAdapter;
|
||||
import com.massivecraft.mcore5.store.storeadapter.StoreAdapterGson;
|
||||
import com.massivecraft.mcore5.util.DiscUtil;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonElement;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonParser;
|
||||
|
||||
public class DriverGson extends DriverAbstract<JsonElement>
|
||||
{
|
||||
protected final static String DOTJSON = ".json";
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override public Class<JsonElement> getRawdataClass() { return JsonElement.class; }
|
||||
|
||||
@Override
|
||||
public StoreAdapter getStoreAdapter()
|
||||
{
|
||||
return StoreAdapterGson.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Db<JsonElement> getDb(String uri)
|
||||
{
|
||||
// "gson://" is 7 chars
|
||||
File folder = new File(uri.substring(7));
|
||||
folder.mkdirs();
|
||||
return new DbGson(this, folder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getCollnames(Db<?> db)
|
||||
{
|
||||
Set<String> ret = new LinkedHashSet<String>();
|
||||
|
||||
for (File f : ((DbGson)db).dir.listFiles())
|
||||
{
|
||||
if ( ! f.isDirectory()) continue;
|
||||
ret.add(f.getName());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> boolean containsId(Coll<?, L> coll, L id)
|
||||
{
|
||||
return fileFromId(coll, id).isFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> Long getMtime(Coll<?, L> coll, L id)
|
||||
{
|
||||
File file = fileFromId(coll, id);
|
||||
if ( ! file.isFile()) return null;
|
||||
return file.lastModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> Collection<L> getIds(Coll<?, L> coll)
|
||||
{
|
||||
List<L> ret = new ArrayList<L>();
|
||||
|
||||
// Scan the collection folder for .json files
|
||||
File collDir = getCollDir(coll);
|
||||
if ( ! collDir.isDirectory()) return ret;
|
||||
for(File file : collDir.listFiles(JsonFileFilter.get()))
|
||||
{
|
||||
// Then convert them to what they should be
|
||||
String remoteId = idFromFile(file);
|
||||
L localId = coll.getIdStrategy().remoteToLocal(remoteId);
|
||||
ret.add(localId);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> Map<L, Long> getId2mtime(Coll<?, L> coll)
|
||||
{
|
||||
Map<L, Long> ret = new HashMap<L, Long>();
|
||||
|
||||
// Scan the collection folder for .json files
|
||||
File collDir = getCollDir(coll);
|
||||
if ( ! collDir.isDirectory()) return ret;
|
||||
for(File file : collDir.listFiles(JsonFileFilter.get()))
|
||||
{
|
||||
// Then convert them to what they should be
|
||||
String remoteId = idFromFile(file);
|
||||
L localId = coll.getIdStrategy().remoteToLocal(remoteId);
|
||||
ret.put(localId, file.lastModified());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> Entry<JsonElement, Long> load(Coll<?, L> coll, L id)
|
||||
{
|
||||
File file = fileFromId(coll, id);
|
||||
Long mtime = file.lastModified();
|
||||
if (mtime == 0) return null;
|
||||
String content = DiscUtil.readCatch(file);
|
||||
if (content == null) return null;
|
||||
if (content.length() == 0) return null;
|
||||
JsonElement raw = new JsonParser().parse(content);
|
||||
return new SimpleEntry<JsonElement, Long>(raw, mtime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> Long save(Coll<?, L> coll, L id, Object rawData)
|
||||
{
|
||||
File file = fileFromId(coll, id);
|
||||
String content = coll.getMplugin().gson.toJson((JsonElement)rawData);
|
||||
if (DiscUtil.writeCatch(file, content) == false) return null;
|
||||
return file.lastModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> void delete(Coll<?, L> coll, L id)
|
||||
{
|
||||
File file = fileFromId(coll, id);
|
||||
file.delete();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// UTIL
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected static File getCollDir(Coll<?, ?> coll)
|
||||
{
|
||||
return (File) coll.getCollDriverObject();
|
||||
}
|
||||
|
||||
protected static String idFromFile(File file)
|
||||
{
|
||||
if (file == null) return null;
|
||||
String name = file.getName();
|
||||
return name.substring(0, name.length()-5);
|
||||
}
|
||||
|
||||
protected static <L> File fileFromId(Coll<?, L> coll, L id)
|
||||
{
|
||||
File collDir = getCollDir(coll);
|
||||
String idString = (String)coll.getIdStrategy().localToRemote(id);
|
||||
File idFile = new File(collDir, idString+DOTJSON);
|
||||
return idFile;
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// CONSTRUCTORS
|
||||
//----------------------------------------------//
|
||||
|
||||
public static String NAME = "gson";
|
||||
|
||||
private DriverGson()
|
||||
{
|
||||
super(NAME);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected static DriverGson instance;
|
||||
public static DriverGson get()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
instance = new DriverGson();
|
||||
instance.registerIdStrategy(IdStrategyAiGson.get());
|
||||
instance.registerIdStrategy(IdStrategyOidGson.get());
|
||||
instance.registerIdStrategy(IdStrategyUuidMongoAndGson.get());
|
||||
}
|
||||
|
||||
}
|
||||
228
src/com/massivecraft/mcore5/store/DriverMongo.java
Normal file
228
src/com/massivecraft/mcore5/store/DriverMongo.java
Normal file
@@ -0,0 +1,228 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.massivecraft.mcore5.store.idstrategy.IdStrategyAiMongo;
|
||||
import com.massivecraft.mcore5.store.idstrategy.IdStrategyOidMongo;
|
||||
import com.massivecraft.mcore5.store.idstrategy.IdStrategyUuidMongoAndGson;
|
||||
import com.massivecraft.mcore5.store.storeadapter.StoreAdapter;
|
||||
import com.massivecraft.mcore5.store.storeadapter.StoreAdapterMongo;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.BasicDBObject;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.DB;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.DBCollection;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.DBCursor;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.MongoURI;
|
||||
|
||||
public class DriverMongo extends DriverAbstract<BasicDBObject>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// STATIC
|
||||
// -------------------------------------------- //
|
||||
|
||||
public final static String ID_FIELD = "_id";
|
||||
public final static String MTIME_FIELD = "_mtime";
|
||||
|
||||
public final static BasicDBObject dboEmpty = new BasicDBObject();
|
||||
public final static BasicDBObject dboKeysId = new BasicDBObject().append(ID_FIELD, 1);
|
||||
public final static BasicDBObject dboKeysMtime = new BasicDBObject().append(MTIME_FIELD, 1);
|
||||
public final static BasicDBObject dboKeysIdandMtime = new BasicDBObject().append(ID_FIELD, 1).append(MTIME_FIELD, 1);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override public Class<BasicDBObject> getRawdataClass() { return BasicDBObject.class; }
|
||||
|
||||
@Override
|
||||
public StoreAdapter getStoreAdapter()
|
||||
{
|
||||
return StoreAdapterMongo.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Db<BasicDBObject> getDb(String uri)
|
||||
{
|
||||
DB db = this.getDbInner(uri);
|
||||
return new DbMongo(this, db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getCollnames(Db<?> db)
|
||||
{
|
||||
return ((DbMongo)db).db.getCollectionNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> boolean containsId(Coll<?, L> coll, L id)
|
||||
{
|
||||
DBCollection dbcoll = fixColl(coll);
|
||||
DBCursor cursor = dbcoll.find(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id)));
|
||||
return cursor.count() != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> Long getMtime(Coll<?, L> coll, L id)
|
||||
{
|
||||
DBCollection dbcoll = fixColl(coll);
|
||||
BasicDBObject found = (BasicDBObject)dbcoll.findOne(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id)), dboKeysMtime);
|
||||
if (found == null) return null;
|
||||
if ( ! found.containsField(MTIME_FIELD)) return null; // This should not happen! But better to ignore than crash?
|
||||
return found.getLong(MTIME_FIELD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> Collection<L> getIds(Coll<?, L> coll)
|
||||
{
|
||||
List<L> ret = null;
|
||||
|
||||
DBCollection dbcoll = fixColl(coll);
|
||||
|
||||
DBCursor cursor = dbcoll.find(dboEmpty, dboKeysId);
|
||||
try
|
||||
{
|
||||
ret = new ArrayList<L>(cursor.count());
|
||||
while(cursor.hasNext())
|
||||
{
|
||||
Object remoteId = cursor.next().get(ID_FIELD);
|
||||
L localId = coll.getIdStrategy().remoteToLocal(remoteId);
|
||||
ret.add(localId);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> Map<L, Long> getId2mtime(Coll<?, L> coll)
|
||||
{
|
||||
Map<L, Long> ret = null;
|
||||
|
||||
DBCollection dbcoll = fixColl(coll);
|
||||
|
||||
DBCursor cursor = dbcoll.find(dboEmpty, dboKeysIdandMtime);
|
||||
try
|
||||
{
|
||||
ret = new HashMap<L, Long>(cursor.count());
|
||||
while(cursor.hasNext())
|
||||
{
|
||||
BasicDBObject raw = (BasicDBObject)cursor.next();
|
||||
Object remoteId = raw.get(ID_FIELD);
|
||||
L localId = coll.getIdStrategy().remoteToLocal(remoteId);
|
||||
if ( ! raw.containsField(MTIME_FIELD)) continue; // This should not happen! But better to ignore than crash?
|
||||
Long mtime = raw.getLong(MTIME_FIELD);
|
||||
ret.put(localId, mtime);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> Entry<BasicDBObject, Long> load(Coll<?, L> coll, L id)
|
||||
{
|
||||
DBCollection dbcoll = fixColl(coll);
|
||||
BasicDBObject raw = (BasicDBObject)dbcoll.findOne(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id)));
|
||||
if (raw == null) return null;
|
||||
Long mtime = (Long) raw.removeField(MTIME_FIELD);
|
||||
return new SimpleEntry<BasicDBObject, Long>(raw, mtime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> Long save(Coll<?, L> coll, L id, Object rawData)
|
||||
{
|
||||
DBCollection dbcoll = fixColl(coll);
|
||||
|
||||
// We shallow copy here in order to stop the extra "_mtime" field from messing up the lastRaw.
|
||||
BasicDBObject data = (BasicDBObject)rawData;
|
||||
data = (BasicDBObject)data.clone();
|
||||
Long mtime = System.currentTimeMillis();
|
||||
data.put(MTIME_FIELD, mtime);
|
||||
|
||||
Object remoteId = coll.getIdStrategy().localToRemote(id);
|
||||
dbcoll.update(new BasicDBObject(ID_FIELD, remoteId), data, true, false);
|
||||
|
||||
return mtime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <L> void delete(Coll<?, L> coll, L id)
|
||||
{
|
||||
fixColl(coll).remove(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id)));
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// UTIL
|
||||
//----------------------------------------------//
|
||||
|
||||
protected static DBCollection fixColl(Coll<?, ?> coll)
|
||||
{
|
||||
return (DBCollection) coll.getCollDriverObject();
|
||||
}
|
||||
|
||||
protected DB getDbInner(String uri)
|
||||
{
|
||||
MongoURI muri = new MongoURI(uri);
|
||||
|
||||
try
|
||||
{
|
||||
DB db = muri.connectDB();
|
||||
|
||||
if (muri.getUsername() == null) return db;
|
||||
|
||||
if ( ! db.authenticate(muri.getUsername(), muri.getPassword()))
|
||||
{
|
||||
//log(Level.SEVERE, "... db authentication failed.");
|
||||
return null;
|
||||
}
|
||||
return db;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//log(Level.SEVERE, "... mongo connection failed.");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// CONSTRUCTORS
|
||||
//----------------------------------------------//
|
||||
|
||||
private DriverMongo()
|
||||
{
|
||||
super("mongodb");
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected static DriverMongo instance;
|
||||
public static DriverMongo get()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
instance = new DriverMongo();
|
||||
instance.registerIdStrategy(IdStrategyAiMongo.get());
|
||||
instance.registerIdStrategy(IdStrategyOidMongo.get());
|
||||
instance.registerIdStrategy(IdStrategyUuidMongoAndGson.get());
|
||||
}
|
||||
}
|
||||
119
src/com/massivecraft/mcore5/store/Entity.java
Normal file
119
src/com/massivecraft/mcore5/store/Entity.java
Normal file
@@ -0,0 +1,119 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import com.massivecraft.mcore5.MCore;
|
||||
import com.massivecraft.mcore5.store.accessor.Accessor;
|
||||
import com.massivecraft.mcore5.xlib.gson.Gson;
|
||||
|
||||
/**
|
||||
* Usage of this class is highly optional. You may persist anything. If you are
|
||||
* creating the class to be persisted yourself, it might be handy to extend this
|
||||
* Entity class. It just contains a set of shortcut methods.
|
||||
*/
|
||||
|
||||
// Self referencing generic using the "getThis trick".
|
||||
// http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206
|
||||
public abstract class Entity<E extends Entity<E, L>, L>
|
||||
{
|
||||
protected transient Coll<E, L> coll;
|
||||
protected void setColl(Coll<E, L> val) { this.coll = val; }
|
||||
public Coll<E, L> getColl() { return this.coll; }
|
||||
|
||||
protected abstract E getThis();
|
||||
protected abstract Class<E> getClazz();
|
||||
|
||||
public abstract E getDefaultInstance();
|
||||
|
||||
public String getUniverse()
|
||||
{
|
||||
Coll<E, L> coll = this.getColl();
|
||||
if (coll == null) return null;
|
||||
|
||||
return coll.getUniverse();
|
||||
}
|
||||
|
||||
public L attach(Coll<E, L> coll)
|
||||
{
|
||||
return coll.attach(getThis());
|
||||
}
|
||||
|
||||
public E detach()
|
||||
{
|
||||
Coll<E, L> coll = this.getColl();
|
||||
if (coll == null) return null;
|
||||
|
||||
return coll.detach(getThis());
|
||||
}
|
||||
|
||||
public boolean attached()
|
||||
{
|
||||
Coll<E, L> coll = this.getColl();
|
||||
if (coll == null) return false;
|
||||
|
||||
return coll.getAll().contains(getThis());
|
||||
}
|
||||
|
||||
public boolean detached()
|
||||
{
|
||||
return ! this.attached();
|
||||
}
|
||||
|
||||
public L getId()
|
||||
{
|
||||
Coll<E, L> coll = this.getColl();
|
||||
if (coll == null) return null;
|
||||
return coll.getId(this.getThis());
|
||||
}
|
||||
|
||||
public void changed()
|
||||
{
|
||||
L id = this.getId();
|
||||
if (id == null) return;
|
||||
|
||||
this.getColl().changedIds.add(id);
|
||||
}
|
||||
|
||||
public ModificationState sync()
|
||||
{
|
||||
L id = this.getId();
|
||||
if (id == null) return ModificationState.UNKNOWN;
|
||||
return this.getColl().syncId(id);
|
||||
}
|
||||
|
||||
public void saveToRemote()
|
||||
{
|
||||
L id = this.getId();
|
||||
if (id == null) return;
|
||||
|
||||
this.getColl().saveToRemote(id);
|
||||
}
|
||||
|
||||
public void loadFromRemote()
|
||||
{
|
||||
L id = this.getId();
|
||||
if (id == null) return;
|
||||
|
||||
this.getColl().loadFromRemote(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
Gson gson = MCore.gson;
|
||||
Coll<E, L> coll = this.getColl();
|
||||
if (coll != null) gson = coll.getMplugin().gson;
|
||||
|
||||
return this.getClazz().getSimpleName()+gson.toJson(this, this.getClazz());
|
||||
}
|
||||
|
||||
public E loadDefaults()
|
||||
{
|
||||
Accessor.get(this.getClazz()).copy(this.getDefaultInstance(), this.getThis());
|
||||
return this.getThis();
|
||||
}
|
||||
|
||||
public E load(E that)
|
||||
{
|
||||
Accessor.get(this.getClazz()).copy(that, this.getThis());
|
||||
return this.getThis();
|
||||
}
|
||||
}
|
||||
43
src/com/massivecraft/mcore5/store/ExamineThread.java
Normal file
43
src/com/massivecraft/mcore5/store/ExamineThread.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
public class ExamineThread<E, L> extends Thread
|
||||
{
|
||||
protected Coll<E, L> coll;
|
||||
|
||||
public ExamineThread(Coll<E, L> coll)
|
||||
{
|
||||
this.coll = coll;
|
||||
this.setName("ExamineThread for "+coll.getName());
|
||||
}
|
||||
|
||||
// TODO: Implement logging and/or auto adjusting system for how long the sleep should be?
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
try
|
||||
{
|
||||
//long before = System.currentTimeMillis();
|
||||
|
||||
coll.findSuspects();
|
||||
|
||||
//long after = System.currentTimeMillis();
|
||||
|
||||
//coll.mplugin().log(this.getName()+ " complete. Took "+ (after-before) +"ms.");
|
||||
|
||||
Thread.sleep(5000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// We've been interrupted. Lets bail.
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/com/massivecraft/mcore5/store/JsonFileFilter.java
Normal file
23
src/com/massivecraft/mcore5/store/JsonFileFilter.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
public class JsonFileFilter implements FileFilter
|
||||
{
|
||||
private final static String DOTJSON = ".json";
|
||||
|
||||
@Override
|
||||
public boolean accept(File pathname)
|
||||
{
|
||||
return pathname.getName().toLowerCase().endsWith(DOTJSON);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static JsonFileFilter instance = new JsonFileFilter();
|
||||
public static JsonFileFilter get() { return instance; }
|
||||
|
||||
}
|
||||
53
src/com/massivecraft/mcore5/store/MStore.java
Normal file
53
src/com/massivecraft/mcore5/store/MStore.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.massivecraft.mcore5.MCore;
|
||||
|
||||
|
||||
public class MStore
|
||||
{
|
||||
protected static Map<String, Driver<?>> drivers = new HashMap<String, Driver<?>>();
|
||||
public static boolean registerDriver(Driver<?> driver)
|
||||
{
|
||||
if (drivers.containsKey(driver.getName())) return false;
|
||||
drivers.put(driver.getName(), driver);
|
||||
return true;
|
||||
}
|
||||
public static Driver<?> getDriver(String id)
|
||||
{
|
||||
|
||||
return drivers.get(id);
|
||||
}
|
||||
|
||||
public static Db<?> getDb(String uri)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (uri.equalsIgnoreCase("default")) return MCore.getDb();
|
||||
return getDb(new URI(uri));
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Db<?> getDb(URI uri)
|
||||
{
|
||||
String scheme = uri.getScheme();
|
||||
Driver<?> driver = getDriver(scheme);
|
||||
if (driver == null) return null;
|
||||
return driver.getDb(uri.toString());
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
registerDriver(DriverMongo.get());
|
||||
registerDriver(DriverGson.get());
|
||||
}
|
||||
}
|
||||
75
src/com/massivecraft/mcore5/store/MStoreUtil.java
Normal file
75
src/com/massivecraft/mcore5/store/MStoreUtil.java
Normal file
@@ -0,0 +1,75 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.massivecraft.mcore5.Predictate;
|
||||
|
||||
public class MStoreUtil
|
||||
{
|
||||
public static <T> ArrayList<T> uglySQL(Collection<T> items, Predictate<T> where, Comparator<T> orderby, Integer limit, Integer offset)
|
||||
{
|
||||
ArrayList<T> ret = new ArrayList<T>(items.size());
|
||||
|
||||
// WHERE
|
||||
if (where == null)
|
||||
{
|
||||
ret.addAll(items);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (T item : items)
|
||||
{
|
||||
if (where.apply(item))
|
||||
{
|
||||
ret.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ORDERBY
|
||||
if (orderby != null)
|
||||
{
|
||||
Collections.sort(ret, orderby);
|
||||
}
|
||||
|
||||
// LIMIT AND OFFSET
|
||||
// Parse args
|
||||
int fromIndex = 0;
|
||||
if (offset != null)
|
||||
{
|
||||
fromIndex = offset;
|
||||
}
|
||||
|
||||
int toIndex = ret.size()-1;
|
||||
if (limit != null)
|
||||
{
|
||||
toIndex = offset+limit;
|
||||
}
|
||||
|
||||
// Clean args
|
||||
if (fromIndex <= 0)
|
||||
{
|
||||
fromIndex = 0;
|
||||
}
|
||||
else if (fromIndex > ret.size()-1)
|
||||
{
|
||||
fromIndex = ret.size()-1;
|
||||
}
|
||||
|
||||
if (toIndex < fromIndex)
|
||||
{
|
||||
toIndex = fromIndex;
|
||||
}
|
||||
else if (toIndex > ret.size()-1)
|
||||
{
|
||||
toIndex = ret.size()-1;
|
||||
}
|
||||
|
||||
// No limit?
|
||||
if (fromIndex == 0 && toIndex == ret.size()-1) return ret;
|
||||
return new ArrayList<T>(ret.subList(fromIndex, toIndex));
|
||||
}
|
||||
}
|
||||
28
src/com/massivecraft/mcore5/store/ModificationState.java
Normal file
28
src/com/massivecraft/mcore5/store/ModificationState.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
public enum ModificationState
|
||||
{
|
||||
LOCAL_ALTER (true, true),
|
||||
LOCAL_ATTACH (true, true),
|
||||
LOCAL_DETACH (true, true),
|
||||
REMOTE_ALTER (true, false),
|
||||
REMOTE_ATTACH (true, false),
|
||||
REMOTE_DETACH (true, false),
|
||||
NONE (false, false),
|
||||
UNKNOWN (false, false),
|
||||
;
|
||||
|
||||
private final boolean modified;
|
||||
public boolean isModified() { return this.modified; }
|
||||
|
||||
private final boolean local;
|
||||
public boolean isLocal() { return this.local; }
|
||||
public boolean isRemote() { return this.local == false; }
|
||||
|
||||
private ModificationState(boolean modified, boolean local)
|
||||
{
|
||||
this.modified = modified;
|
||||
this.local = local;
|
||||
}
|
||||
|
||||
}
|
||||
133
src/com/massivecraft/mcore5/store/PlayerColl.java
Normal file
133
src/com/massivecraft/mcore5/store/PlayerColl.java
Normal file
@@ -0,0 +1,133 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.massivecraft.mcore5.MCore;
|
||||
import com.massivecraft.mcore5.MPlugin;
|
||||
import com.massivecraft.mcore5.Predictate;
|
||||
import com.massivecraft.mcore5.cmd.arg.ARStringEntity;
|
||||
import com.massivecraft.mcore5.cmd.arg.ARStringMatchFullCI;
|
||||
import com.massivecraft.mcore5.cmd.arg.ARStringMatchStartCI;
|
||||
import com.massivecraft.mcore5.cmd.arg.ArgReader;
|
||||
import com.massivecraft.mcore5.util.MUtil;
|
||||
import com.massivecraft.mcore5.util.PlayerUtil;
|
||||
|
||||
public class PlayerColl<E extends PlayerEntity<E>> extends Coll<E, String>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
// Note that the lowercasing should be kept at either true or false.
|
||||
protected boolean lowercasing = false;
|
||||
public boolean isLowercasing() { return this.lowercasing; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public PlayerColl(Db<?> db, MPlugin mplugin, String name, Class<E> entityClass, boolean creative, boolean lowercasing)
|
||||
{
|
||||
super(db, mplugin, "ai", name, entityClass, String.class, creative);
|
||||
this.lowercasing = lowercasing;
|
||||
}
|
||||
|
||||
public PlayerColl(Db<?> db, MPlugin mplugin, String name, Class<E> entityClass, boolean creative)
|
||||
{
|
||||
this(db, mplugin, name, entityClass, creative, false);
|
||||
}
|
||||
|
||||
public PlayerColl(Db<?> db, MPlugin mplugin, String name, Class<E> entityClass)
|
||||
{
|
||||
this(db, mplugin, name, entityClass, true);
|
||||
}
|
||||
|
||||
public PlayerColl(MPlugin mplugin, String name, Class<E> entityClass, boolean creative, boolean lowercasing)
|
||||
{
|
||||
this(MCore.getDb(), mplugin, name, entityClass, creative, lowercasing);
|
||||
}
|
||||
|
||||
public PlayerColl(MPlugin mplugin, String name, Class<E> entityClass, boolean creative)
|
||||
{
|
||||
this(MCore.getDb(), mplugin, name, entityClass, creative);
|
||||
}
|
||||
|
||||
public PlayerColl(MPlugin mplugin, String name, Class<E> entityClass)
|
||||
{
|
||||
this(MCore.getDb(), mplugin, name, entityClass);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// EXTRAS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public String fixId(Object oid)
|
||||
{
|
||||
if (oid == null) return null;
|
||||
String ret = MUtil.extract(String.class, "playerName", oid);
|
||||
if (ret == null) return ret;
|
||||
return this.lowercasing ? ret.toLowerCase() : ret;
|
||||
}
|
||||
|
||||
public Collection<E> getAllOnline()
|
||||
{
|
||||
List<E> ret = new ArrayList<E>();
|
||||
for(Player player : Bukkit.getOnlinePlayers())
|
||||
{
|
||||
E entity = this.get(player.getName());
|
||||
if (entity == null) continue;
|
||||
ret.add(entity);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Collection<E> getAllOffline()
|
||||
{
|
||||
return this.getAll(new Predictate<E>()
|
||||
{
|
||||
public boolean apply(E entity)
|
||||
{
|
||||
return entity.isOffline();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ARGUMENT READERS
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected Collection<Collection<String>> forgeAltColls()
|
||||
{
|
||||
Collection<Collection<String>> ret = new ArrayList<Collection<String>>();
|
||||
ret.add(this.getIds());
|
||||
if (this.isCreative()) ret.add(PlayerUtil.getAllVisitorNames());
|
||||
return ret;
|
||||
}
|
||||
|
||||
public ArgReader<String> argReaderPlayerNameFull()
|
||||
{
|
||||
return new ARStringMatchFullCI("player", this.forgeAltColls());
|
||||
}
|
||||
|
||||
public ArgReader<String> argReaderPlayerNameStart()
|
||||
{
|
||||
return new ARStringMatchStartCI("player", this.forgeAltColls());
|
||||
}
|
||||
|
||||
public ArgReader<E> argReaderPlayerFull()
|
||||
{
|
||||
return new ARStringEntity<E>(this.argReaderPlayerNameFull(), this);
|
||||
}
|
||||
|
||||
public ArgReader<E> argReaderPlayerStart()
|
||||
{
|
||||
return new ARStringEntity<E>(this.argReaderPlayerNameStart(), this);
|
||||
}
|
||||
|
||||
}
|
||||
123
src/com/massivecraft/mcore5/store/PlayerEntity.java
Normal file
123
src/com/massivecraft/mcore5/store/PlayerEntity.java
Normal file
@@ -0,0 +1,123 @@
|
||||
package com.massivecraft.mcore5.store;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.massivecraft.mcore5.util.PlayerUtil;
|
||||
import com.massivecraft.mcore5.util.Txt;
|
||||
|
||||
|
||||
public abstract class PlayerEntity<E extends PlayerEntity<E>> extends Entity<E, String>
|
||||
{
|
||||
public Player getPlayer()
|
||||
{
|
||||
if (this.getColl() == null) return null;
|
||||
if (this.getColl().isLowercasing())
|
||||
{
|
||||
return Bukkit.getPlayerExact(this.getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
return PlayerUtil.getPlayerExact(this.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerColl<E> getColl()
|
||||
{
|
||||
return (PlayerColl<E>) super.getColl();
|
||||
}
|
||||
|
||||
public boolean isOnline()
|
||||
{
|
||||
return this.getPlayer() != null;
|
||||
}
|
||||
|
||||
public boolean isOffline()
|
||||
{
|
||||
return ! isOnline();
|
||||
}
|
||||
|
||||
/*public String getCurrentUniverse()
|
||||
{
|
||||
Player player = this.getPlayer();
|
||||
if (player == null) return null;
|
||||
|
||||
String aspectId = this.getColl().nameAspect();
|
||||
Aspect aspect = Aspect.get(aspectId);
|
||||
|
||||
aspect.
|
||||
|
||||
return USelColl.i.get(aspect).select(player.getWorld().getName());
|
||||
|
||||
|
||||
|
||||
|
||||
vi ska returna ett universeId
|
||||
}
|
||||
|
||||
public boolean isInThisUniverse()
|
||||
{
|
||||
String universe = this.getUniverse();
|
||||
if (universe == null) return false;
|
||||
|
||||
String currentUniverse = this.getCurrentUniverse();
|
||||
if (currentUniverse == null) return false;
|
||||
|
||||
return universe.equals(currentUniverse);
|
||||
}*/
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CHECKER UTILS
|
||||
// -------------------------------------------- //
|
||||
public boolean isGameMode(GameMode gm, boolean defaultIfOffline)
|
||||
{
|
||||
Player player = this.getPlayer();
|
||||
if (player == null || ! player.isOnline()) return defaultIfOffline;
|
||||
return player.getGameMode() == gm;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Message Sending Helpers
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void sendMessage(String msg)
|
||||
{
|
||||
Player player = this.getPlayer();
|
||||
if (player == null) return;
|
||||
player.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void sendMessage(Collection<String> msgs)
|
||||
{
|
||||
Player player = this.getPlayer();
|
||||
if (player == null) return;
|
||||
for(String msg : msgs)
|
||||
{
|
||||
player.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void msg(String msg)
|
||||
{
|
||||
this.sendMessage(Txt.parse(msg));
|
||||
}
|
||||
|
||||
public void msg(String msg, Object... args)
|
||||
{
|
||||
this.sendMessage(Txt.parse(msg, args));
|
||||
}
|
||||
|
||||
public void msg(Collection<String> msgs)
|
||||
{
|
||||
Player player = this.getPlayer();
|
||||
if (player == null) return;
|
||||
for(String msg : msgs)
|
||||
{
|
||||
player.sendMessage(Txt.parse(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/com/massivecraft/mcore5/store/accessor/Accessor.java
Normal file
20
src/com/massivecraft/mcore5/store/accessor/Accessor.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class Accessor
|
||||
{
|
||||
private static Map<Class<?>, EntityAccessor> class2EntityAccessor = new HashMap<Class<?>, EntityAccessor>();
|
||||
|
||||
public static EntityAccessor get(Class<?> clazz)
|
||||
{
|
||||
EntityAccessor ret = class2EntityAccessor.get(clazz);
|
||||
if (ret == null)
|
||||
{
|
||||
ret = new EntityAccessorPerProperty(clazz);
|
||||
class2EntityAccessor.put(clazz, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
175
src/com/massivecraft/mcore5/store/accessor/AccessorUtil.java
Normal file
175
src/com/massivecraft/mcore5/store/accessor/AccessorUtil.java
Normal file
@@ -0,0 +1,175 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AccessorUtil
|
||||
{
|
||||
|
||||
//----------------------------------------------//
|
||||
// MAKE ACCESSIBLE
|
||||
//----------------------------------------------//
|
||||
|
||||
public static void makeAccessible(Field field)
|
||||
{
|
||||
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
|
||||
{
|
||||
field.setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void makeAccessible(Method method)
|
||||
{
|
||||
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible())
|
||||
{
|
||||
method.setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// FIND
|
||||
//----------------------------------------------//
|
||||
|
||||
public static List<Method> findMethod(Class<?> clazz, String name)
|
||||
{
|
||||
List<Method> ret = new ArrayList<Method>();
|
||||
for (Class<?> c = clazz; c != null; c = c.getSuperclass())
|
||||
{
|
||||
Method[] methods = (c.isInterface() ? c.getMethods() : c.getDeclaredMethods());
|
||||
for (Method method : methods)
|
||||
{
|
||||
if (name.equals(method.getName())) ret.add(method);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static Field findField(Class<?> clazz, String name)
|
||||
{
|
||||
for (Class<?> c = clazz; c != null && !Object.class.equals(c); c = c.getSuperclass())
|
||||
{
|
||||
Field[] fields = c.getDeclaredFields();
|
||||
for (Field field : fields)
|
||||
{
|
||||
if (name.equals(field.getName())) return field;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<Field> findAllFields(Class<?> clazz)
|
||||
{
|
||||
List<Field> fields = new ArrayList<Field>();
|
||||
for (Class<?> c = clazz; c != null; c = c.getSuperclass())
|
||||
{
|
||||
fields.addAll(Arrays.asList(c.getDeclaredFields()));
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be non-transient.
|
||||
* Must be non-final.
|
||||
* Will be set accessible if possible.
|
||||
*/
|
||||
public static Map<String, Field> getFieldMap(Class<?> clazz)
|
||||
{
|
||||
Map<String, Field> ret = new HashMap<String, Field>();
|
||||
|
||||
for (Field field : findAllFields(clazz))
|
||||
{
|
||||
if (Modifier.isTransient(field.getModifiers())) continue;
|
||||
if (Modifier.isFinal(field.getModifiers())) continue;
|
||||
makeAccessible(field);
|
||||
ret.put(field.getName(), field);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// FIND GETTERS AND SETTERS
|
||||
//----------------------------------------------//
|
||||
|
||||
public static String ucfirst(String str)
|
||||
{
|
||||
return Character.toUpperCase(str.charAt(0))+str.substring(1);
|
||||
}
|
||||
public static String calcGetterNameBool(String fieldName) { return "is"+ucfirst(fieldName); }
|
||||
public static String calcGetterName(String fieldName) { return "get"+ucfirst(fieldName); }
|
||||
public static String calcSetterName(String fieldName) { return "set"+ucfirst(fieldName); }
|
||||
|
||||
// TODO: Use a predictate?
|
||||
public static Method findGetter(Class<?> clazz, String fieldName)
|
||||
{
|
||||
for (Method method : findMethod(clazz, calcGetterName(fieldName)))
|
||||
{
|
||||
if (method.getParameterTypes().length == 0 && method.getReturnType() != null) return method;
|
||||
}
|
||||
|
||||
for (Method method : findMethod(clazz, calcGetterNameBool(fieldName)))
|
||||
{
|
||||
if (method.getParameterTypes().length == 0 && method.getReturnType() == Boolean.class) return method;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Method findSetter(Class<?> clazz, String fieldName)
|
||||
{
|
||||
List<Method> methods = findMethod(clazz, calcSetterName(fieldName));
|
||||
methods.addAll(findMethod(clazz, fieldName));
|
||||
|
||||
for (Method method : methods)
|
||||
{
|
||||
if (method != null && method.getParameterTypes().length == 1) return method;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// CREATE PROPERTY ACCESS
|
||||
//----------------------------------------------//
|
||||
|
||||
public static PropertyGetter createPropertyGetter(Class<?> clazz, String name)
|
||||
{
|
||||
Method method = findGetter(clazz, name);
|
||||
if (method != null) return new PropertyGetterMethodReflection(method);
|
||||
|
||||
Field field = findField(clazz, name);
|
||||
if (field != null) return new PropertyGetterFieldReflection(field);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PropertySetter createPropertySetter(Class<?> clazz, String name)
|
||||
{
|
||||
Method method = findSetter(clazz, name);
|
||||
if (method != null) return new PropertySetterMethodReflection(method);
|
||||
|
||||
Field field = findField(clazz, name);
|
||||
if (field != null) return new PropertySetterFieldReflection(field);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PropertyAccessor createPropertyAccessor(Class<?> clazz, String name)
|
||||
{
|
||||
PropertyGetter getter = createPropertyGetter(clazz, name);
|
||||
if (getter == null) return null;
|
||||
|
||||
PropertySetter setter = createPropertySetter(clazz, name);
|
||||
if (setter == null) return null;
|
||||
|
||||
return new PropertyAccessorComposite(getter, setter);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
public interface EntityAccessor extends EntitySetter, EntityGetter, EntityGlue
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class EntityAccessorAbstract implements EntityAccessor
|
||||
{
|
||||
protected final Class<?> clazz;
|
||||
public Class<?> getClazz() { return this.clazz; }
|
||||
|
||||
public EntityAccessorAbstract(Class<?> clazz)
|
||||
{
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
private static final boolean DEFAULT_TRANSPARENT = false;
|
||||
@Override
|
||||
public void copy(Object from, Object to, String property, boolean transparent)
|
||||
{
|
||||
Object val = this.get(from, property);
|
||||
if (transparent && val == null) return;
|
||||
this.set(to, property, val);
|
||||
}
|
||||
@Override
|
||||
public void copy(Object from, Object to, String property)
|
||||
{
|
||||
this.copy(from, to, property, DEFAULT_TRANSPARENT);
|
||||
}
|
||||
@Override
|
||||
public void copy(Object from, Object to, Collection<String> properties, boolean transparent)
|
||||
{
|
||||
for (String property : properties)
|
||||
{
|
||||
this.copy(from, to, property, transparent);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void copy(Object from, Object to, Collection<String> properties)
|
||||
{
|
||||
this.copy(from, to, properties, DEFAULT_TRANSPARENT);
|
||||
}
|
||||
@Override
|
||||
public void copy(Object from, Object to, boolean transparent)
|
||||
{
|
||||
this.copy(from, to, this.getPropertyNames(), transparent);
|
||||
}
|
||||
@Override
|
||||
public void copy(Object from, Object to)
|
||||
{
|
||||
this.copy(from, to, DEFAULT_TRANSPARENT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EntityAccessorPerProperty extends EntityAccessorAbstract
|
||||
{
|
||||
protected Map<String, PropertyAccessor> propertyAccessors;
|
||||
public Map<String, PropertyAccessor> getPropertyAccessors() { return this.propertyAccessors; }
|
||||
public PropertyAccessor getPropertyAccessor(String name)
|
||||
{
|
||||
PropertyAccessor ret = this.propertyAccessors.get(name);
|
||||
if (ret == null)
|
||||
{
|
||||
throw new IllegalArgumentException("The property \""+name+"\" is not supported.");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
public void setPropertyAccessor(String name, PropertyAccessor val)
|
||||
{
|
||||
this.propertyAccessors.put(name, val);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------//
|
||||
// CONSTRUCTORS
|
||||
//----------------------------------------------//
|
||||
|
||||
public EntityAccessorPerProperty(Class<?> clazz)
|
||||
{
|
||||
super(clazz);
|
||||
this.propertyAccessors = new HashMap<String, PropertyAccessor>();
|
||||
this.populateAI1();
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// AI
|
||||
//----------------------------------------------//
|
||||
|
||||
public void populateAI1()
|
||||
{
|
||||
this.propertyAccessorAI(AccessorUtil.getFieldMap(this.clazz).keySet());
|
||||
}
|
||||
|
||||
public void propertyAccessorAI(String name)
|
||||
{
|
||||
this.propertyAccessors.put(name, AccessorUtil.createPropertyAccessor(this.clazz, name));
|
||||
}
|
||||
public void propertyAccessorAI(String... names)
|
||||
{
|
||||
for (String name : names)
|
||||
{
|
||||
this.propertyAccessorAI(name);
|
||||
}
|
||||
}
|
||||
public void propertyAccessorAI(Collection<? extends String> names)
|
||||
{
|
||||
this.propertyAccessorAI(names.toArray(new String[0]));
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// IMPLEMENTATION
|
||||
//----------------------------------------------//
|
||||
|
||||
@Override
|
||||
public void set(Object entity, String property, Object val)
|
||||
{
|
||||
PropertyAccessor pa = this.getPropertyAccessor(property);
|
||||
pa.set(entity, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object entity, String property)
|
||||
{
|
||||
PropertyAccessor pa = this.getPropertyAccessor(property);
|
||||
return pa.get(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getPropertyNames()
|
||||
{
|
||||
return this.propertyAccessors.keySet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
public interface EntityGetter
|
||||
{
|
||||
public Object get(Object entity, String property);
|
||||
}
|
||||
17
src/com/massivecraft/mcore5/store/accessor/EntityGlue.java
Normal file
17
src/com/massivecraft/mcore5/store/accessor/EntityGlue.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface EntityGlue
|
||||
{
|
||||
public void copy(Object from, Object to, String property, boolean transparent);
|
||||
public void copy(Object from, Object to, String property);
|
||||
|
||||
public void copy(Object from, Object to, Collection<String> properties, boolean transparent);
|
||||
public void copy(Object from, Object to, Collection<String> properties);
|
||||
|
||||
public void copy(Object from, Object to, boolean transparent);
|
||||
public void copy(Object from, Object to);
|
||||
|
||||
public Collection<String> getPropertyNames();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
public interface EntitySetter
|
||||
{
|
||||
public void set(Object entity, String property, Object val);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
public interface PropertyAccessor extends PropertySetter, PropertyGetter
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
public class PropertyAccessorComposite implements PropertyAccessor
|
||||
{
|
||||
private final PropertyGetter getter;
|
||||
private final PropertySetter setter;
|
||||
|
||||
public PropertyAccessorComposite(PropertyGetter getter, PropertySetter setter)
|
||||
{
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Object entity, Object val)
|
||||
{
|
||||
this.setter.set(entity, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object entity)
|
||||
{
|
||||
return this.getter.get(entity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
public interface PropertyGetter
|
||||
{
|
||||
public Object get(Object entity);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class PropertyGetterFieldReflection implements PropertyGetter
|
||||
{
|
||||
private final Field field;
|
||||
|
||||
public PropertyGetterFieldReflection(Field field)
|
||||
{
|
||||
AccessorUtil.makeAccessible(field);
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object entity)
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.field.get(entity);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class PropertyGetterMethodReflection implements PropertyGetter
|
||||
{
|
||||
private final Method method;
|
||||
|
||||
public PropertyGetterMethodReflection(Method method)
|
||||
{
|
||||
AccessorUtil.makeAccessible(method);
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object entity)
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.method.invoke(entity, new Object[0]);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
public interface PropertySetter
|
||||
{
|
||||
public void set(Object entity, Object val);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class PropertySetterFieldReflection implements PropertySetter
|
||||
{
|
||||
private final Field field;
|
||||
|
||||
public PropertySetterFieldReflection(Field field)
|
||||
{
|
||||
AccessorUtil.makeAccessible(field);
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Object entity, Object val)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.field.set(entity, val);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.massivecraft.mcore5.store.accessor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class PropertySetterMethodReflection implements PropertySetter
|
||||
{
|
||||
private final Method method;
|
||||
|
||||
public PropertySetterMethodReflection(Method method)
|
||||
{
|
||||
AccessorUtil.makeAccessible(method);
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Object entity, Object val)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.method.invoke(entity, val);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
29
src/com/massivecraft/mcore5/store/idstrategy/IdStrategy.java
Normal file
29
src/com/massivecraft/mcore5/store/idstrategy/IdStrategy.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.massivecraft.mcore5.store.idstrategy;
|
||||
|
||||
import com.massivecraft.mcore5.store.CollInterface;
|
||||
|
||||
/**
|
||||
* The tasks of the IdStrategy:
|
||||
* 1. Generate a new free id that has not yet been used.
|
||||
* 2. Convert the id between java object and raw database data.
|
||||
*
|
||||
* To complete the tasks the IdStrategy must be tailored for a specific database-driver.
|
||||
* Thus you will find multiple implementations with the name "ai" (auto increment).
|
||||
* There must be one implementation per driver.
|
||||
*/
|
||||
public interface IdStrategy<L, R>
|
||||
{
|
||||
// The name of the strategy (such as "auto_increment")
|
||||
public String getName();
|
||||
|
||||
// The id classes
|
||||
public Class<L> getLocalClass();
|
||||
public Class<R> getRemoteClass();
|
||||
|
||||
// Convert
|
||||
public R localToRemote(Object local);
|
||||
public L remoteToLocal(Object remote);
|
||||
|
||||
// Generate
|
||||
public L generate(CollInterface<?, L> coll);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.massivecraft.mcore5.store.idstrategy;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.massivecraft.mcore5.store.CollInterface;
|
||||
|
||||
public abstract class IdStrategyAbstract<L, R> implements IdStrategy<L, R>
|
||||
{
|
||||
public IdStrategyAbstract(String name, Class<L> localClass, Class<R> remoteClass)
|
||||
{
|
||||
this.name = name;
|
||||
this.localClass = localClass;
|
||||
this.remoteClass = remoteClass;
|
||||
}
|
||||
|
||||
protected String name;
|
||||
@Override public String getName() { return this.name; }
|
||||
|
||||
protected Class<L> localClass;
|
||||
@Override public Class<L> getLocalClass() { return this.localClass; }
|
||||
|
||||
protected Class<R> remoteClass;
|
||||
@Override public Class<R> getRemoteClass() { return this.remoteClass; }
|
||||
|
||||
|
||||
@Override
|
||||
public L generate(CollInterface<?, L> coll)
|
||||
{
|
||||
Collection<L> alreadyInUse = coll.getIds();
|
||||
L ret = null;
|
||||
do
|
||||
{
|
||||
ret = this.generateAttempt(coll);
|
||||
if (ret == null) return null;
|
||||
}
|
||||
while (alreadyInUse.contains(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public abstract L generateAttempt(CollInterface<?, L> coll);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.massivecraft.mcore5.store.idstrategy;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.massivecraft.mcore5.store.CollInterface;
|
||||
import com.massivecraft.mcore5.store.DbGson;
|
||||
import com.massivecraft.mcore5.util.DiscUtil;
|
||||
|
||||
public class IdStrategyAiGson extends IdStrategyAbstract<String, String>
|
||||
{
|
||||
|
||||
//----------------------------------------------//
|
||||
// CONSTRUCTORS
|
||||
//----------------------------------------------//
|
||||
|
||||
private IdStrategyAiGson()
|
||||
{
|
||||
super("ai", String.class, String.class);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override public String localToRemote(Object local) { return (String)local; }
|
||||
@Override public String remoteToLocal(Object remote) { return (String)remote; }
|
||||
|
||||
@Override
|
||||
public String generateAttempt(CollInterface<?, String> coll)
|
||||
{
|
||||
File file = getAiFile(coll);
|
||||
|
||||
// Ensure the file exists
|
||||
if (this.ensureFileExists(file) == false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String content = DiscUtil.readCatch(file);
|
||||
if (content == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Integer current = 0;
|
||||
if (content.length() > 0)
|
||||
{
|
||||
current = Integer.valueOf(content);
|
||||
}
|
||||
|
||||
Integer next = current + 1;
|
||||
if (DiscUtil.writeCatch(file, next.toString()) == false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return current.toString();
|
||||
|
||||
}
|
||||
|
||||
protected File getAiFile(CollInterface<?, String> coll)
|
||||
{
|
||||
DbGson cdb = (DbGson)coll.getDb();
|
||||
return new File(cdb.dir, coll.getName() + "_ai.txt");
|
||||
}
|
||||
|
||||
protected boolean ensureFileExists(File file)
|
||||
{
|
||||
if (file.isFile()) return true;
|
||||
if (file.isDirectory()) return false;
|
||||
try
|
||||
{
|
||||
return file.createNewFile();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected static IdStrategyAiGson instance = new IdStrategyAiGson();
|
||||
public static IdStrategyAiGson get()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.massivecraft.mcore5.store.idstrategy;
|
||||
|
||||
import com.massivecraft.mcore5.store.CollInterface;
|
||||
import com.massivecraft.mcore5.store.DbMongo;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.BasicDBObject;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.DBCollection;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.DBObject;
|
||||
|
||||
public class IdStrategyAiMongo extends IdStrategyAbstract<String, String>
|
||||
{
|
||||
private static String SEC = "seq";
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
// String sequenseName;
|
||||
// DBCollection sequenseCollection;
|
||||
String sequenseField;
|
||||
|
||||
//----------------------------------------------//
|
||||
// CONSTRUCTORS
|
||||
//----------------------------------------------//
|
||||
|
||||
private IdStrategyAiMongo()
|
||||
{
|
||||
super("ai", String.class, String.class);
|
||||
this.sequenseField = SEC;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override public String localToRemote(Object local) { return (String)local; }
|
||||
@Override public String remoteToLocal(Object remote) { return (String)remote; }
|
||||
|
||||
// http://dev.bubblemix.net/blog/2011/04/auto-increment-for-mongodb-with-the-java-driver/
|
||||
@Override
|
||||
public String generateAttempt(CollInterface<?, String> coll)
|
||||
{
|
||||
String sequenseName = coll.getName();
|
||||
DBCollection sequenseCollection = ((DbMongo)coll.getDb()).db.getCollection(SEC);
|
||||
|
||||
// this object represents your "query", its analogous to a WHERE clause in SQL
|
||||
DBObject query = new BasicDBObject();
|
||||
query.put("_id", sequenseName); // where _id = the input sequence name
|
||||
|
||||
// this object represents the "update" or the SET blah=blah in SQL
|
||||
DBObject change = new BasicDBObject(this.sequenseField, 1);
|
||||
DBObject update = new BasicDBObject("$inc", change); // the $inc here is a mongodb command for increment
|
||||
|
||||
// Atomically updates the sequence field and returns the value for you
|
||||
DBObject res = sequenseCollection.findAndModify(query, new BasicDBObject(), new BasicDBObject(), false, update, true, true);
|
||||
return res.get(this.sequenseField).toString();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected static IdStrategyAiMongo instance = new IdStrategyAiMongo();
|
||||
public static IdStrategyAiMongo get()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.massivecraft.mcore5.store.idstrategy;
|
||||
|
||||
import com.massivecraft.mcore5.store.CollInterface;
|
||||
import com.massivecraft.mcore5.xlib.bson.types.ObjectId;
|
||||
|
||||
public class IdStrategyOidGson extends IdStrategyAbstract<ObjectId, String>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override public String localToRemote(Object local) { return ((ObjectId)local).toStringBabble(); }
|
||||
@Override public ObjectId remoteToLocal(Object remote) { return ObjectId.massageToObjectId((String)remote); }
|
||||
|
||||
@Override
|
||||
public ObjectId generateAttempt(CollInterface<?, ObjectId> coll)
|
||||
{
|
||||
return ObjectId.get();
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// CONSTRUCTORS
|
||||
//----------------------------------------------//
|
||||
|
||||
private IdStrategyOidGson()
|
||||
{
|
||||
super("oid", ObjectId.class, String.class);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected static IdStrategyOidGson instance = new IdStrategyOidGson();
|
||||
public static IdStrategyOidGson get()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.massivecraft.mcore5.store.idstrategy;
|
||||
|
||||
import com.massivecraft.mcore5.store.CollInterface;
|
||||
import com.massivecraft.mcore5.xlib.bson.types.ObjectId;
|
||||
|
||||
public class IdStrategyOidMongo extends IdStrategyAbstract<ObjectId, ObjectId>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override public ObjectId localToRemote(Object local) { return (ObjectId)local; }
|
||||
@Override public ObjectId remoteToLocal(Object remote) { return (ObjectId)remote; }
|
||||
|
||||
@Override
|
||||
public ObjectId generateAttempt(CollInterface<?, ObjectId> coll)
|
||||
{
|
||||
return ObjectId.get();
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// CONSTRUCTORS
|
||||
//----------------------------------------------//
|
||||
|
||||
private IdStrategyOidMongo()
|
||||
{
|
||||
super("oid", ObjectId.class, ObjectId.class);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected static IdStrategyOidMongo instance = new IdStrategyOidMongo();
|
||||
public static IdStrategyOidMongo get()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.massivecraft.mcore5.store.idstrategy;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.massivecraft.mcore5.store.CollInterface;
|
||||
|
||||
public class IdStrategyUuidMongoAndGson extends IdStrategyAbstract<UUID, String>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// IMPLEMENTATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override public String localToRemote(Object local) { return ((UUID)local).toString(); }
|
||||
@Override public UUID remoteToLocal(Object remote) { return UUID.fromString((String)remote); }
|
||||
|
||||
@Override
|
||||
public UUID generateAttempt(CollInterface<?, UUID> coll)
|
||||
{
|
||||
return UUID.randomUUID();
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// CONSTRUCTORS
|
||||
//----------------------------------------------//
|
||||
|
||||
private IdStrategyUuidMongoAndGson()
|
||||
{
|
||||
super("uuid", UUID.class, String.class);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected static IdStrategyUuidMongoAndGson instance = new IdStrategyUuidMongoAndGson();
|
||||
public static IdStrategyUuidMongoAndGson get()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package com.massivecraft.mcore5.store.storeadapter;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.massivecraft.mcore5.xlib.bson.types.ObjectId;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonArray;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonElement;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonNull;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonObject;
|
||||
import com.massivecraft.mcore5.xlib.gson.JsonPrimitive;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.BasicDBList;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.BasicDBObject;
|
||||
import com.massivecraft.mcore5.xlib.mongodb.DBObject;
|
||||
|
||||
public final class MongoGsonConverter
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// GSON 2 MONGO
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static BasicDBObject gson2MongoObject(JsonElement inElement)
|
||||
{
|
||||
JsonObject in = inElement.getAsJsonObject();
|
||||
BasicDBObject out = new BasicDBObject();
|
||||
for (Entry<String, JsonElement> entry : in.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
JsonElement val = entry.getValue();
|
||||
if (val.isJsonArray())
|
||||
{
|
||||
out.put(key, gson2MongoArray(val));
|
||||
}
|
||||
else if (val.isJsonObject())
|
||||
{
|
||||
out.put(key, gson2MongoObject(val));
|
||||
}
|
||||
else
|
||||
{
|
||||
out.put(key, gson2MongoPrimitive(val));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static BasicDBList gson2MongoArray(JsonElement inElement)
|
||||
{
|
||||
JsonArray in = inElement.getAsJsonArray();
|
||||
BasicDBList out = new BasicDBList();
|
||||
for (int i = 0; i < in.size(); i++)
|
||||
{
|
||||
JsonElement element = in.get(i);
|
||||
if (element.isJsonArray())
|
||||
{
|
||||
out.add(gson2MongoArray(element));
|
||||
}
|
||||
else if (element.isJsonObject())
|
||||
{
|
||||
out.add(gson2MongoObject(element));
|
||||
}
|
||||
else
|
||||
{
|
||||
out.add(gson2MongoPrimitive(element));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static Object gson2MongoPrimitive(JsonElement inElement)
|
||||
{
|
||||
if (inElement.isJsonNull()) return null;
|
||||
JsonPrimitive in = inElement.getAsJsonPrimitive();
|
||||
if (in.isBoolean()) return in.getAsBoolean();
|
||||
if (in.isNumber()) return in.getAsNumber();
|
||||
if (in.isString()) return in.getAsString();
|
||||
throw new IllegalArgumentException("Unsupported value type for: " + in);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// MONGO 2 GSON
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static JsonObject mongo2GsonObject(DBObject inObject)
|
||||
{
|
||||
if (!(inObject instanceof BasicDBObject)) throw new IllegalArgumentException("Expected BasicDBObject as argument type!");
|
||||
BasicDBObject in = (BasicDBObject)inObject;
|
||||
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
for (Entry<String, Object> entry : in.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
Object val = entry.getValue();
|
||||
if (val instanceof BasicDBList)
|
||||
{
|
||||
jsonObject.add(key, mongo2GsonArray((BasicDBList)val));
|
||||
}
|
||||
else if (val instanceof BasicDBObject)
|
||||
{
|
||||
jsonObject.add(key, mongo2GsonObject((BasicDBObject)val));
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonObject.add(key, mongo2GsonPrimitive(val));
|
||||
}
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
public static JsonArray mongo2GsonArray(DBObject inObject)
|
||||
{
|
||||
if (!(inObject instanceof BasicDBList)) throw new IllegalArgumentException("Expected BasicDBList as argument type!");
|
||||
BasicDBList in = (BasicDBList)inObject;
|
||||
JsonArray jsonArray = new JsonArray();
|
||||
for (int i = 0; i < in.size(); i++)
|
||||
{
|
||||
Object object = in.get(i);
|
||||
if (object instanceof BasicDBList)
|
||||
{
|
||||
jsonArray.add(mongo2GsonArray((BasicDBList) object));
|
||||
}
|
||||
else if (object instanceof BasicDBObject)
|
||||
{
|
||||
jsonArray.add(mongo2GsonObject((BasicDBObject) object));
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonArray.add(mongo2GsonPrimitive(object));
|
||||
}
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
public static JsonElement mongo2GsonPrimitive(Object inObject)
|
||||
{
|
||||
if (inObject == null) return JsonNull.INSTANCE;
|
||||
if (inObject instanceof Boolean) return new JsonPrimitive((Boolean) inObject);
|
||||
if (inObject instanceof Number) return new JsonPrimitive((Number) inObject);
|
||||
if (inObject instanceof String) return new JsonPrimitive((String) inObject);
|
||||
if (inObject instanceof Character) return new JsonPrimitive((Character) inObject);
|
||||
if (inObject instanceof ObjectId) return new JsonPrimitive(inObject.toString());
|
||||
throw new IllegalArgumentException("Unsupported value type for: " + inObject);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user