summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDico200 <dico.karssiens@gmail.com>2016-06-25 07:27:36 +0200
committerDico200 <dico.karssiens@gmail.com>2016-06-25 07:27:36 +0200
commitd8d2a0de6a5301343371779b8a0d82c128537128 (patch)
treeb150f701a4185b346fce0363dbe5937f7fbe869c
parentcebdb90d601cf4cb0889212cc804893a112f10e7 (diff)
Added command intercepter tool, used it for //calc
-rw-r--r--misc.py128
1 files changed, 128 insertions, 0 deletions
diff --git a/misc.py b/misc.py
index 026650e..1cbe8fb 100644
--- a/misc.py
+++ b/misc.py
@@ -8,8 +8,136 @@ import org.bukkit.inventory.ItemStack as ItemStack
import org.bukkit.Bukkit as Bukkit
from basecommands import simplecommand, Validate
import java.util.Arrays as Arrays
+import org.bukkit.command.Command as Command
+import java.util.HashMap as HashMap
+"""
+This section is a little tool to intercept commands.
+It can intercept any aliases of the command, which it does by default.
+
+An intercepter is a function that is run before the command is executed,
+which takes the parameters: sender, args
+It should return a boolean value to specify whether it should be executed.
+
+The optional tab completer is a function that takes the following parameters:
+ original_completions (List<String>), sender, alias, args
+and it should return a List<String>. By default it returns the original completions.
+"""
+
+class CommandInterceptions:
+
+ def __init__(self):
+ raise Exception("Instances of 'CommandInterceptions' are not meant to exist")
+
+ registrations = {} # cmd : (intercepter, tab_completer)
+ interceptions = {} # original_obj : replacement_obj
+ cmd_map = None # CustomHashMap
+
+ @staticmethod
+ def register(plugin_name, command, intercepter, tab_completer = None):
+ key = (plugin_name + ":" + command if plugin_name else command).lower()
+ CommandInterceptions.registrations[key] = (intercepter, tab_completer)
+ if CommandInterceptions.cmd_map.containsKey(key):
+ CommandInterceptions.add_interception(key, CommandInterceptions.cmd_map.get(key))
+
+
+ class Intercepter(Command):
+
+ def __init__(self, wrapped, intercepter, tab_completer):
+ try:
+ Command.__init__(self, wrapped.getName())
+ self.setDescription(wrapped.getDescription())
+ self.setPermission(wrapped.getPermission())
+ self.setUsage(wrapped.getUsage())
+
+ # I had to dig deep in spigot code to find out what's happening
+ # But without this snippet, the server shuts itself down because
+ # commands can't be aliases for themselves (shrug) :)
+ aliases = wrapped.getAliases()
+ aliases.remove(wrapped.getLabel())
+ self.setAliases(aliases)
+ self.wrapped = wrapped
+ self.intercepter = intercepter
+ self.tab_completer = tab_completer
+ except:
+ error(trace())
+
+ def execute(self, sender, label, args):
+ if self.intercepter(sender, args):
+ return self.wrapped.execute(sender, label, args)
+ return True
+
+ def tabComplete(self, sender, alias, args):
+ return self.tab_completer(self.wrapped.tabComplete(sender, alias, args), sender, alias, args)
+
+
+ @staticmethod
+ def add_interception(key, intercepted):
+ try:
+ info("Adding interception for /" + key)
+ registration = CommandInterceptions.registrations[key]
+ tab_completer = registration[1]
+ if tab_completer is None:
+ tab_completer = lambda original_completions, sender, alias, args: original_completions
+ cmd_intercepter = CommandInterceptions.Intercepter(intercepted, registration[0], tab_completer)
+ CommandInterceptions.interceptions[intercepted] = cmd_intercepter
+ for entry in CommandInterceptions.cmd_map.entrySet():
+ if entry.getValue() is intercepted:
+ entry.setValue(cmd_intercepter)
+ except:
+ error(trace())
+
+ @staticmethod
+ def init_interceptions():
+
+ # The map object in the command map used by spigot is previously already a hashmap, we replace its put() here
+ class CustomHashMap(HashMap):
+
+ def __init__(self, replaced):
+ HashMap.__init__(self)
+ for entry in replaced.entrySet():
+ self.put(entry.getKey(), entry.getValue())
+
+ def java_put(self, key, value):
+ return HashMap.put(self, key, value)
+
+ def put(self, key, value):
+ try:
+ for intercepted in CommandInterceptions.interceptions:
+ if value is intercepted:
+ return self.java_put(key, CommandInterceptions.interceptions[intercepted])
+ ret = self.java_put(key, value)
+ if key in CommandInterceptions.registrations:
+ CommandInterceptions.add_interception(key, value)
+ return ret
+ except:
+ error(trace())
+
+ try:
+ map_field = server.getPluginManager().getClass().getDeclaredField("commandMap")
+ map_field.setAccessible(True)
+ command_map = map_field.get(server.getPluginManager())
+
+ commands_field = command_map.getClass().getDeclaredField("knownCommands")
+ commands_field.setAccessible(True)
+ CommandInterceptions.cmd_map = CustomHashMap(commands_field.get(command_map))
+ commands_field.set(command_map, CommandInterceptions.cmd_map)
+ except:
+ error("[Interceptions] Failed to wrap the command map:")
+ error(trace())
+CommandInterceptions.init_interceptions()
+
+
+def worldedit_calc_intercepter(sender, args):
+ info("WorldEdit Calc Intercepter WOOHOO")
+ if not sender.hasPermission("worldedit.calc"):
+ noperm(sender)
+ return False
+ return True
+
+CommandInterceptions.register("worldedit", "/calc", worldedit_calc_intercepter)
+
@hook.event("player.PlayerJoinEvent", "monitor")
def on_join(event):