diff --git a/src/main/java/co/aikar/commands/ACFPatterns.java b/src/main/java/co/aikar/commands/ACFPatterns.java index f80e5928..d0f7e2c8 100644 --- a/src/main/java/co/aikar/commands/ACFPatterns.java +++ b/src/main/java/co/aikar/commands/ACFPatterns.java @@ -45,7 +45,6 @@ final class ACFPatterns { public static final Pattern INTEGER = Pattern.compile("^[0-9]+$"); public static final Pattern VALID_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]{2,16}$"); public static final Pattern NON_PRINTABLE_CHARACTERS = Pattern.compile("[^\\x20-\\x7F]"); - public static final Pattern EQUALS = Pattern.compile("="); diff --git a/src/main/java/co/aikar/commands/BukkitCommandManager.java b/src/main/java/co/aikar/commands/BukkitCommandManager.java index 2999f95d..ba1e6270 100644 --- a/src/main/java/co/aikar/commands/BukkitCommandManager.java +++ b/src/main/java/co/aikar/commands/BukkitCommandManager.java @@ -25,9 +25,12 @@ package co.aikar.commands; import co.aikar.timings.lib.TimingManager; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.Server; import org.bukkit.command.Command; +import org.bukkit.command.CommandException; import org.bukkit.command.CommandMap; +import org.bukkit.command.CommandSender; import org.bukkit.command.SimpleCommandMap; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -59,9 +62,13 @@ public class BukkitCommandManager extends CommandManager { Method getCommandMap = server.getClass().getDeclaredMethod("getCommandMap"); getCommandMap.setAccessible(true); commandMap = (CommandMap) getCommandMap.invoke(server); - if (!commandMap.getClass().equals(SimpleCommandMap.class)) { + if (!SimpleCommandMap.class.isAssignableFrom(commandMap.getClass())) { ACFLog.severe("ERROR: CommandMap has been hijacked! Offending command map is located at: " + commandMap.getClass().getName()); - ACFLog.severe("Commands are most likely broken unless the hijacker did it in a friendly way."); + ACFLog.severe("We are going to try to hijack it back and resolve this, but you are now in dangerous territory."); + ACFLog.severe("We can not guarantee things are going to work."); + Field cmField = server.getClass().getDeclaredField("commandMap"); + cmField.set(server, new ProxyCommandMap(commandMap)); + ACFLog.info("Injected Proxy Command Map... good luck..."); } Field knownCommands = commandMap.getClass().getDeclaredField("knownCommands"); knownCommands.setAccessible(true); @@ -154,4 +161,79 @@ public class BukkitCommandManager extends CommandManager { public TimingManager getTimings() { return timingManager; } + + class ProxyCommandMap extends SimpleCommandMap { + + CommandMap proxied; + + ProxyCommandMap(CommandMap proxied) { + super(Bukkit.getServer()); + this.proxied = proxied; + } + + @Override + public void registerAll(String fallbackPrefix, List commands) { + proxied.registerAll(fallbackPrefix, commands); + } + + @Override + public boolean register(String label, String fallbackPrefix, Command command) { + if (isOurCommand(command)) { + return super.register(label, fallbackPrefix, command); + } else { + return proxied.register(label, fallbackPrefix, command); + } + } + + boolean isOurCommand(String cmdLine) { + String[] args = ACFPatterns.SPACE.split(cmdLine); + return args.length != 0 && isOurCommand(knownCommands.get(args[0].toLowerCase(Locale.ENGLISH))); + + } + boolean isOurCommand(Command command) { + return command instanceof BaseCommand && ((BaseCommand) command).manager == BukkitCommandManager.this; + } + + @Override + public boolean register(String fallbackPrefix, Command command) { + if (isOurCommand(command)) { + return super.register(fallbackPrefix, command); + } else { + return proxied.register(fallbackPrefix, command); + } + } + + @Override + public boolean dispatch(CommandSender sender, String cmdLine) throws CommandException { + if (isOurCommand(cmdLine)) { + return super.dispatch(sender, cmdLine); + } else { + return proxied.dispatch(sender, cmdLine); + } + } + + @Override + public void clearCommands() { + super.clearCommands();; + proxied.clearCommands(); + } + + @Override + public Command getCommand(String name) { + if (isOurCommand(name)) { + return super.getCommand(name); + } else { + return proxied.getCommand(name); + } + } + + @Override + public List tabComplete(CommandSender sender, String cmdLine) throws IllegalArgumentException { + if (isOurCommand(cmdLine)) { + return super.tabComplete(sender, cmdLine); + } else { + return proxied.tabComplete(sender, cmdLine); + } + } + } }