From b3b6d15a32a5f9e2d7257292fac8115dfe37dcc1 Mon Sep 17 00:00:00 2001 From: Dico200 Date: Wed, 25 Nov 2015 15:55:25 +0100 Subject: wrapper_command WIP... to wrapper branch now? --- chatalias.py | 4 +- serversigns.py | 53 +++++++----- setup.sh | 2 +- vanish.py | 53 ++++++------ wrapper_command.py | 237 +++++++++++++++++++++++++++++++++++++++++++++++++++-- wrapper_event.py | 8 -- wrapper_player.py | 47 +++-------- 7 files changed, 301 insertions(+), 103 deletions(-) diff --git a/chatalias.py b/chatalias.py index d55269c..25e3336 100644 --- a/chatalias.py +++ b/chatalias.py @@ -125,8 +125,9 @@ def on_player_chat(event): data = safe_open_json() if event.isCancelled(): return - if not data[playerid]: + if not playerid in data: return + event.setMessage(multiple_replace(data[playerid], event.getMessage())) if (event.getPlayer().hasPermission("essentials.chat.color")): @@ -135,4 +136,3 @@ def on_player_chat(event): event.setCancelled(True) plugin_header(recipient=event.getPlayer(), name="Chat Alias") msg(event.getPlayer(), "&7The message generated was too long and was not sent. :/") - diff --git a/serversigns.py b/serversigns.py index 297b727..f8f9db5 100644 --- a/serversigns.py +++ b/serversigns.py @@ -5,6 +5,14 @@ import java.util.UUID as UUID import org.bukkit.Material as Material import org.bukkit.block.BlockFace as BlockFace +""" + # About permissions: + # To use the command, the user needs to have utils.serversigns. + # To use ANY subcommand, the user needs to have utils.serversigns. IN ADDITION to the previously mentioned node. + # To be able to add commands as messages to a sign, a user will need the node utils.serversigns.command. + # To be able to claim a sign for another player or to edit signs that the user doesn't own, they will need utils.serversigns.admin. +""" + blocked_cmds = ("pex", "kick", "ban", "tempban", "pyeval", "sudo", "stop", "reload", "op", "deop", "whitelist") def load_signs(): @@ -24,6 +32,18 @@ signs = load_signs() # {("world", x, y, z): ["owner_id", "msg1", "msg2"]} lines = {} # Accumulated messages so players can have longer messages: {"Dico200": "Message...........", ""} +@hook.enable +def check_all_signs(): + # Check if all saved signs actually represent a sign block. There are ways to break the signs without the plugin knowing. + for loc in dict(signs): # Can't change dict size during iteration, using a copy + world = server.getWorld(loc[0]) + if world and world.getBlockAt(loc[1], loc[2], loc[3]).getType() in (Material.SIGN_POST, Material.WALL_SIGN): + continue + del signs[loc] + info("[Server Signs] Couldn't find a %s, removed the data for the sign that was once there." % identifySign(loc)) + save_signs() + + def fromLoc(bLoc): """ # Returns a tuple containing the (bukkit)location's world's name and its x, y and z coordinates @@ -222,9 +242,6 @@ def svs_command(sender, command, label, args): return signsMsg("Removed all messages and the owner from the %s, it can now be claimed" % signName, 'a') #------------------------------------------------------------------------------------------------------- - - - @hook.event("player.PlayerInteractEvent") def on_click(event): if str(event.getAction()) != "RIGHT_CLICK_BLOCK": @@ -254,25 +271,22 @@ faces = { @hook.event("block.BlockBreakEvent", "monitor") def on_break(event): - try: - global checking_block - if checking_block or event.isCancelled(): - return + global checking_block + if checking_block or event.isCancelled(): + return - block = event.getBlock() - if block.getType() in (Material.SIGN_POST, Material.WALL_SIGN): - check_sign(event, block, attached = False) + block = event.getBlock() + if block.getType() in (Material.SIGN_POST, Material.WALL_SIGN): + check_sign(event, block, attached = False) - for block_face, data_values in faces.iteritems(): - block2 = block.getRelative(block_face) - if block2.getType() == Material.WALL_SIGN and block2.getData() in data_values: - check_sign(event, block2) + for block_face, data_values in faces.iteritems(): + block2 = block.getRelative(block_face) + if block2.getType() == Material.WALL_SIGN and block2.getData() in data_values: + check_sign(event, block2) - block3 = block.getRelative(BlockFace.UP) - if block3.getType() == Material.SIGN_POST: - check_sign(event, block3) - except: - error(trace()) + block3 = block.getRelative(BlockFace.UP) + if block3.getType() == Material.SIGN_POST: + check_sign(event, block3) def check_sign(event, block, attached = True): @@ -287,6 +301,7 @@ def check_sign(event, block, attached = True): save_signs() msg(player, signsMsg("Reset the %s which you just broke" % identifySign(loc))) + def can_build2(player, block): global checking_block event = BlockBreakEvent(block, player) diff --git a/setup.sh b/setup.sh index 336376f..74cc599 100755 --- a/setup.sh +++ b/setup.sh @@ -91,7 +91,7 @@ echo -e "\n> All plugins downloaded" cd "redstoner-utils.py.dir" echo -e "\n> Duplicating sample files" -for file in ls ./*.example; do +for file in ./*.example; do cp -v "$file" "$(echo "$file" | rev | cut -d "." -f 2- | rev)" done diff --git a/vanish.py b/vanish.py index a572ebc..87a667b 100644 --- a/vanish.py +++ b/vanish.py @@ -13,7 +13,7 @@ def is_vanished(player): return uid(player) in vanished -#this can be used to silently set the vanished state of a player +#this can be used to silently set the vanished state of a player I guess. def set_state(player, state): if state == is_vanished(player): return @@ -37,6 +37,10 @@ def disable_vanish(target): player.showPlayer(target) +def get_online_vanished_players(): + return (player.getPlayer() for player in (retrieve_player(uuid) for uuid in vanished) if player.isOnline()) + + @simplecommand("vanish", aliases = ["v"], usage = "[on/off]", @@ -48,45 +52,38 @@ def disable_vanish(target): helpSubcmd = True ) def vanish_command(sender, command, label, args): - try: - current_state = is_vanished(sender) - new_state = not current_state + current_state = is_vanished(sender) + new_state = not current_state - if len(args) == 1: - arg = args[0].lower() - if arg == "on": - new_state = True - elif arg == "off": - new_state = False - - if current_state == new_state: - return "&cYou were %s vanished!" % ("already" if current_state else "not yet") + if len(args) == 1: + arg = args[0].lower() + if arg == "on": + new_state = True + elif arg == "off": + new_state = False - set_state(sender, new_state) - return "&a%s vanish mode!" % ("Enabled" if new_state else "Disabled") - except: - error(trace()) + Validate.isTrue(current_state != new_state, "&cYou were %s vanished!" % ("already" if current_state else "not yet")) + set_state(sender, new_state) + return "&a%s vanish mode!" % ("Enabled" if new_state else "Disabled") @hook.event("player.PlayerJoinEvent") def on_player_join(event): player = event.getPlayer() - if not is_authorized(player): - for uuid in vanished: - player.hidePlayer(retrieve_player(uuid)) - - elif is_vanished(player): - msg(player, "&cKeep in mind that you are still vanished! Use /vanish to disable.") + for vanished in get_online_vanished_players(): + player.hidePlayer(vanished) @hook.event("player.PlayerQuitEvent") def on_player_quit(event): player = event.getPlayer() - if not is_authorized(player): - for uuid in vanished: - player.showPlayer(retrieve_player(uuid)) + for vanished in get_online_vanished_players(): + player.showPlayer(vanished) + + elif is_vanished(player): + disable_vanish(player) @simplecommand("vanishother", @@ -110,9 +107,7 @@ def vanishother_command(sender, command, label, args): elif arg == "off": new_state = False - if current_state == new_state: - return "&cThat player was already vanished!" if current_state else "&cThat player was not yet vanished!" - + Validate.isTrue(current_state != new_state, "&cThat player was %s vanished!" % ("already" if current_state else "not yet")) set_state(target, new_state) enabled_str = "enabled" if new_state else "disabled" 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) diff --git a/wrapper_event.py b/wrapper_event.py index c203cd3..083bf33 100644 --- a/wrapper_event.py +++ b/wrapper_event.py @@ -10,14 +10,6 @@ class py_event: except: warn("Player doesn't exist") - @property - def cancelled(self): - return self.event.isCancelled() - - @cancelled.setter - def cancelled(self, value): - self.event.setCancelled(value) - def event_handler(event_name = None, priority = "normal"): def decorator(wrapped): @hook.event(event_name, priority) diff --git a/wrapper_player.py b/wrapper_player.py index 4ca302a..db7f6cc 100644 --- a/wrapper_player.py +++ b/wrapper_player.py @@ -6,12 +6,15 @@ from players_secret import * from datetime import datetime from com.ziclix.python.sql import zxJDBC +def get_py_player(player): + + class py_player: def __init__(self,player): self.player = player - self.logging_in = True - self.login_time = time.time() + self.logging_in = False + self.nickname = self.name self.registered = False self.password = "None" @@ -24,9 +27,6 @@ class py_player: def kick(self, kick_message = "You have been kicked from the server!"): self.player.KickPlayer(kick_message) - def msg(self, message): - self.player.sendMessage(message) - @property def name(self): return self.player.getName() @@ -60,11 +60,6 @@ py_players = Py_players() @async(daemon=True) def fetch_player(player): - properties = (player.uuid, player.name, player.nickname, player.registered, - player.password, player.banned, - player.banned_reason, player.played_time, - player.last_login, player.first_seen) - with mysql_connect() as sql: sql.execute("SELECT * FROM utils_players WHERE uuid = ?", (player.uuid,)) result = sql.fetchall() @@ -76,39 +71,19 @@ def fetch_player(player): banned_reason, played_time, last_login, first_seen) \ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", - args=properties) - - elif len(result) is 1: - props = result[0] - print props - for prop in properties: - prop = props[properties.index(prop)] - + args=(player.uuid, player.name, player.nickname, player.registered, + player.password, player.banned, + player.banned_reason, player.played_time, + player.last_login, player.first_seen)) else: - player.kick("Something went wrong while loading your player data, please contact an admin") - return - player.logging_in = False - player.msg("You have succesfully logged into redstoner!") - - -blocked_events = ["block.BlockBreakEvent", "block.BlockPlaceEvent", "player.PlayerMoveEvent", - "player.AsyncPlayerChatEvent","player.PlayerTeleportEvent", - "player.PlayerCommandPreprocessEvent", "player.PlayerInteractEvent"] - -for event in blocked_events: - @hook.event(event,"highest") - def on_blocked_event(event): - player = py_players[event.getPlayer()] - if player.logging_in: - event.setCancelled(True) - + pass + #test @hook.event("player.PlayerJoinEvent","lowest") def on_join(event): player = py_player(event.getPlayer()) py_players.append(player) - player.msg("Your input will be blocked for a short while") fetch_player(player) -- cgit v1.2.3