summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPanFritz <redstonenoobpan@gmail.com>2015-11-25 18:26:50 +0100
committerPanFritz <redstonenoobpan@gmail.com>2015-11-25 18:26:50 +0100
commitf7626300ea12e061ffc2124fa91be1ff2392dc94 (patch)
tree05ace95ba5cf57b8cc0a0ee2e66f857ef45f118a
parent14b6c6905ae0767596fe06b1c057db9416f0d8b2 (diff)
parent3bc7963a7a0a000fd5ae365bb5fabc59d22b189f (diff)
merge conflicts
-rw-r--r--chatalias.py4
-rw-r--r--serversigns.py53
-rwxr-xr-xsetup.sh2
-rw-r--r--vanish.py53
-rw-r--r--wrapper_command.py327
5 files changed, 380 insertions, 59 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.<subcommand> 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..b2190ac 100644
--- a/wrapper_command.py
+++ b/wrapper_command.py
@@ -1,11 +1,322 @@
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}
+
+class Command(object):
+ """
+ # 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
+ 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
+
+ # ---- Add self to parent sub_commands ----
+ 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[cmd_name]
+ parent_sub_commands = parent_obj.sub_commands
+
+ parent_obj.sub_commands[self.command] = self
+
+ except KeyError as e:
+ error("Error occurred while setting up command hierarchy: " + e.message + "\n" + trace())
+
+ 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
+
+ if parent == None:
+ @hook.command(self.command, self.aliases)
+ 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:
+ 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[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):
+
+ # ---- 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):
+ sender = py_players[sender]
+
+ return self.handler(sender, self, scape)
+ # @Command("hello") def on_hello_command(sender, command, scape/args)
+
+ def syntax(self):
+ 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):
+
+ def __init__(self, args, arg_layout, command, label):
+ super(list, self).__init__()
+ self.raw = args
+ self.arg_layout = arg_layout
+ self.command = command
+ self.label = label
+
+ 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 Argument_exception(Exception):
+
+ def __init__(self, message):
+ self.message = message
+