summaryrefslogtreecommitdiff
path: root/wrapper_command.py
diff options
context:
space:
mode:
Diffstat (limited to 'wrapper_command.py')
-rw-r--r--wrapper_command.py237
1 files changed, 229 insertions, 8 deletions
diff --git a/wrapper_command.py b/wrapper_command.py
index dd51534..90eaf01 100644
--- a/wrapper_command.py
+++ b/wrapper_command.py
@@ -1,11 +1,232 @@
from wrapper_player import *
+from helpers import *
-def command(command = "help"):
- def decorator(wrapped):
- @hook.command(command)
- def wrapper(sender, command, label, args):
+root_commands = Command_dict() # {"command": command_object}
+
+def check_arguments(command, arguments):
+ prev_required = True
+ type_message_seen = False
+ prev_arg = arguments[0] if len(arguments) > 0 else None
+ for arg_info in arguments[1:]:
+
+ if not prev_arg.required and arg_info.required:
+ raise Argument_exception("Command: %s; There may not be required arguments after non-required arguments" % command)
+
+ if prev_arg.type == Argument.MESSAGE:
+ raise Argument_exception("Command: %s; An argument of type MESSAGE may not be followed by other arguments" % command)
+
+ prev_arg = arg_info
+
+#--------------------------------------------------------------------------------------
+
+class Command_dict(dict):
+ #{"cmd1" : cmd_object}
+ def get_command_object(self, alias):
+ for cmd_name, cmd_obj in self.iteritems():
+ if alias == cmd_name or alias in cmd_obj.aliases:
+ return cmd_obj
+ raise KeyError("Subcommand '%s' was not found" % alias)
+
+#--------------------------------------------------------------------------------------
+
+class Command(object):
+
+ def __init__(self,
+ command,
+ aliases = (),
+ arguments = (
+ Argument("target", Argument.string, "the player to teleport to"),
+ Argument("second target", Argument.string, "the player to teleport", False),
+ ),
+ parent = None):
+
+ self.command = command.lower()
+ self.arguments = arguments
+
+ check_arguments(self.command, self.arguments)
+
+ prev_required = True
+ for arg_info in self.arguments:
+ if not prev_required and arg_info.required:
+ raise Argument_exception("Command: %s; There may not be required arguments after non-required arguments" % self.command)
+
+ self.aliases = tuple(alias.lower() for alias in aliases)
+ self.parent = parent
+ self.sub_commands = Command_dict()
+
+ if self.parent == None:
+ root_commands[self.command] = self
+ else:
try:
- return wrapped(sender = py_players[sender], command = command, label = label, args = args)
- except:
- print(print_traceback())
- return decorator \ No newline at end of file
+ parent_route = self.parent.split(" ")
+ parent_sub_commands = root_commands
+ parent_obj = None
+ for cmd_name in parent_route:
+ parent_obj = parent_sub_commands.get_command_object(cmd_name)
+ parent_sub_commands = parent_obj.sub_commands
+ parent_obj.sub_commands[self.command] = self
+
+ except command_exception, e:
+ error("Error occurred while setting up command hierarchy. " + e.message + "\n" + trace())
+
+ def __call__(self, handler):
+ self.handler = handler
+
+ if parent == None:
+ @hook.command(self.command, self.aliases)
+ def run(sender, command, label, args):
+ try:
+ message = self.execute(sender, command, label, args)
+ except Command_exception as e:
+ message = e.message
+ except Exception:
+ error(trace())
+ return True
+ if message:
+ sender.sendMessage(message)
+ return True
+
+ return handler
+
+ def execute(self, sender, command, label, args):
+ try:
+ return self.sub_commands.get_command_object(args[0].lower()).execute(sender, command, label, args[1:])
+ except (KeyError, IndexError):
+ self.execute_checks(sender, command, label, args)
+
+ def execute_checks(self, sender, command, label, args):
+ #TODO
+
+ scape = Command_scape(args, self.arguments)
+ if is_player(sender):
+ sender = py_players[sender]
+
+ return self.handler(sender, self, scape)
+
+ def syntax(self):
+ return " ".join(tuple(arg_info.syntax() for arg_info in self.arguments))
+
+#--------------------------------------------------------------------------------------
+
+class Command_scape(list):
+
+ def __init__(self, args, arg_layout):
+ super(list, self).__init__()
+ self.raw = args
+ self.arg_layout = arg_layout
+
+ has_message = False
+ for i in range(len(arg_layout)):
+ arg_info = arg_layout[i]
+
+ given = (len(args) >= i + 1)
+ if arg_info.required and not given:
+ raise Argument_exception("You must specify the " + arg_info.name)
+
+ if not given:
+ self.append(None)
+ continue
+
+ given_arg = args[i]
+ arg_type = arg_info.type
+
+ if arg_type == Argument.STRING:
+ self.append(given_arg)
+
+ elif arg_type == Argument.INTEGER:
+ try:
+ value = int(given_arg)
+ except ValueError:
+ raise Argument_exception("The %s has to be a round number" % arg_info.name)
+ self.append(value)
+
+ elif arg_type == Argument.FLOAT:
+ try:
+ value = float(given_arg)
+ except ValueError:
+ raise Argument_exception("The %s has to be a number" % arg_info.name)
+ self.append(value)
+
+ elif arg_type == Argument.PLAYER:
+ target = server.getPlayer(given_arg)
+ if target == None:
+ raise Argument_exception("The %s has to be an online player" % arg_info.name)
+ self.append(py_players[target])
+
+ elif arg_type == Argument.OFFLINE_PLAYER:
+ try:
+ # Code to get the PY PLAYER by name. Possibly, uid(server.getOfflinePlayer(given_arg)) can be used?
+ pass
+ except KeyError:
+ raise Argument_exception("The %s has to be an existing player" % arg_info.name)
+ self.append(None)
+
+ elif arg_type == Argument.MESSAGE:
+ self.append(" ".join(args[i:]))
+ has_message = True
+ else:
+ error("Argument type not found: %d" % arg_type)
+ raise Argument_exception("A weird thing has happened, please contact an administrator")
+
+ if not has_message:
+ self.remainder = args[len(arg_layout):]
+ else:
+ self.remainder = None
+
+ def has_flag(self, flag, check_all = False):
+ return (("-" + flag) in self.raw) if check_all else (("-" + flag) in self.remainder)
+
+ def get_raw(self):
+ return self.raw
+
+ def get_arg_layout(self):
+ return self.arg_layout
+
+#--------------------------------------------------------------------------------------
+
+class Command_exception(Exception):
+
+ def __init__(self, message):
+ self.message = message
+
+class Argument_exception(Exception):
+
+ def __init__(self, message):
+ self.message = message
+
+#--------------------------------------------------------------------------------------
+
+class Argument():
+
+ STRING = 0
+ INTEGER = 1
+ FLOAT = 2
+ PLAYER = 3
+ OFFLINE_PLAYER = 4
+ MESSAGE = 5
+
+ def __init__(self, name, type, definition, required = True):
+ self.name = name
+ self.type = type
+ self.definition = definition
+ self.required = required
+
+ def syntax(self):
+ syntax = self.name
+ if self.type == Argument.MESSAGE:
+ syntax += "..."
+ return (("<%s>" if self.required else "[%s]") % syntax)
+
+#--------------------------------------------------------------------------------------
+
+class Validate():
+
+ @staticmethod
+ def is_true(expression, fail_message):
+ if not expression:
+ raise Command_exception(fail_message)
+
+ @staticmethod
+ def not_none(obj, fail_message):
+ if obj == None:
+ raise Command_exception(fail_message)