diff options
author | Dico200 <dico.karssiens@gmail.com> | 2015-10-20 18:03:05 +0200 |
---|---|---|
committer | Dico200 <dico.karssiens@gmail.com> | 2015-10-20 18:03:05 +0200 |
commit | 9119c3d1500a02b49d078a8a0d01a271e630092b (patch) | |
tree | f4e46239d0739ca88a2192bd47e66bf846f2174a | |
parent | 2db8142b35a92e93459fb9a9505778db303291a9 (diff) |
Moved /signalstrength to its own file, added default configurability, added basecommands documentation, added can_build() to helpers
-rw-r--r-- | basecommands.py | 59 | ||||
-rw-r--r-- | helpers.py | 10 | ||||
-rw-r--r-- | main.py | 2 | ||||
-rw-r--r-- | misc.py | 91 |
4 files changed, 68 insertions, 94 deletions
diff --git a/basecommands.py b/basecommands.py index 89e08aa..dee79f8 100644 --- a/basecommands.py +++ b/basecommands.py @@ -1,13 +1,66 @@ from helpers import * -to_see_permission = "utils.showpermission" # See cmd permission in help +""" +@simplecommand is a decorator which is meant to replace @hook.command in redstoner-utils, where useful. +It takes care of checks such as whether the sender is a player, whether they have permission, +whether there are enough argumens, and also takes care of a help message. +On top of that, it makes the code shorter and easier to write with features like Validate, and returning a message instead of a boolean value. +@simplecommand has an inbuilt tracing feature, so you won't have to put all your code in a try/except statement anymore. +Make sure to `from basecommands import simplecommand` before using this decorator. + +The arguments are as follows: +* cmd: the command, self explanatory (required); + +* aliases: A list containing any aliases for the command, like shortcuts; + +* usage: a String defining the expected arguments for the command. Example: + Let's say I have a command /tp <player_to_teleport> <destination_player>. The usage is: "<player_to_teleport> <destination_player>". + I suggest we use the same format throughout redstoner-utils: + - Separate arguments by spaces; + - Use <> if the argument is required, and [] if the argument is optional; + - Add .. to the argument's identifier (name) if it is for example a message (containing spaces). + for example in /msg, the usage would be "<player> <msg..>" + +* description: a description of what the command does. Defaults to "Handles cmd". + This is used for the help message, where the description is (meant to be) indented. To keep this indentation + with longer descriptions, call the help message (with the command, ingame) and add '\n' + when it jumps to a new line in the chat. The decorator will take care of the indentation after that. + +* senderLimit: an integer resembling the accepted sender type. Defaults to -1. Use: + -1 for console as well as players; + 0 for players only; + 1 for console only. + +* amin: an integer resembling the minimum amount of arguments. Defaults to 0 +* amax: an integer resembling the maximum amount of arguments. Defaults to -1, which means that there is no maximum. + +* helpNoargs: a boolean value resembling whether the help message should be displayed when no arguments are given. + Defaults to False. + +* helpSubcmd: a boolean value resembling whether the help message should be displayed when the first argument.lower() equals "help". + Defaults to False. + +Comments on the function added to the decorator: +It should return a message to send to the player. Color codes are translated automatically. It can return None or an empty string to send nothing. + +Inside the function, calls to static methods in the class Validate can be used to make the code shorter and easier to write (maybe not easier to read). +For example, to make sure that a condition is met, use Validate.isTrue(condition, message to send to the player if the condition is not met) +Don't forget to `from basecommands import Validate` if you wish to make use of this. +For all other Validate checks, see the code below. Feel free to add your own. + +Instead of returning a message mid-code to describe an error, you can also use raise CommandException(msg), but it is almost always possible +to replace this return statement with a call to one of the functions in the Validate class. Once again, if you use raise CommandException(msg), +don't forget to `from basecommands import CommandException`. +""" + +to_see_permission = "utils.showpermission" # See cmd permission in help def isSenderValid(senderLimit, isPlayer): return True if senderLimit == -1 else senderLimit != isPlayer def invalidSenderMsg(isPlayer): - return "&cThat command can only be run from the console" if isPlayer else "&cThat command can only be run by players" + return "&cThat command can only be used by " + ("the console" if isPlayer else "players") def helpMsg(sender, cmd, description, usage, aliases, permission): help_msg = "&aInformation about command /%s:\n &9%s" % (cmd, description.replace("\n", "\n ")) @@ -65,7 +118,7 @@ def simplecommand(cmd, except CommandException, e: return e.message except Exception, e: - error(e.message, trace()) + error(trace()) return "&cAn internal error occurred while attempting to perform this command" return call @@ -6,6 +6,7 @@ import org.bukkit as bukkit import org.bukkit.Location as Location import org.bukkit.entity.Player as Player import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause as TeleportCause +import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent import org.bukkit.block as bblock import org.bukkit.event.entity as entity import org.bukkit.command.ConsoleCommandSender @@ -143,6 +144,15 @@ def is_player(obj): return (isinstance(obj, Player)) +def can_build(player, block): + """ + return True if the player can change/build at the location of given block + """ + event = BlockBreakEvent(block, player) + server.getPluginManager().callEvent(event) + return not event.isCancelled() + + def checkargs(sender, args, amin, amax): """ check if a command has a valid amount of args, otherwise notify the sender @@ -54,6 +54,8 @@ shared["load_modules"] = [ "webtoken", # Adds /lol, broadcasts random funyy messages. A bit like the splash text in the menu "saylol", + # Adds /signalstrength, lets you request a signal strength and an amount of items will be inserted into target container to meet that strength. + "signalstrength", # Shows the owner of a skull when right-clicked "skullclick", # Adds /listen, highlights chat and plays a sound when your name was mentioned @@ -4,11 +4,7 @@ from time import time as now from time import sleep from sys import exc_info import thread - import org.bukkit.inventory.ItemStack as ItemStack -import org.bukkit.Material as Material -from math import ceil - import org.bukkit.Bukkit as Bukkit from basecommands import simplecommand, Validate @@ -145,93 +141,6 @@ def on_sudo_command(sender, command, label, args): return "&cPlayer %s not found!" % target -""" -Suggestion by Armadillo28, see thread: http://redstoner.com/forums/threads/2213?page=1#reply-14507 - -Clarification on these formulas on http://minecraft.gamepedia.com/Redstone_Comparator#Containers -""" - -def required_item_count(strength, slots, stack): - if strength == 0: - count = 0 - elif strength == 1: - count = 1 - else: - count = int(ceil(slots * stack / 14.0 * (strength - 1))) - - resulting_strength = int(1 + 14.0 * count / stack / slots) - - return count if resulting_strength == strength else None - -@simplecommand("signalstrength", - usage = "<signal strength> [item] [data]", - aliases = ["ss", "level"], - description = "Fills the targeted container with the correct amount of items to achieve the desired signal strength.", - amin = 1, - amax = 3, - helpNoargs = True, - helpSubcmd = True, - senderLimit = 0) -def on_signalstrength_command(sender, command, label, args): - - target_block = sender.getTargetBlock(None, 5) - Validate.notNone(target_block, "&cThat command can only be used when a container is targeted") - - try: - inv = target_block.getState().getInventory() - except AttributeError: - return "&cThat command can only be used when a container is targeted" - - #---------Define the requested strength, item type and item data---------- - Validate.isTrue(args[0].isdigit() and 0 <= int(args[0]) <= 15, "&cThe signal strength has to be a value from 0 to 15") - strength = int(args[0]) - - item_type = Material.REDSTONE if len(args) < 2 else Material.getMaterial(int(args[1]) if args[1].isdigit() else args[1]) - Validate.notNone(item_type, "&cThat item id does not exist") - - item_data = 0 if len(args) < 3 else int(args[2]) if args[2].isdigit() else -1 - Validate.isTrue(0 <= item_data <= 15, "&cThe data has to be a value from 0 to 15") - - #--------Get the stack size and required amount of items to achieve the desired signal strength--------- - stack_size = item_type.getMaxStackSize() - item_count = required_item_count(strength, inv.getSize(), stack_size) - Validate.notNone(item_count, "&cThe desired signal strength could not be achieved with the requested item type") - - #------------Add the other side of the chest if target is a double chest-------------- - target_blocks = [target_block] - target_type = target_block.getType() - if target_type in (Material.CHEST, Material.TRAPPED_CHEST): - loc = target_block.getLocation() - x = loc.getBlockX() - y = loc.getBlockY() - z = loc.getBlockZ() - world = loc.getWorld() - - target_blocks += [ - block for block in ( - world.getBlockAt(x + 1, y, z), - world.getBlockAt(x - 1, y, z), - world.getBlockAt(x, y, z + 1), - world.getBlockAt(x, y, z - 1), - ) if block.getType() == target_type - ] - - #----------------Insert items------------- - full_stack_count, remaining = divmod(item_count, stack_size) - - inv.clear() - for block in target_blocks: - for i in range(full_stack_count): - inv.setItem(i, ItemStack(item_type, stack_size, item_data)) - if remaining > 0: - inv.setItem(full_stack_count, ItemStack(item_type, remaining, item_data)) - - - return "&aSuccesfully edited the targeted %s to give out a signal strenth of %s to comparators" % ( - str(target_type).lower().replace("_", " "), strength) - - - @simplecommand("me", usage = "[message..]", |