In progress: Using MassiveCraftCore and Allman indentation style and minor refactoring.
This commit is contained in:
@ -0,0 +1,9 @@
|
||||
package com.massivecraft.factions.zcore;
|
||||
|
||||
public enum CommandVisibility
|
||||
{
|
||||
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.
|
||||
;
|
||||
}
|
429
src/com/massivecraft/factions/zcore/MCommand.java
Normal file
429
src/com/massivecraft/factions/zcore/MCommand.java
Normal file
@ -0,0 +1,429 @@
|
||||
package com.massivecraft.factions.zcore;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.massivecraft.factions.zcore.MCommand;
|
||||
import com.massivecraft.factions.zcore.MPlugin;
|
||||
import com.massivecraft.factions.zcore.util.TextUtil;
|
||||
|
||||
|
||||
public abstract class MCommand<T extends MPlugin>
|
||||
{
|
||||
public T p;
|
||||
|
||||
// The sub-commands to this command
|
||||
public List<MCommand<?>> subCommands;
|
||||
|
||||
// The different names this commands will react to
|
||||
public List<String> aliases;
|
||||
public boolean allowNoSlashAccess;
|
||||
|
||||
// Information on the args
|
||||
public List<String> requiredArgs;
|
||||
public LinkedHashMap<String, String> optionalArgs;
|
||||
|
||||
// Help info
|
||||
public String helpShort;
|
||||
public List<String> helpLong;
|
||||
public CommandVisibility visibility;
|
||||
|
||||
// Some information on permissions
|
||||
public boolean senderMustBePlayer;
|
||||
public String permission;
|
||||
|
||||
// Information available on execution of the command
|
||||
public CommandSender sender; // Will always be set
|
||||
public Player player; // Will only be set when the sender is a player
|
||||
public List<String> args; // Will contain the arguments, or and empty list if there are none.
|
||||
public List<MCommand<?>> commandChain; // The command chain used to execute this command
|
||||
|
||||
public MCommand(T p)
|
||||
{
|
||||
this.p = p;
|
||||
|
||||
this.permission = null;
|
||||
|
||||
this.allowNoSlashAccess = false;
|
||||
|
||||
this.subCommands = new ArrayList<MCommand<?>>();
|
||||
this.aliases = new ArrayList<String>();
|
||||
|
||||
this.requiredArgs = new ArrayList<String>();
|
||||
this.optionalArgs = new LinkedHashMap<String, String>();
|
||||
|
||||
this.helpShort = "*Default helpShort*";
|
||||
this.helpLong = new ArrayList<String>();
|
||||
this.visibility = CommandVisibility.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;
|
||||
if (sender instanceof Player)
|
||||
{
|
||||
this.player = (Player)sender;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.player = null;
|
||||
}
|
||||
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 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.
|
||||
*/
|
||||
|
||||
// TODO: There should be a boolean for silence
|
||||
public boolean validCall(CommandSender sender, List<String> args)
|
||||
{
|
||||
if ( ! validSenderType(sender, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! validSenderPermissions(sender, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! validArgs(args, sender))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean validSenderType(CommandSender sender, boolean informSenderIfNot)
|
||||
{
|
||||
if (this.senderMustBePlayer && ! (sender instanceof Player))
|
||||
{
|
||||
if (informSenderIfNot)
|
||||
{
|
||||
sender.sendMessage(p.txt.get("command.sender_must_me_player"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean validSenderPermissions(CommandSender sender, boolean informSenderIfNot)
|
||||
{
|
||||
if (this.permission == null) return true;
|
||||
return p.perm.has(sender, this.permission, informSenderIfNot);
|
||||
}
|
||||
|
||||
public boolean validArgs(List<String> args, CommandSender sender)
|
||||
{
|
||||
if (args.size() < this.requiredArgs.size())
|
||||
{
|
||||
if (sender != null)
|
||||
{
|
||||
sender.sendMessage(p.txt.get("command.to_few_args"));
|
||||
sender.sendMessage(this.getUseageTemplate());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.size() > this.requiredArgs.size() + this.optionalArgs.size())
|
||||
{
|
||||
if (sender != null)
|
||||
{
|
||||
// Get the to many string slice
|
||||
List<String> theToMany = args.subList(this.requiredArgs.size() + this.optionalArgs.size(), args.size());
|
||||
sender.sendMessage(String.format(p.txt.get("command.to_many_args"), TextUtil.implode(theToMany, " ")));
|
||||
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 addShortHelp)
|
||||
{
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ret.append(p.txt.tags("<c>"));
|
||||
ret.append('/');
|
||||
|
||||
for (MCommand<?> mc : commandChain)
|
||||
{
|
||||
ret.append(TextUtil.implode(mc.aliases, ","));
|
||||
ret.append(' ');
|
||||
}
|
||||
|
||||
ret.append(TextUtil.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(p.txt.tags("<p> "));
|
||||
ret.append(TextUtil.implode(args, " "));
|
||||
}
|
||||
|
||||
if (addShortHelp)
|
||||
{
|
||||
ret.append(p.txt.tags(" <i>"));
|
||||
ret.append(this.helpShort);
|
||||
}
|
||||
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
public String getUseageTemplate(boolean addShortHelp)
|
||||
{
|
||||
return getUseageTemplate(this.commandChain, addShortHelp);
|
||||
}
|
||||
|
||||
public String getUseageTemplate()
|
||||
{
|
||||
return getUseageTemplate(false);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Message Sending Helpers
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void msg(String msg, boolean parseColors)
|
||||
{
|
||||
if (parseColors)
|
||||
{
|
||||
sender.sendMessage(p.txt.tags(msg));
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void msg(String msg)
|
||||
{
|
||||
this.msg(msg, false);
|
||||
}
|
||||
|
||||
public void msg(List<String> msgs, boolean parseColors)
|
||||
{
|
||||
for(String msg : msgs)
|
||||
{
|
||||
this.msg(msg, parseColors);
|
||||
}
|
||||
}
|
||||
|
||||
public void msg(List<String> msgs)
|
||||
{
|
||||
msg(msgs, false);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Argument Readers
|
||||
// -------------------------------------------- //
|
||||
|
||||
// STRING
|
||||
public String argAsString(int idx, String def)
|
||||
{
|
||||
if (this.args.size() < idx+1)
|
||||
{
|
||||
return def;
|
||||
}
|
||||
return this.args.get(idx);
|
||||
}
|
||||
public String argAsString(int idx)
|
||||
{
|
||||
return this.argAsString(idx, null);
|
||||
}
|
||||
|
||||
// INT
|
||||
public int argAsInt(int idx, int def)
|
||||
{
|
||||
String str = this.argAsString(idx);
|
||||
if (str == null) return def;
|
||||
try
|
||||
{
|
||||
int ret = Integer.parseInt(str);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return def;
|
||||
}
|
||||
}
|
||||
public int argAsInt(int idx)
|
||||
{
|
||||
return this.argAsInt(idx, -1);
|
||||
}
|
||||
|
||||
// Double
|
||||
public double argAsDouble(int idx, double def)
|
||||
{
|
||||
String str = this.argAsString(idx);
|
||||
if (str == null) return def;
|
||||
try
|
||||
{
|
||||
double ret = Double.parseDouble(str);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return def;
|
||||
}
|
||||
}
|
||||
public double argAsDouble(int idx)
|
||||
{
|
||||
return this.argAsDouble(idx, -1d);
|
||||
}
|
||||
|
||||
// Boolean
|
||||
public boolean argAsBool(int idx, boolean def)
|
||||
{
|
||||
String str = this.argAsString(idx);
|
||||
if (str == null) return def;
|
||||
|
||||
str = str.toLowerCase();
|
||||
if (str.startsWith("y") || str.startsWith("t") || str.startsWith("on") || str.startsWith("+") || str.startsWith("1"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean argAsBool(int idx)
|
||||
{
|
||||
return this.argAsBool(idx, false);
|
||||
}
|
||||
|
||||
// PLAYER
|
||||
public Player argAsPlayer(int idx, Player def, boolean msg)
|
||||
{
|
||||
Player ret = def;
|
||||
|
||||
String name = this.argAsString(idx);
|
||||
if (name != null)
|
||||
{
|
||||
Player player = Bukkit.getServer().getPlayer(name);
|
||||
if (player != null)
|
||||
{
|
||||
ret = player;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg && ret == null)
|
||||
{
|
||||
// TODO: Fix this injection risk!
|
||||
this.msg(p.txt.tags("<b>The player \"<p>"+name+"<b>\" could not be found."));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
public Player argAsPlayer(int idx, Player def)
|
||||
{
|
||||
return this.argAsPlayer(idx, def, true);
|
||||
}
|
||||
public Player argAsPlayer(int idx)
|
||||
{
|
||||
return this.argAsPlayer(idx, null);
|
||||
}
|
||||
|
||||
// BEST PLAYER MATCH
|
||||
public Player argAsBestPlayerMatch(int idx, Player def, boolean msg)
|
||||
{
|
||||
Player ret = def;
|
||||
|
||||
String name = this.argAsString(idx);
|
||||
if (name != null)
|
||||
{
|
||||
List<Player> players = Bukkit.getServer().matchPlayer(name);
|
||||
if (players.size() > 0)
|
||||
{
|
||||
ret = players.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (msg && ret == null)
|
||||
{
|
||||
// TODO: Fix this injection risk!
|
||||
this.msg(p.txt.tags("<b>No player match found for \"<p>"+name+"<b>\"."));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
public Player argAsBestPlayerMatch(int idx, Player def)
|
||||
{
|
||||
return this.argAsBestPlayerMatch(idx, def, true);
|
||||
}
|
||||
public Player argAsBestPlayerMatch(int idx)
|
||||
{
|
||||
return this.argAsPlayer(idx, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
236
src/com/massivecraft/factions/zcore/MPlugin.java
Normal file
236
src/com/massivecraft/factions/zcore/MPlugin.java
Normal file
@ -0,0 +1,236 @@
|
||||
package com.massivecraft.factions.zcore;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.massivecraft.factions.zcore.persist.EM;
|
||||
import com.massivecraft.factions.zcore.persist.SaveTask;
|
||||
import com.massivecraft.factions.zcore.util.LibLoader;
|
||||
import com.massivecraft.factions.zcore.util.PermUtil;
|
||||
import com.massivecraft.factions.zcore.util.Persist;
|
||||
import com.massivecraft.factions.zcore.util.TextUtil;
|
||||
|
||||
|
||||
public abstract class MPlugin extends JavaPlugin
|
||||
{
|
||||
// Some utils
|
||||
public Persist persist;
|
||||
public TextUtil txt;
|
||||
public LibLoader lib;
|
||||
public PermUtil perm;
|
||||
|
||||
// Persist related
|
||||
public Gson gson;
|
||||
private Integer saveTask = null;
|
||||
|
||||
// Listeners
|
||||
private MPluginSecretPlayerListener mPluginSecretPlayerListener;
|
||||
private MPluginSecretServerListener mPluginSecretServerListener;
|
||||
|
||||
// Our stored base commands
|
||||
private List<MCommand<?>> baseCommands = new ArrayList<MCommand<?>>();
|
||||
public List<MCommand<?>> getBaseCommands() { return this.baseCommands; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ENABLE
|
||||
// -------------------------------------------- //
|
||||
private long timeEnableStart;
|
||||
public boolean preEnable()
|
||||
{
|
||||
log("=== ENABLE START ===");
|
||||
timeEnableStart = System.currentTimeMillis();
|
||||
|
||||
// Ensure basefolder exists!
|
||||
this.getDataFolder().mkdirs();
|
||||
|
||||
// Create Utility Instances
|
||||
this.perm = new PermUtil(this);
|
||||
this.persist = new Persist(this);
|
||||
this.lib = new LibLoader(this);
|
||||
|
||||
if ( ! lib.require("gson.jar", "http://search.maven.org/remotecontent?filepath=com/google/code/gson/gson/1.7.1/gson-1.7.1.jar")) return false;
|
||||
this.gson = this.getGsonBuilder().create();
|
||||
|
||||
initTXT();
|
||||
|
||||
// Create and register listeners
|
||||
this.mPluginSecretPlayerListener = new MPluginSecretPlayerListener(this);
|
||||
this.mPluginSecretServerListener = new MPluginSecretServerListener(this);
|
||||
PluginManager pm = this.getServer().getPluginManager();
|
||||
pm.registerEvent(Event.Type.PLAYER_PRELOGIN, this.mPluginSecretPlayerListener, Event.Priority.Lowest, this);
|
||||
pm.registerEvent(Event.Type.PLAYER_CHAT, this.mPluginSecretPlayerListener, Event.Priority.Low, this);
|
||||
pm.registerEvent(Event.Type.PLAYER_COMMAND_PREPROCESS, this.mPluginSecretPlayerListener, Event.Priority.Lowest, this);
|
||||
pm.registerEvent(Event.Type.SERVER_COMMAND, this.mPluginSecretServerListener, Event.Priority.Lowest, this);
|
||||
|
||||
|
||||
// Register recurring tasks
|
||||
long saveTicks = 20 * 60 * 30; // Approximately every 30 min
|
||||
if (saveTask == null)
|
||||
{
|
||||
saveTask = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new SaveTask(), saveTicks, saveTicks);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void postEnable()
|
||||
{
|
||||
log("=== ENABLE DONE (Took "+(System.currentTimeMillis()-timeEnableStart)+"ms) ===");
|
||||
}
|
||||
|
||||
public void onDisable()
|
||||
{
|
||||
if (saveTask != null)
|
||||
{
|
||||
this.getServer().getScheduler().cancelTask(saveTask);
|
||||
saveTask = null;
|
||||
}
|
||||
EM.saveAllToDisc();
|
||||
log("Disabled");
|
||||
}
|
||||
|
||||
public void suicide()
|
||||
{
|
||||
log("Now I suicide!");
|
||||
this.getServer().getPluginManager().disablePlugin(this);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Some inits...
|
||||
// You are supposed to override these in the plugin if you aren't satisfied with the defaults
|
||||
// The goal is that you always will be satisfied though.
|
||||
// -------------------------------------------- //
|
||||
|
||||
public GsonBuilder getGsonBuilder()
|
||||
{
|
||||
return new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.serializeNulls()
|
||||
.excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// LANG AND TAGS
|
||||
// -------------------------------------------- //
|
||||
|
||||
// These are not supposed to be used directly.
|
||||
// They are loaded and used through the TextUtil instance for the plugin.
|
||||
public Map<String, String> tags = new LinkedHashMap<String, String>();
|
||||
public Map<String, String> lang = new LinkedHashMap<String, String>();
|
||||
|
||||
public void addLang()
|
||||
{
|
||||
this.lang.put("perm.forbidden", "<b>You don't have permission to %s.");
|
||||
this.lang.put("perm.dothat", "do that");
|
||||
this.lang.put("command.sender_must_me_player", "<b>This command can only be used by ingame players.");
|
||||
this.lang.put("command.to_few_args", "<b>To few arguments. <i>Use like this:");
|
||||
this.lang.put("command.to_many_args", "<b>Strange argument \"<p>%s<b>\". <i>Use the command like this:");
|
||||
}
|
||||
|
||||
public void addTags()
|
||||
{
|
||||
this.tags.put("black", "§0");
|
||||
this.tags.put("navy", "§1");
|
||||
this.tags.put("green", "§2");
|
||||
this.tags.put("teal", "§3");
|
||||
this.tags.put("red", "§4");
|
||||
this.tags.put("purple", "§5");
|
||||
this.tags.put("gold", "§6");
|
||||
this.tags.put("silver", "§7");
|
||||
this.tags.put("gray", "§8");
|
||||
this.tags.put("blue", "§9");
|
||||
this.tags.put("white", "§f");
|
||||
this.tags.put("lime", "§a");
|
||||
this.tags.put("aqua", "§b");
|
||||
this.tags.put("rose", "§c");
|
||||
this.tags.put("pink", "§d");
|
||||
this.tags.put("yellow", "§e");
|
||||
|
||||
this.tags.put("l", "§2"); // logo
|
||||
this.tags.put("a", "§6"); // art
|
||||
this.tags.put("n", "§7"); // notice
|
||||
this.tags.put("i", "§e"); // info
|
||||
this.tags.put("g", "§a"); // good
|
||||
this.tags.put("b", "§c"); // bad
|
||||
this.tags.put("h", "§d"); // highligh
|
||||
this.tags.put("c", "§b"); // command
|
||||
this.tags.put("p", "§3"); // parameter
|
||||
}
|
||||
|
||||
public void initTXT()
|
||||
{
|
||||
this.addLang();
|
||||
this.addTags();
|
||||
|
||||
Type type = new TypeToken<Map<String, String>>(){}.getType();
|
||||
|
||||
Map<String, String> langFromFile = this.persist.load(type, "lang");
|
||||
if (langFromFile != null) this.lang.putAll(langFromFile);
|
||||
this.persist.save(this.lang, "lang");
|
||||
|
||||
Map<String, String> tagsFromFile = this.persist.load(type, "tags");
|
||||
if (tagsFromFile != null) this.tags.putAll(tagsFromFile);
|
||||
this.persist.save(this.tags, "tags");
|
||||
|
||||
this.txt = new TextUtil(this.tags, this.lang);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COMMAND HANDLING
|
||||
// -------------------------------------------- //
|
||||
|
||||
public boolean handleCommand(CommandSender sender, String commandString)
|
||||
{
|
||||
boolean noSlash = false;
|
||||
if (commandString.startsWith("/"))
|
||||
{
|
||||
noSlash = true;
|
||||
commandString = commandString.substring(1);
|
||||
}
|
||||
|
||||
for (MCommand<?> command : this.getBaseCommands())
|
||||
{
|
||||
if (noSlash && ! command.allowNoSlashAccess) continue;
|
||||
|
||||
for (String alias : command.aliases)
|
||||
{
|
||||
if (commandString.startsWith(alias) || commandString.equals(alias+" "))
|
||||
{
|
||||
List<String> args = new ArrayList<String>(Arrays.asList(commandString.split("\\s+")));
|
||||
args.remove(0);
|
||||
command.execute(sender, args);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------- //
|
||||
// LOGGING
|
||||
// -------------------------------------------- //
|
||||
public void log(Object msg)
|
||||
{
|
||||
log(Level.INFO, msg);
|
||||
}
|
||||
|
||||
public void log(Level level, Object msg)
|
||||
{
|
||||
Logger.getLogger("Minecraft").log(level, "["+this.getDescription().getFullName()+"] "+msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.massivecraft.factions.zcore;
|
||||
|
||||
import org.bukkit.event.player.PlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerListener;
|
||||
import org.bukkit.event.player.PlayerPreLoginEvent;
|
||||
|
||||
import com.massivecraft.factions.zcore.persist.EM;
|
||||
import com.massivecraft.factions.zcore.persist.Entity;
|
||||
import com.massivecraft.factions.zcore.persist.EntityCollection;
|
||||
import com.massivecraft.factions.zcore.persist.PlayerEntityCollection;
|
||||
|
||||
public class MPluginSecretPlayerListener extends PlayerListener
|
||||
{
|
||||
private MPlugin p;
|
||||
public MPluginSecretPlayerListener(MPlugin p)
|
||||
{
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event)
|
||||
{
|
||||
if (event.isCancelled()) return;
|
||||
|
||||
if (p.handleCommand(event.getPlayer(), event.getMessage()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerChat(PlayerChatEvent event)
|
||||
{
|
||||
if (event.isCancelled()) return;
|
||||
|
||||
if (p.handleCommand(event.getPlayer(), event.getMessage()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerPreLogin(PlayerPreLoginEvent event)
|
||||
{
|
||||
for (EntityCollection<? extends Entity> ecoll : EM.class2Entities.values())
|
||||
{
|
||||
if (ecoll instanceof PlayerEntityCollection)
|
||||
{
|
||||
ecoll.get(event.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.massivecraft.factions.zcore;
|
||||
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
import org.bukkit.event.server.ServerListener;
|
||||
|
||||
public class MPluginSecretServerListener extends ServerListener
|
||||
{
|
||||
private MPlugin p;
|
||||
public MPluginSecretServerListener(MPlugin p)
|
||||
{
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
// This method is not perfect. It says unknown console command.
|
||||
@Override
|
||||
public void onServerCommand(ServerCommandEvent event)
|
||||
{
|
||||
if (event.getCommand().length() == 0) return;
|
||||
|
||||
if (p.handleCommand(event.getSender(), event.getCommand()))
|
||||
{
|
||||
event.setCommand("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
74
src/com/massivecraft/factions/zcore/persist/EM.java
Normal file
74
src/com/massivecraft/factions/zcore/persist/EM.java
Normal file
@ -0,0 +1,74 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.massivecraft.factions.zcore.persist.Entity;
|
||||
import com.massivecraft.factions.zcore.persist.EntityCollection;
|
||||
|
||||
public class EM
|
||||
{
|
||||
public static Map<Class<? extends Entity>, EntityCollection<? extends Entity>> class2Entities = new LinkedHashMap<Class<? extends Entity>, EntityCollection<? extends Entity>>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> EntityCollection<T> getEntitiesCollectionForEntityClass(Class<T> entityClass)
|
||||
{
|
||||
return (EntityCollection<T>) class2Entities.get(entityClass);
|
||||
}
|
||||
|
||||
public static void setEntitiesCollectionForEntityClass(Class<? extends Entity> entityClass, EntityCollection<? extends Entity> entities)
|
||||
{
|
||||
class2Entities.put(entityClass, entities);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> void attach(T entity)
|
||||
{
|
||||
EntityCollection<T> ec = (EntityCollection<T>) getEntitiesCollectionForEntityClass(entity.getClass());
|
||||
ec.attach(entity);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> void detach(T entity)
|
||||
{
|
||||
EntityCollection<T> ec = (EntityCollection<T>) getEntitiesCollectionForEntityClass(entity.getClass());
|
||||
ec.detach(entity);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> boolean attached(T entity)
|
||||
{
|
||||
EntityCollection<T> ec = (EntityCollection<T>) getEntitiesCollectionForEntityClass(entity.getClass());
|
||||
return ec.attached(entity);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> boolean detached(T entity)
|
||||
{
|
||||
EntityCollection<T> ec = (EntityCollection<T>) getEntitiesCollectionForEntityClass(entity.getClass());
|
||||
return ec.detached(entity);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// DISC
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static void saveAllToDisc()
|
||||
{
|
||||
for (EntityCollection<? extends Entity> ec : class2Entities.values())
|
||||
{
|
||||
ec.saveToDisc();
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadAllFromDisc()
|
||||
{
|
||||
for (EntityCollection<? extends Entity> ec : class2Entities.values())
|
||||
{
|
||||
ec.loadFromDisc();
|
||||
}
|
||||
}
|
||||
}
|
65
src/com/massivecraft/factions/zcore/persist/Entity.java
Normal file
65
src/com/massivecraft/factions/zcore/persist/Entity.java
Normal file
@ -0,0 +1,65 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
public abstract class Entity
|
||||
{
|
||||
public Entity()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected transient String id = null;
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
protected void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean shouldBeSaved()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void attach()
|
||||
{
|
||||
EM.attach(this);
|
||||
}
|
||||
|
||||
public void detach()
|
||||
{
|
||||
EM.detach(this);
|
||||
}
|
||||
|
||||
public boolean attached()
|
||||
{
|
||||
return EM.attached(this);
|
||||
}
|
||||
|
||||
public boolean detached()
|
||||
{
|
||||
return EM.detached(this);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// EVENTS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void preDetach()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void postDetach()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,250 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.massivecraft.factions.zcore.util.DiscUtil;
|
||||
|
||||
public abstract class EntityCollection<E extends Entity>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
// These must be instantiated in order to allow for different configuration (orders, comparators etc)
|
||||
private Collection<E> entities;
|
||||
private Map<String, E> id2entity;
|
||||
|
||||
// If the entities are creative they will create a new instance if a non existent id was requested
|
||||
private boolean creative;
|
||||
public boolean isCreative() { return creative; }
|
||||
public void setCreative(boolean creative) { this.creative = creative; }
|
||||
|
||||
// This is the auto increment for the primary key "id"
|
||||
private int nextId;
|
||||
|
||||
// This ugly crap is necessary due to java type erasure
|
||||
private Class<E> entityClass;
|
||||
public abstract Type getMapType(); // This is special stuff for GSON.
|
||||
|
||||
// Info on how to persist
|
||||
private Gson gson;
|
||||
public Gson getGson() { return gson; }
|
||||
public void setGson(Gson gson) { this.gson = gson; }
|
||||
|
||||
private File file;
|
||||
public File getFile() { return file; }
|
||||
public void setFile(File file) { this.file = file; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCTORS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public EntityCollection(Class<E> entityClass, Collection<E> entities, Map<String, E> id2entity, File file, Gson gson, boolean creative)
|
||||
{
|
||||
this.entityClass = entityClass;
|
||||
this.entities = entities;
|
||||
this.id2entity = id2entity;
|
||||
this.file = file;
|
||||
this.gson = gson;
|
||||
this.creative = creative;
|
||||
this.nextId = 1;
|
||||
|
||||
EM.setEntitiesCollectionForEntityClass(this.entityClass, this);
|
||||
}
|
||||
|
||||
public EntityCollection(Class<E> entityClass, Collection<E> entities, Map<String, E> id2entity, File file, Gson gson)
|
||||
{
|
||||
this(entityClass, entities, id2entity, file, gson, false);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// GET
|
||||
// -------------------------------------------- //
|
||||
|
||||
public Collection<E> get()
|
||||
{
|
||||
return entities;
|
||||
}
|
||||
|
||||
public Map<String, E> getMap()
|
||||
{
|
||||
return this.id2entity;
|
||||
}
|
||||
|
||||
public E get(String id)
|
||||
{
|
||||
if (this.creative) return this.getCreative(id);
|
||||
return id2entity.get(id);
|
||||
}
|
||||
|
||||
public E getCreative(String id)
|
||||
{
|
||||
E e = id2entity.get(id);
|
||||
if (e != null) return e;
|
||||
return this.create(id);
|
||||
}
|
||||
|
||||
public boolean exists(String id)
|
||||
{
|
||||
return id2entity.get(id) != null;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CREATE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public E create()
|
||||
{
|
||||
return this.create(this.getNextId());
|
||||
}
|
||||
|
||||
public E create(String id)
|
||||
{
|
||||
if ( ! this.isIdFree(id)) return null;
|
||||
|
||||
E e = null;
|
||||
try
|
||||
{
|
||||
e = this.entityClass.newInstance();
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
e.setId(id);
|
||||
this.entities.add(e);
|
||||
this.id2entity.put(e.getId(), e);
|
||||
this.updateNextIdForId(id);
|
||||
return e;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void attach(E entity)
|
||||
{
|
||||
if (entity.getId() != null) return;
|
||||
entity.setId(this.getNextId());
|
||||
this.entities.add(entity);
|
||||
this.id2entity.put(entity.getId(), entity);
|
||||
}
|
||||
|
||||
public void detach(E entity)
|
||||
{
|
||||
entity.preDetach();
|
||||
this.entities.remove(entity);
|
||||
this.id2entity.remove(entity.getId());
|
||||
entity.postDetach();
|
||||
}
|
||||
|
||||
public void detach(String id)
|
||||
{
|
||||
E entity = this.id2entity.get(id);
|
||||
if (entity == null) return;
|
||||
this.detach(entity);
|
||||
}
|
||||
|
||||
public boolean attached(E entity)
|
||||
{
|
||||
return this.entities.contains(entity);
|
||||
}
|
||||
|
||||
public boolean detached(E entity)
|
||||
{
|
||||
return ! this.attached(entity);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// DISC
|
||||
// -------------------------------------------- //
|
||||
|
||||
public boolean saveToDisc()
|
||||
{
|
||||
Map<String, E> entitiesThatShouldBeSaved = new HashMap<String, E>();
|
||||
for (E entity : this.entities)
|
||||
{
|
||||
if (entity.shouldBeSaved())
|
||||
{
|
||||
entitiesThatShouldBeSaved.put(entity.getId(), entity);
|
||||
}
|
||||
}
|
||||
|
||||
return this.saveCore(entitiesThatShouldBeSaved);
|
||||
}
|
||||
|
||||
private boolean saveCore(Map<String, E> entities)
|
||||
{
|
||||
return DiscUtil.writeCatch(this.file, this.gson.toJson(entities));
|
||||
}
|
||||
|
||||
public boolean loadFromDisc()
|
||||
{
|
||||
Map<String, E> id2entity = this.loadCore();
|
||||
if (id2entity == null) return false;
|
||||
this.entities.clear();
|
||||
this.entities.addAll(id2entity.values());
|
||||
this.id2entity.clear();
|
||||
this.id2entity.putAll(id2entity);
|
||||
this.fillIds();
|
||||
return true;
|
||||
}
|
||||
|
||||
private Map<String, E> loadCore()
|
||||
{
|
||||
if ( ! this.file.exists())
|
||||
{
|
||||
return new HashMap<String, E>();
|
||||
}
|
||||
|
||||
String content = DiscUtil.readCatch(this.file);
|
||||
if (content == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Type type = this.getMapType();
|
||||
return this.gson.fromJson(content, type);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ID MANAGEMENT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public String getNextId()
|
||||
{
|
||||
this.nextId += 1;
|
||||
return "" + (nextId - 1);
|
||||
}
|
||||
|
||||
public boolean isIdFree(String id)
|
||||
{
|
||||
return ! this.id2entity.containsKey(id);
|
||||
}
|
||||
|
||||
protected void fillIds()
|
||||
{
|
||||
this.nextId = 1;
|
||||
for(Entry<String, E> entry : this.id2entity.entrySet())
|
||||
{
|
||||
String id = entry.getKey();
|
||||
E entity = entry.getValue();
|
||||
entity.id = id;
|
||||
this.updateNextIdForId(id);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateNextIdForId(String id)
|
||||
{
|
||||
try
|
||||
{
|
||||
int idAsInt = Integer.parseInt(id);
|
||||
if (this.nextId < idAsInt)
|
||||
{
|
||||
this.nextId = idAsInt + 1;
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlayerEntity extends Entity
|
||||
{
|
||||
public Player getPlayer()
|
||||
{
|
||||
return Bukkit.getPlayer(this.getId());
|
||||
}
|
||||
|
||||
public boolean isOnline()
|
||||
{
|
||||
return this.getPlayer() != null;
|
||||
}
|
||||
|
||||
public boolean isOffline()
|
||||
{
|
||||
return ! isOnline();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Message Sending Helpers
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void sendMessage(String msg)
|
||||
{
|
||||
Player player = this.getPlayer();
|
||||
if (player == null) return;
|
||||
player.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void sendMessage(List<String> msgs)
|
||||
{
|
||||
for(String msg : msgs)
|
||||
{
|
||||
this.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* The PlayerEntityCollection is an EntityCollection with the extra features
|
||||
* a player skin usually requires.
|
||||
*
|
||||
* This entity collection is not only creative. It even creates the instance for the player
|
||||
* when the player logs in to the server.
|
||||
*
|
||||
* This way we can be sure that PlayerEntityCollection.get() will contain
|
||||
* all entities in PlayerEntityCollection.getOnline()
|
||||
*/
|
||||
public abstract class PlayerEntityCollection<E extends Entity> extends EntityCollection<E>
|
||||
{
|
||||
public PlayerEntityCollection(Class<E> entityClass, Collection<E> entities, Map<String, E> id2entity, File file, Gson gson)
|
||||
{
|
||||
super(entityClass, entities, id2entity, file, gson, true);
|
||||
}
|
||||
|
||||
public E get(Player player)
|
||||
{
|
||||
return this.get(player.getName());
|
||||
}
|
||||
|
||||
public Set<E> getOnline()
|
||||
{
|
||||
Set<E> entities = new HashSet<E>();
|
||||
for (Player player : Bukkit.getServer().getOnlinePlayers())
|
||||
{
|
||||
entities.add(this.get(player));
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
public class SaveTask implements Runnable
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
EM.saveAllToDisc();
|
||||
}
|
||||
}
|
51
src/com/massivecraft/factions/zcore/util/ClassLoadHack.java
Normal file
51
src/com/massivecraft/factions/zcore/util/ClassLoadHack.java
Normal file
@ -0,0 +1,51 @@
|
||||
package com.massivecraft.factions.zcore.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
public class ClassLoadHack {
|
||||
|
||||
private static URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
|
||||
|
||||
public static boolean load(String filename)
|
||||
{
|
||||
return load(new File(filename));
|
||||
}
|
||||
|
||||
public static boolean load(File file)
|
||||
{
|
||||
try
|
||||
{
|
||||
return load(file.toURI().toURL());
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean load(URL url)
|
||||
{
|
||||
// If the file already is loaded we can skip it
|
||||
for (URL otherUrl : sysloader.getURLs())
|
||||
{
|
||||
if (otherUrl.sameFile(url)) return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Method addURLMethod = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{ URL.class });
|
||||
addURLMethod.setAccessible(true);
|
||||
addURLMethod.invoke(sysloader, new Object[]{ url });
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
78
src/com/massivecraft/factions/zcore/util/DiscUtil.java
Normal file
78
src/com/massivecraft/factions/zcore/util/DiscUtil.java
Normal file
@ -0,0 +1,78 @@
|
||||
package com.massivecraft.factions.zcore.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
|
||||
public class DiscUtil
|
||||
{
|
||||
public static void write(File file, String content) throws IOException
|
||||
{
|
||||
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, false), "UTF8"));
|
||||
out.write(content);
|
||||
out.close();
|
||||
}
|
||||
|
||||
public static String read(File file) throws IOException
|
||||
{
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
|
||||
String ret = new String(new byte[0], "UTF-8");
|
||||
|
||||
String line;
|
||||
while ((line = in.readLine()) != null)
|
||||
{
|
||||
ret += line;
|
||||
}
|
||||
|
||||
in.close();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static boolean writeCatch(File file, String content)
|
||||
{
|
||||
try
|
||||
{
|
||||
write(file, content);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String readCatch(File file)
|
||||
{
|
||||
try
|
||||
{
|
||||
return read(file);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean downloadUrl(String urlstring, File file)
|
||||
{
|
||||
try
|
||||
{
|
||||
URL url = new URL(urlstring);
|
||||
ReadableByteChannel rbc = Channels.newChannel(url.openStream());
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.getChannel().transferFrom(rbc, 0, 1 << 24);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean downloadUrl(String urlstring, String filename)
|
||||
{
|
||||
return downloadUrl(urlstring, new File(filename));
|
||||
}
|
||||
}
|
50
src/com/massivecraft/factions/zcore/util/LibLoader.java
Normal file
50
src/com/massivecraft/factions/zcore/util/LibLoader.java
Normal file
@ -0,0 +1,50 @@
|
||||
package com.massivecraft.factions.zcore.util;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.massivecraft.factions.zcore.MPlugin;
|
||||
|
||||
public class LibLoader
|
||||
{
|
||||
MPlugin p;
|
||||
public LibLoader(MPlugin p)
|
||||
{
|
||||
this.p = p;
|
||||
new File("./lib").mkdirs();
|
||||
}
|
||||
|
||||
public boolean require(String filename, String url)
|
||||
{
|
||||
if ( ! include(filename, url))
|
||||
{
|
||||
p.log("Failed to load the required library "+filename);
|
||||
p.suicide();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean include (String filename, String url)
|
||||
{
|
||||
File file = getFile(filename);
|
||||
if ( ! file.exists())
|
||||
{
|
||||
p.log("Downloading library "+filename);
|
||||
if ( ! DiscUtil.downloadUrl(url, file))
|
||||
{
|
||||
p.log("Failed to download "+filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return ClassLoadHack.load(file);
|
||||
}
|
||||
|
||||
private static File getFile(String filename)
|
||||
{
|
||||
return new File("./lib/"+filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
128
src/com/massivecraft/factions/zcore/util/PermUtil.java
Normal file
128
src/com/massivecraft/factions/zcore/util/PermUtil.java
Normal file
@ -0,0 +1,128 @@
|
||||
package com.massivecraft.factions.zcore.util;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import ru.tehkode.permissions.PermissionManager;
|
||||
import ru.tehkode.permissions.bukkit.PermissionsEx;
|
||||
|
||||
import com.massivecraft.factions.zcore.MPlugin;
|
||||
import com.nijiko.permissions.PermissionHandler;
|
||||
import com.nijikokun.bukkit.Permissions.Permissions;
|
||||
|
||||
|
||||
public class PermUtil {
|
||||
|
||||
public PermissionManager pex = null;
|
||||
public PermissionHandler perm2or3 = null;
|
||||
public Map<String, String> permissionDescriptions = new HashMap<String, String>();
|
||||
|
||||
protected MPlugin p;
|
||||
|
||||
public PermUtil(MPlugin p)
|
||||
{
|
||||
this.p = p;
|
||||
this.setup();
|
||||
}
|
||||
|
||||
public String getForbiddenMessage(String perm)
|
||||
{
|
||||
return p.txt.get("perm.forbidden", getPermissionDescription(perm));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method hooks into all permission plugins we are supporting
|
||||
*/
|
||||
public void setup()
|
||||
{
|
||||
for(Permission permission : p.getDescription().getPermissions())
|
||||
{
|
||||
this.permissionDescriptions.put(permission.getName(), permission.getDescription());
|
||||
}
|
||||
|
||||
if ( Bukkit.getServer().getPluginManager().isPluginEnabled("PermissionsEx"))
|
||||
{
|
||||
pex = PermissionsEx.getPermissionManager();
|
||||
p.log("Will use this plugin for permissions: " + Bukkit.getServer().getPluginManager().getPlugin("PermissionsEx").getDescription().getFullName());
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Bukkit.getServer().getPluginManager().isPluginEnabled("Permissions"))
|
||||
{
|
||||
Plugin permissionsPlugin = Bukkit.getServer().getPluginManager().getPlugin("Permissions");
|
||||
perm2or3 = ((Permissions) permissionsPlugin).getHandler();
|
||||
p.log("Will use this plugin for permissions: " + permissionsPlugin.getDescription().getFullName());
|
||||
return;
|
||||
}
|
||||
|
||||
p.log("No permission plugin detected. Defaulting to native bukkit permissions.");
|
||||
}
|
||||
|
||||
public String getPermissionDescription (String perm)
|
||||
{
|
||||
String desc = permissionDescriptions.get(perm);
|
||||
if (desc == null)
|
||||
{
|
||||
return p.txt.get("perm.dothat");
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tests if me has a certain permission and returns
|
||||
* true if me has. Otherwise false
|
||||
*/
|
||||
public boolean has (CommandSender me, String perm)
|
||||
{
|
||||
if ( ! (me instanceof Player))
|
||||
{
|
||||
return me.hasPermission(perm);
|
||||
}
|
||||
|
||||
if (pex != null)
|
||||
{
|
||||
return pex.has((Player)me, perm);
|
||||
}
|
||||
|
||||
if (perm2or3 != null)
|
||||
{
|
||||
return perm2or3.has((Player)me, perm);
|
||||
}
|
||||
|
||||
return me.hasPermission(perm);
|
||||
}
|
||||
|
||||
public boolean has (CommandSender me, String perm, boolean informSenderIfNot)
|
||||
{
|
||||
if (has(me, perm))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (informSenderIfNot)
|
||||
{
|
||||
me.sendMessage(this.getForbiddenMessage(perm));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public <T> T pickFirstVal(CommandSender me, Map<String, T> perm2val)
|
||||
{
|
||||
if (perm2val == null) return null;
|
||||
T ret = null;
|
||||
|
||||
for ( Entry<String, T> entry : perm2val.entrySet())
|
||||
{
|
||||
ret = entry.getValue();
|
||||
if (has(me, entry.getKey())) break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
154
src/com/massivecraft/factions/zcore/util/Persist.java
Normal file
154
src/com/massivecraft/factions/zcore/util/Persist.java
Normal file
@ -0,0 +1,154 @@
|
||||
package com.massivecraft.factions.zcore.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.massivecraft.factions.zcore.MPlugin;
|
||||
|
||||
// TODO: Give better name and place to differenciate from the entity-orm-ish system in "com.massivecraft.core.persist".
|
||||
|
||||
public class Persist {
|
||||
|
||||
private MPlugin p;
|
||||
public Persist(MPlugin p)
|
||||
{
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ //
|
||||
// GET NAME - What should we call this type of object?
|
||||
// ------------------------------------------------------------ //
|
||||
|
||||
public static String getName(Class<?> clazz)
|
||||
{
|
||||
return clazz.getSimpleName().toLowerCase();
|
||||
}
|
||||
|
||||
public static String getName(Object o)
|
||||
{
|
||||
return getName(o.getClass());
|
||||
}
|
||||
|
||||
public static String getName(Type type)
|
||||
{
|
||||
return getName(type.getClass());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ //
|
||||
// GET FILE - In which file would we like to store this object?
|
||||
// ------------------------------------------------------------ //
|
||||
|
||||
public File getFile(String name)
|
||||
{
|
||||
return new File(p.getDataFolder(), name+".json");
|
||||
}
|
||||
|
||||
public File getFile(Class<?> clazz)
|
||||
{
|
||||
return getFile(getName(clazz));
|
||||
}
|
||||
|
||||
public File getFile(Object obj)
|
||||
{
|
||||
return getFile(getName(obj));
|
||||
}
|
||||
|
||||
public File getFile(Type type)
|
||||
{
|
||||
return getFile(getName(type));
|
||||
}
|
||||
|
||||
|
||||
// NICE WRAPPERS
|
||||
|
||||
public <T> T loadOrSaveDefault(T def, Class<T> clazz)
|
||||
{
|
||||
return loadOrSaveDefault(def, clazz, getFile(clazz));
|
||||
}
|
||||
|
||||
public <T> T loadOrSaveDefault(T def, Class<T> clazz, String name)
|
||||
{
|
||||
return loadOrSaveDefault(def, clazz, getFile(name));
|
||||
}
|
||||
|
||||
public <T> T loadOrSaveDefault(T def, Class<T> clazz, File file)
|
||||
{
|
||||
if ( ! file.exists())
|
||||
{
|
||||
p.log("Creating default: "+file);
|
||||
this.save(def, file);
|
||||
return def;
|
||||
}
|
||||
|
||||
T loaded = this.load(clazz, file);
|
||||
|
||||
if (loaded == null)
|
||||
{
|
||||
p.log(Level.WARNING, "Using default as I failed to load: "+file);
|
||||
return def;
|
||||
}
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
// SAVE
|
||||
|
||||
public boolean save(Object instance)
|
||||
{
|
||||
return save(instance, getFile(instance));
|
||||
}
|
||||
|
||||
public boolean save(Object instance, String name)
|
||||
{
|
||||
return save(instance, getFile(name));
|
||||
}
|
||||
|
||||
public boolean save(Object instance, File file)
|
||||
{
|
||||
return DiscUtil.writeCatch(file, p.gson.toJson(instance));
|
||||
}
|
||||
|
||||
// LOAD BY CLASS
|
||||
|
||||
public <T> T load(Class<T> clazz)
|
||||
{
|
||||
return load(clazz, getFile(clazz));
|
||||
}
|
||||
|
||||
public <T> T load(Class<T> clazz, String name)
|
||||
{
|
||||
return load(clazz, getFile(name));
|
||||
}
|
||||
|
||||
public <T> T load(Class<T> clazz, File file)
|
||||
{
|
||||
String content = DiscUtil.readCatch(file);
|
||||
if (content == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
T instance = p.gson.fromJson(content, clazz);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
// LOAD BY TYPE
|
||||
public <T> T load(Type typeOfT, String name)
|
||||
{
|
||||
return load(typeOfT, getFile(name));
|
||||
}
|
||||
|
||||
public <T> T load(Type typeOfT, File file)
|
||||
{
|
||||
String content = DiscUtil.readCatch(file);
|
||||
if (content == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return p.gson.fromJson(content, typeOfT);
|
||||
}
|
||||
|
||||
}
|
245
src/com/massivecraft/factions/zcore/util/TextUtil.java
Normal file
245
src/com/massivecraft/factions/zcore/util/TextUtil.java
Normal file
@ -0,0 +1,245 @@
|
||||
package com.massivecraft.factions.zcore.util;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
|
||||
public class TextUtil
|
||||
{
|
||||
private Map<String, String> tags = new HashMap<String, String>();
|
||||
private Map<String, String> lang = new HashMap<String, String>();
|
||||
|
||||
public TextUtil(Map<String, String> tags, Map<String, String> lang)
|
||||
{
|
||||
if (tags != null)
|
||||
{
|
||||
this.tags.putAll(tags);
|
||||
}
|
||||
|
||||
if (lang != null)
|
||||
{
|
||||
this.lang.putAll(lang);
|
||||
}
|
||||
}
|
||||
|
||||
// Get is supposed to be the way we reach registered lang
|
||||
// TODO: Is the parse
|
||||
public String get(String name)
|
||||
{
|
||||
String str = lang.get(name);
|
||||
if (str == null) str = name;
|
||||
|
||||
return this.parse(str);
|
||||
}
|
||||
|
||||
public String get(String name, Object... args)
|
||||
{
|
||||
String str = lang.get(name);
|
||||
if (str == null) str = name;
|
||||
|
||||
return this.parse(str, args);
|
||||
}
|
||||
|
||||
// Parse is used to handle non registered text
|
||||
public String parse(String str, Object... args)
|
||||
{
|
||||
return String.format(this.tags(str), args);
|
||||
}
|
||||
|
||||
public String parse(String str)
|
||||
{
|
||||
return this.tags(str);
|
||||
}
|
||||
|
||||
public Map<String, String> getTags()
|
||||
{
|
||||
return tags;
|
||||
}
|
||||
|
||||
public Map<String, String> getLang()
|
||||
{
|
||||
return lang;
|
||||
}
|
||||
|
||||
public String tags(String str)
|
||||
{
|
||||
return replaceTags(str, this.tags);
|
||||
}
|
||||
|
||||
public static final transient Pattern patternTag = Pattern.compile("<([^<>]*)>");
|
||||
public static String replaceTags(String str, Map<String, String> tags)
|
||||
{
|
||||
StringBuffer ret = new StringBuffer();
|
||||
Matcher matcher = patternTag.matcher(str);
|
||||
while (matcher.find())
|
||||
{
|
||||
String tag = matcher.group(1);
|
||||
String repl = tags.get(tag);
|
||||
if (repl == null)
|
||||
{
|
||||
matcher.appendReplacement(ret, "<"+tag+">");
|
||||
}
|
||||
else
|
||||
{
|
||||
matcher.appendReplacement(ret, repl);
|
||||
}
|
||||
}
|
||||
matcher.appendTail(ret);
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
public static String implode(List<String> list, String glue)
|
||||
{
|
||||
StringBuilder ret = new StringBuilder();
|
||||
for (int i=0; i<list.size(); i++)
|
||||
{
|
||||
if (i!=0)
|
||||
{
|
||||
ret.append(glue);
|
||||
}
|
||||
ret.append(list.get(i));
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
public static String repeat(String s, int times)
|
||||
{
|
||||
if (times <= 0) return "";
|
||||
else return s + repeat(s, times-1);
|
||||
}
|
||||
|
||||
public static String getMaterialName(Material material)
|
||||
{
|
||||
return material.toString().replace('_', ' ').toLowerCase();
|
||||
}
|
||||
|
||||
public static String getMaterialName(int materialId)
|
||||
{
|
||||
return getMaterialName(Material.getMaterial(materialId));
|
||||
}
|
||||
|
||||
public static String upperCaseFirst(String string)
|
||||
{
|
||||
return string.substring(0, 1).toUpperCase()+string.substring(1);
|
||||
}
|
||||
|
||||
// TODO: Make part of layout configuration.
|
||||
private final static String titleizeLine = repeat("_", 52);
|
||||
private final static int titleizeBalance = -1;
|
||||
public String titleize(String str)
|
||||
{
|
||||
String center = ".[ "+ tags("<l>") + str + tags("<a>")+ " ].";
|
||||
int centerlen = ChatColor.stripColor(center).length();
|
||||
int pivot = titleizeLine.length() / 2;
|
||||
int eatLeft = (centerlen / 2) - titleizeBalance;
|
||||
int eatRight = (centerlen - eatLeft) + titleizeBalance;
|
||||
|
||||
if (eatLeft < pivot)
|
||||
return tags("<a>")+titleizeLine.substring(0, pivot - eatLeft) + center + titleizeLine.substring(pivot + eatRight);
|
||||
else
|
||||
return tags("<a>")+center;
|
||||
}
|
||||
|
||||
public ArrayList<String> getPage(List<String> lines, int pageHumanBased, String title)
|
||||
{
|
||||
ArrayList<String> ret = new ArrayList<String>();
|
||||
int pageZeroBased = pageHumanBased - 1;
|
||||
int pageheight = 9;
|
||||
int pagecount = (lines.size() / pageheight)+1;
|
||||
|
||||
ret.add(this.titleize(title+" "+pageHumanBased+"/"+pagecount));
|
||||
|
||||
if (pagecount == 0)
|
||||
{
|
||||
ret.add(this.tags("<i>Sorry. No Pages available."));
|
||||
return ret;
|
||||
}
|
||||
else if (pageZeroBased < 0 || pageHumanBased > pagecount)
|
||||
{
|
||||
ret.add(this.tags("<i>Invalid page. Must be between 1 and "+pagecount));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int from = pageZeroBased * pageheight;
|
||||
int to = from+pageheight;
|
||||
if (to > lines.size())
|
||||
{
|
||||
to = lines.size();
|
||||
}
|
||||
|
||||
ret.addAll(lines.subList(from, to));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Using this function you transform a delta in milliseconds
|
||||
* to a String like "2 weeks from now" or "7 days ago".
|
||||
*/
|
||||
public static final long millisPerSecond = 1000;
|
||||
public static final long millisPerMinute = 60 * millisPerSecond;
|
||||
public static final long millisPerHour = 60 * millisPerMinute;
|
||||
public static final long millisPerDay = 24 * millisPerHour;
|
||||
public static final long millisPerWeek = 7 * millisPerDay;
|
||||
public static final long millisPerMonth = 31 * millisPerDay;
|
||||
public static final long millisPerYear = 365 * millisPerDay;
|
||||
public static String getTimeDeltaDescriptionRelNow(long millis)
|
||||
{
|
||||
double absmillis = (double) Math.abs(millis);
|
||||
String agofromnow = "from now";
|
||||
String unit;
|
||||
long num;
|
||||
if (millis <= 0)
|
||||
{
|
||||
agofromnow = "ago";
|
||||
}
|
||||
|
||||
// We use a factor 3 below for a reason... why do you think?
|
||||
// Answer: it is a way to make our round of error smaller.
|
||||
if (absmillis < 3 * millisPerSecond)
|
||||
{
|
||||
unit = "milliseconds";
|
||||
num = (long) (absmillis);
|
||||
}
|
||||
else if (absmillis < 3 * millisPerMinute)
|
||||
{
|
||||
unit = "seconds";
|
||||
num = (long) (absmillis / millisPerSecond);
|
||||
}
|
||||
else if (absmillis < 3 * millisPerHour)
|
||||
{
|
||||
unit = "minutes";
|
||||
num = (long) (absmillis / millisPerMinute);
|
||||
}
|
||||
else if (absmillis < 3 * millisPerDay)
|
||||
{
|
||||
unit = "hours";
|
||||
num = (long) (absmillis / millisPerHour);
|
||||
}
|
||||
else if (absmillis < 3 * millisPerWeek)
|
||||
{
|
||||
unit = "days";
|
||||
num = (long) (absmillis / millisPerDay);
|
||||
}
|
||||
else if (absmillis < 3 * millisPerMonth)
|
||||
{
|
||||
unit = "weeks";
|
||||
num = (long) (absmillis / millisPerWeek);
|
||||
}
|
||||
else if (absmillis < 3 * millisPerYear)
|
||||
{
|
||||
unit = "months";
|
||||
num = (long) (absmillis / millisPerMonth);
|
||||
}
|
||||
else
|
||||
{
|
||||
unit = "years";
|
||||
num = (long) (absmillis / millisPerYear);
|
||||
}
|
||||
|
||||
return ""+num+" "+unit+" "+agofromnow;
|
||||
}
|
||||
}
|
39
src/com/massivecraft/factions/zcore/util/WorldUtil.java
Normal file
39
src/com/massivecraft/factions/zcore/util/WorldUtil.java
Normal file
@ -0,0 +1,39 @@
|
||||
package com.massivecraft.factions.zcore.util;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class WorldUtil
|
||||
{
|
||||
// Previously We had crappy support for multiworld management.
|
||||
// This should however be handled by an external plugin!
|
||||
/*public static boolean load(String name) {
|
||||
if (isWorldLoaded(name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! doesWorldExist(name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Environment env = WorldEnv.get(name);
|
||||
if (env == null) {
|
||||
P.log(Level.WARNING, "Failed to load world. Environment was unknown.");
|
||||
return false;
|
||||
}
|
||||
|
||||
P.p.getServer().createWorld(name, env);
|
||||
return true;
|
||||
}*/
|
||||
|
||||
public static boolean isWorldLoaded(String name)
|
||||
{
|
||||
return Bukkit.getServer().getWorld(name) != null;
|
||||
}
|
||||
|
||||
public static boolean doesWorldExist(String name)
|
||||
{
|
||||
return new File(name, "level.dat").exists();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user