Be less hacky. Dynamic aliases in a new and less intrusive way.
This commit is contained in:
parent
4384c5f396
commit
ddcca231a6
155
src/com/massivecraft/mcore/EngineCommandRegistration.java
Normal file
155
src/com/massivecraft/mcore/EngineCommandRegistration.java
Normal file
@ -0,0 +1,155 @@
|
||||
package com.massivecraft.mcore;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.SimpleCommandMap;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.CraftServer;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.massivecraft.mcore.cmd.MCommand;
|
||||
import com.massivecraft.mcore.cmd.MCoreBukkitCommand;
|
||||
|
||||
public class EngineCommandRegistration extends EngineAbstract
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE & CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static EngineCommandRegistration i = new EngineCommandRegistration();
|
||||
public static EngineCommandRegistration get() { return i; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// OVERRIDE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public Plugin getPlugin()
|
||||
{
|
||||
return MCore.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getPeriod()
|
||||
{
|
||||
return 20L;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// TASK
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
updateRegistrations();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// UPDATE REGISTRATIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static void updateRegistrations()
|
||||
{
|
||||
// Get the SimpleCommandMap and it's knownCommands.
|
||||
SimpleCommandMap simpleCommandMap = getSimpleCommandMap();
|
||||
Map<String, Command> knownCommands = getSimpleCommandMapDotKnownCommands(simpleCommandMap);
|
||||
|
||||
// For each known command ...
|
||||
Iterator<Entry<String, Command>> iter = knownCommands.entrySet().iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Entry<String, Command> entry = iter.next();
|
||||
Command command = entry.getValue();
|
||||
|
||||
// ... if this command is a MCoreBukkitCommand ...
|
||||
if (!(command instanceof MCoreBukkitCommand)) continue;
|
||||
|
||||
// ... unregister it.
|
||||
command.unregister(simpleCommandMap);
|
||||
iter.remove();
|
||||
}
|
||||
|
||||
// For each MCommand that is supposed to be registered ...
|
||||
for (MCommand mcommand : MCommand.getRegisteredCommands())
|
||||
{
|
||||
// ... and for each of it's aliases ...
|
||||
for (String alias : mcommand.getAliases())
|
||||
{
|
||||
// ... clean the alias ...
|
||||
alias = alias.trim().toLowerCase();
|
||||
|
||||
// ... unregister current occupant of that alias ...
|
||||
Command previousOccupant = knownCommands.remove(alias);
|
||||
if (previousOccupant != null)
|
||||
{
|
||||
previousOccupant.unregister(simpleCommandMap);
|
||||
}
|
||||
|
||||
// ... create a new MCoreBukkitCommand ...
|
||||
MCoreBukkitCommand command = new MCoreBukkitCommand(alias, mcommand);
|
||||
|
||||
// ... and finally register it.
|
||||
simpleCommandMap.register("MCore", command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// GETTERS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static CraftServer getCraftServer()
|
||||
{
|
||||
return (CraftServer)Bukkit.getServer();
|
||||
}
|
||||
|
||||
public static SimpleCommandMap getSimpleCommandMap()
|
||||
{
|
||||
return getCraftServer().getCommandMap();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Map<String, Command> getSimpleCommandMapDotKnownCommands(SimpleCommandMap simpleCommandMap)
|
||||
{
|
||||
return (Map<String, Command>) get(SimpleCommandMap.class, "knownCommands", simpleCommandMap);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// UTIL
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Object get(Class<?> clazz, String fieldName, Object object)
|
||||
{
|
||||
try
|
||||
{
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field.get(object);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void set(Class<?> clazz, String fieldName, Object object, Object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
field.set(object, value);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -20,7 +20,6 @@ import com.massivecraft.mcore.adapter.ModdedEnumTypeAdapter;
|
||||
import com.massivecraft.mcore.adapter.ObjectIdAdapter;
|
||||
import com.massivecraft.mcore.adapter.PlayerInventoryAdapter;
|
||||
import com.massivecraft.mcore.adapter.UUIDAdapter;
|
||||
import com.massivecraft.mcore.cmd.MCoreBukkitSimpleCommandMap;
|
||||
import com.massivecraft.mcore.integration.protocollib.ProtocolLibFeatures;
|
||||
import com.massivecraft.mcore.integration.vault.VaultFeatures;
|
||||
import com.massivecraft.mcore.mcorecmd.CmdMCore;
|
||||
@ -150,7 +149,8 @@ public class MCore extends MPlugin
|
||||
EngineScheduledTeleport.get().activate();
|
||||
EngineTeleportMixinCause.get().activate();
|
||||
EngineWorldNameSet.get().activate();
|
||||
EngineOfflineCase.get().activate(); // TODO: Make all engines
|
||||
EngineOfflineCase.get().activate();
|
||||
EngineCommandRegistration.get().activate(); // TODO: Make all engines
|
||||
PlayerUtil.get().setup();
|
||||
|
||||
// Tasks
|
||||
@ -161,9 +161,6 @@ public class MCore extends MPlugin
|
||||
AspectColl.get().init();
|
||||
MCoreConfColl.get().init();
|
||||
|
||||
// Inject our command map with dynamic tweaks
|
||||
MCoreBukkitSimpleCommandMap.inject();
|
||||
|
||||
// Register commands
|
||||
this.outerCmdMCore = new CmdMCore() { public List<String> getAliases() { return MCoreConf.get().aliasesOuterMCore; } };
|
||||
this.outerCmdMCore.register();
|
||||
|
@ -1,115 +0,0 @@
|
||||
package com.massivecraft.mcore.cmd;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.command.SimpleCommandMap;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.CraftServer;
|
||||
import org.bukkit.plugin.SimplePluginManager;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class BukkitCommandDoor
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// SINGLETON
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static CraftServer getCraftServer()
|
||||
{
|
||||
return (CraftServer)Bukkit.getServer();
|
||||
}
|
||||
|
||||
public static SimpleCommandMap getSimpleCommandMap()
|
||||
{
|
||||
return getCraftServer().getCommandMap();
|
||||
}
|
||||
|
||||
public static void setSimpleCommandMap(SimpleCommandMap simpleCommandMap)
|
||||
{
|
||||
set(CraftServer.class, "commandMap", getCraftServer(), simpleCommandMap);
|
||||
}
|
||||
|
||||
public static SimplePluginManager getSimplePluginManager()
|
||||
{
|
||||
return (SimplePluginManager)Bukkit.getPluginManager();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SIMPLE COMMAND MAP
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Map<String, Command> getSimpleCommandMapDotKnownCommands(SimpleCommandMap simpleCommandMap)
|
||||
{
|
||||
return (Map<String, Command>) get(SimpleCommandMap.class, "knownCommands", simpleCommandMap);
|
||||
}
|
||||
|
||||
public static Set<String> getSimpleCommandMapDotAliases(SimpleCommandMap simpleCommandMap)
|
||||
{
|
||||
return (Set<String>) get(SimpleCommandMap.class, "aliases", simpleCommandMap);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SIMPLE PLUGIN MANAGER
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static CommandMap getSimplePluginManagerCommandMap(SimplePluginManager simplePluginManager)
|
||||
{
|
||||
return (CommandMap) get(SimplePluginManager.class, "commandMap", simplePluginManager);
|
||||
}
|
||||
|
||||
public static void setSimplePluginManagerCommandMap(SimplePluginManager simplePluginManager, CommandMap commandMap)
|
||||
{
|
||||
set(SimplePluginManager.class, "commandMap", simplePluginManager, commandMap);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COMMAND
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static CommandMap getCommandDotCommandMap(Command command)
|
||||
{
|
||||
return (CommandMap) get(Command.class, "commandMap", command);
|
||||
}
|
||||
|
||||
public static void setCommandDotCommandMap(Command command, CommandMap commandMap)
|
||||
{
|
||||
set(Command.class, "commandMap", command, commandMap);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// UTIL
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Object get(Class<?> clazz, String fieldName, Object object)
|
||||
{
|
||||
try
|
||||
{
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field.get(object);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void set(Class<?> clazz, String fieldName, Object object, Object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
field.set(object, value);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -4,11 +4,9 @@ import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.SimpleCommandMap;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.massivecraft.mcore.Lang;
|
||||
import com.massivecraft.mcore.MCore;
|
||||
import com.massivecraft.mcore.cmd.arg.ArgReader;
|
||||
import com.massivecraft.mcore.cmd.arg.ArgResult;
|
||||
import com.massivecraft.mcore.cmd.req.Req;
|
||||
@ -19,6 +17,27 @@ import com.massivecraft.mcore.util.Txt;
|
||||
|
||||
public class MCommand
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// REGISTER
|
||||
// -------------------------------------------- //
|
||||
// MCore commands are a bit special when it comes to registration.
|
||||
//
|
||||
// I want my users to be able to edit the command aliases and I want
|
||||
// them to be able to do so during server runtime without having to use the /reload command.
|
||||
//
|
||||
// To provide a truly neat experience I place the command aliases in a mstore database configuration file.
|
||||
// As such these config files are polled for changes and loaded into the server automatically.
|
||||
// If someone changed the command aliases we must update all Bukkit command registrations.
|
||||
//
|
||||
// In order to achieve this we run a task once a second (see com.massivecraft.mcore.EngineCommandRegistration).
|
||||
// This task unregisters /all/ registered MCommands and then register them all again.
|
||||
// When registering again we use the fresh and current aliases.
|
||||
|
||||
private static transient Set<MCommand> registeredCommands = new LinkedHashSet<MCommand>();
|
||||
public static Set<MCommand> getRegisteredCommands() { return registeredCommands; }
|
||||
public void register() { getRegisteredCommands().add(this); }
|
||||
public void unregister() { getRegisteredCommands().remove(this); }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COMMAND BEHAVIOR
|
||||
// -------------------------------------------- //
|
||||
@ -160,19 +179,6 @@ public class MCommand
|
||||
public Player me;
|
||||
public boolean senderIsConsole;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// BUKKIT INTEGRATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected final MCoreBukkitCommand bukkitCommand = new MCoreBukkitCommand(this);
|
||||
public MCoreBukkitCommand getBukkitCommand() { return this.bukkitCommand; }
|
||||
|
||||
public void register()
|
||||
{
|
||||
SimpleCommandMap scm = BukkitCommandDoor.getSimpleCommandMap();
|
||||
scm.register(MCore.get().getDescription().getName(), this.getBukkitCommand());
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCTORS AND EXECUTOR
|
||||
// -------------------------------------------- //
|
||||
|
@ -25,46 +25,17 @@ public class MCoreBukkitCommand extends Command
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public MCoreBukkitCommand(MCommand mcommand)
|
||||
public MCoreBukkitCommand(String name, MCommand mcommand)
|
||||
{
|
||||
super(
|
||||
mcommand.getClass().getSimpleName(), // The name field is final. MCommand aliases/names are not final so we simply use the class name.
|
||||
null, // Set description to null. Instead we override the getter.
|
||||
null, // Set usage to null. Instead we override the getter.
|
||||
new ArrayList<String>() // Set aliases to "null". Instead we override the getter.
|
||||
name,
|
||||
mcommand.getDesc(),
|
||||
mcommand.getUseageTemplate(),
|
||||
new ArrayList<String>() // We don't use aliases
|
||||
);
|
||||
|
||||
this.mcommand = mcommand;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// OVERRIDE: GETTERS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public String getDescription()
|
||||
{
|
||||
return this.getMcommand().getDesc();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage()
|
||||
{
|
||||
return this.getMcommand().getUseageTemplate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAliases()
|
||||
{
|
||||
return this.getMcommand().getAliases();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel()
|
||||
{
|
||||
return this.getMcommand().getAliases().get(0);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// OVERRIDE: EXECUTE
|
||||
// -------------------------------------------- //
|
||||
|
@ -1,110 +0,0 @@
|
||||
package com.massivecraft.mcore.cmd;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.SimpleCommandMap;
|
||||
|
||||
|
||||
public class MCoreBukkitSimpleCommandMap extends SimpleCommandMap
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// INJECT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static MCoreBukkitSimpleCommandMap get()
|
||||
{
|
||||
SimpleCommandMap ret = BukkitCommandDoor.getSimpleCommandMap();
|
||||
if (!(ret instanceof MCoreBukkitSimpleCommandMap)) return null;
|
||||
return (MCoreBukkitSimpleCommandMap) ret;
|
||||
}
|
||||
|
||||
public static boolean isInjected()
|
||||
{
|
||||
return get() != null;
|
||||
}
|
||||
|
||||
public static void inject()
|
||||
{
|
||||
if (isInjected()) return;
|
||||
MCoreBukkitSimpleCommandMap instance = new MCoreBukkitSimpleCommandMap();
|
||||
BukkitCommandDoor.setSimpleCommandMap(instance);
|
||||
BukkitCommandDoor.setSimplePluginManagerCommandMap(BukkitCommandDoor.getSimplePluginManager(), instance);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
private final LinkedHashSet<MCoreBukkitCommand> mcoreBukkitCommands = new LinkedHashSet<MCoreBukkitCommand>();
|
||||
public LinkedHashSet<MCoreBukkitCommand> getMCoreBukkitCommands() { return this.mcoreBukkitCommands; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public MCoreBukkitSimpleCommandMap(SimpleCommandMap simpleCommandMap)
|
||||
{
|
||||
// Trigger the super constructor
|
||||
super(Bukkit.getServer());
|
||||
|
||||
// Fetch non static collection content
|
||||
this.knownCommands.putAll(BukkitCommandDoor.getSimpleCommandMapDotKnownCommands(simpleCommandMap));
|
||||
this.aliases.addAll(BukkitCommandDoor.getSimpleCommandMapDotAliases(simpleCommandMap));
|
||||
|
||||
// Convert registrations
|
||||
for (Entry<String, Command> entry : this.knownCommands.entrySet())
|
||||
{
|
||||
Command command = entry.getValue();
|
||||
if (BukkitCommandDoor.getCommandDotCommandMap(command) == null) continue;
|
||||
BukkitCommandDoor.setCommandDotCommandMap(command, this);
|
||||
}
|
||||
}
|
||||
|
||||
public MCoreBukkitSimpleCommandMap()
|
||||
{
|
||||
this(BukkitCommandDoor.getSimpleCommandMap());
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// OVERRIDE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public boolean register(String label, String fallbackPrefix, Command command)
|
||||
{
|
||||
// Bukkit
|
||||
if (!(command instanceof MCoreBukkitCommand))
|
||||
{
|
||||
return super.register(label, fallbackPrefix, command);
|
||||
}
|
||||
|
||||
// MCore
|
||||
command.register(this);
|
||||
this.getMCoreBukkitCommands().add((MCoreBukkitCommand)command);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command getCommand(String name)
|
||||
{
|
||||
// MCore
|
||||
for (MCoreBukkitCommand mbc : this.getMCoreBukkitCommands())
|
||||
{
|
||||
for (String alias : mbc.getAliases())
|
||||
{
|
||||
if (alias.equalsIgnoreCase(name))
|
||||
{
|
||||
return mbc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bukkit
|
||||
return super.getCommand(name);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user