wrapper_command WIP
This commit is contained in:
@@ -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
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user