wrapper_player progress

This commit is contained in:
Dico200
2015-11-25 18:03:36 +01:00
parent 37d425bb65
commit 3bc7963a7a

View File

@@ -3,9 +3,44 @@ from helpers import *
root_commands = Command_dict() # {"command": command_object} root_commands = Command_dict() # {"command": command_object}
def check_arguments(command, arguments): class Command(object):
prev_required = True """
type_message_seen = False # Documentation to come.s
"""
SENDER_ANY = 0
SENDER_PLAYER = 1
SENDER_CONSOLE = 2
ACTION_IGNORE = 3
ACTION_SYNTAXERROR = 4
ACTION_DISPLAYSYNTAX = 5
ACTION_DISPLAYHELP = 6
def __init__(self,
command,
aliases = (),
permission = None,
description = "Description",
type = Command.SENDER_ANY
no_arg_action = Command.ACTION_IGNORE
help_request_action = Command.ACTION_IGNORE
arguments = (),
parent = None,
):
self.command = command.lower()
self.aliases = tuple(alias.lower() for alias in aliases)
self.permission = self.command if permission == None else permission
self.description = description
self.type = type
self.no_arg_action = no_arg_action
self.help_request_action = help_request_action
self.arguments = arguments
self.parent = parent
self.sub_commands = Command_dict()
# ---- Check if argument layout is valid ----
prev_arg = arguments[0] if len(arguments) > 0 else None prev_arg = arguments[0] if len(arguments) > 0 else None
for arg_info in arguments[1:]: for arg_info in arguments[1:]:
@@ -17,43 +52,7 @@ def check_arguments(command, arguments):
prev_arg = arg_info prev_arg = arg_info
#-------------------------------------------------------------------------------------- # ---- Add self to parent sub_commands ----
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: if self.parent == None:
root_commands[self.command] = self root_commands[self.command] = self
else: else:
@@ -62,19 +61,29 @@ class Command(object):
parent_sub_commands = root_commands parent_sub_commands = root_commands
parent_obj = None parent_obj = None
for cmd_name in parent_route: for cmd_name in parent_route:
parent_obj = parent_sub_commands.get_command_object(cmd_name) parent_obj = parent_sub_commands[cmd_name]
parent_sub_commands = parent_obj.sub_commands parent_sub_commands = parent_obj.sub_commands
parent_obj.sub_commands[self.command] = self parent_obj.sub_commands[self.command] = self
except command_exception, e: except KeyError as e:
error("Error occurred while setting up command hierarchy. " + e.message + "\n" + trace()) error("Error occurred while setting up command hierarchy: " + e.message + "\n" + trace())
def __call__(self, handler): def __call__(self, handler):
"""
# To clarify: This function is called when you 'call' an instance of a class.
# This means, that Command() calls __init__() and Command()() calls __call__().
# This makes it possible to use class instances for decoration. The decorator is this function.
"""
self.handler = handler self.handler = handler
if parent == None: if parent == None:
@hook.command(self.command, self.aliases) @hook.command(self.command, self.aliases)
def run(sender, command, label, args): def run(sender, command, label, args):
"""
# This function will take care of prefixing and colouring of messages in the future.
# So it's very much WIP.
"""
try: try:
message = self.execute(sender, command, label, args) message = self.execute(sender, command, label, args)
except Command_exception as e: except Command_exception as e:
@@ -90,30 +99,154 @@ class Command(object):
def execute(self, sender, command, label, args): def execute(self, sender, command, label, args):
try: try:
return self.sub_commands.get_command_object(args[0].lower()).execute(sender, command, label, args[1:]) return self.sub_commands[args[0].lower()].execute(sender, command, label, args[1:])
except (KeyError, IndexError): except (KeyError, IndexError):
self.execute_checks(sender, command, label, args) self.execute_checks(sender, command, label, args)
def execute_checks(self, sender, command, label, args): def execute_checks(self, sender, command, label, args):
#TODO
scape = Command_scape(args, self.arguments) # ---- Check sender type ----
Validate.is_true(self.type != Command.SENDER_CONSOLE, "That command can only be used by the console")
else:
Validate.is_true(self.type != Command.SENDER_PLAYER, "That command can only be used by players")
# ---- Check permission ----
Validate.is_authorized(sender, self.permission)
# ---- Check if a help message is expected ----
if len(args) == 0:
action = self.no_arg_action
elif args[0].lower() == "help":
action = self.help_request_action
else:
action = Command.ACTION_IGNORE
if action != Command.ACTION_IGNORE:
if action == Command.ACTION_SYNTAXERROR:
return "&cInvalid syntax, please try again."
if action == Command.ACTION_DISPLAYSYNTAX:
return self.syntax()
if action == Command.ACTION_DISPLAYHELP:
return self.help()
# ---- Set up passed arguments, prepare for handler call ----
if is_player(sender):
sender = py_players[sender]
scape = Command_scape(args, self.arguments, command, label)
if is_player(sender): if is_player(sender):
sender = py_players[sender] sender = py_players[sender]
return self.handler(sender, self, scape) return self.handler(sender, self, scape)
# @Command("hello") def on_hello_command(sender, command, scape/args)
def syntax(self): def syntax(self):
return " ".join(tuple(arg_info.syntax() for arg_info in self.arguments)) return " ".join(tuple(arg_info.syntax() for arg_info in self.arguments))
#-------------------------------------------------------------------------------------- def help(self):
syntax = self.syntax()
return syntax #WIP...
class Argument():
"""
# A more advanced implementation of amin and amax, though it doesn't do exactly the same.
# You can now pass a list of Argument objects which define what the argument represents.
# In the process of doing so, you can set an argument type, one of the ones mentioned below.
# For example, if Argument.PLAYER is given, the server will be searched for the given player, and
# they will be passed as the argument, instead of a string representing their name.
#
# Feel free to add your own argument types. If you want to make a change to the API to make it different,
# please don't do so on your own behalf.
"""
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():
"""
# Much like what you often see in Java.
# Instead of having to check if a condition is met, and if not,
# sending the player a message and returning true,
# You can use one of these methods to check the condition, and
# pass a message if it's not met.
#
# For example:
# > if not sender.hasPermission("utils.smth"):
# noperm(sender)
# return True
#
# Can be replaced with:
# > Validate.is_authorized(sender, "utils.smth")
#
"""
@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)
@staticmethod
def is_authorized(player, permission, msg = "You do not have permission to use that command"):
if not player.hasPermission(permission):
raise Command_exception(msg)
@staticmethod
def is_player(sender):
if not is_player(sender):
raise Command_exception("That command can only be used by players")
@staticmethod
def is_console(sender):
if is_player(sender):
raise Command_exception("That command can only be used by the console")
"""
# ---------- API classes ----------
"""
class Command_dict(dict):
#{"cmd1" : cmd_object}
def __getattr__(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_exception(Exception):
def __init__(self, message):
self.message = message
class Command_scape(list): class Command_scape(list):
def __init__(self, args, arg_layout): def __init__(self, args, arg_layout, command, label):
super(list, self).__init__() super(list, self).__init__()
self.raw = args self.raw = args
self.arg_layout = arg_layout self.arg_layout = arg_layout
self.command = command
self.label = label
has_message = False has_message = False
for i in range(len(arg_layout)): for i in range(len(arg_layout)):
@@ -182,51 +315,8 @@ class Command_scape(list):
def get_arg_layout(self): def get_arg_layout(self):
return self.arg_layout return self.arg_layout
#--------------------------------------------------------------------------------------
class Command_exception(Exception):
def __init__(self, message):
self.message = message
class Argument_exception(Exception): class Argument_exception(Exception):
def __init__(self, message): def __init__(self, message):
self.message = 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)