diff options
author | PixelSergey <sergey.ichtchenko@gmail.com> | 2015-11-22 19:56:55 +0200 |
---|---|---|
committer | PixelSergey <sergey.ichtchenko@gmail.com> | 2015-11-22 19:56:55 +0200 |
commit | e57f721db3a7e4960787099d571c5bc74a92478a (patch) | |
tree | 82e0d44e7632f4887c7e43ef6d9ed68f5ea04151 | |
parent | 2808c5838b33dac74ad3ce34c733b2b7f1199d0a (diff) | |
parent | ab42a0cb655d5e4123f8eeb8acd90de3531d0367 (diff) |
Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev
-rw-r--r-- | blockplacemods.py | 4 | ||||
-rw-r--r-- | main.py | 6 | ||||
-rw-r--r-- | serversigns.py | 418 |
3 files changed, 253 insertions, 175 deletions
diff --git a/blockplacemods.py b/blockplacemods.py index 246f9eb..85e71c5 100644 --- a/blockplacemods.py +++ b/blockplacemods.py @@ -24,7 +24,7 @@ settingInformation = dict( #[setting type, identifying description, detailed des ], furnace = [1, "automatically filling furnaces upon placement", - "Sets your preferred default furnace contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle dropper clear to clear all slots.", + "Sets your preferred default furnace contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle furnace clear to clear all slots.", ["cooker", "fillf"], 2 ], #torch = [0, @@ -44,7 +44,7 @@ settingInformation = dict( #[setting type, identifying description, detailed des ], hopper = [1, "automatically filling hoppers upon placement", - "Sets your preferred default hopper contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle dropper clear to clear all slots.", + "Sets your preferred default hopper contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle hopper clear to clear all slots.", ["itemtransporter", "fillh"], 4 ] ) @@ -43,7 +43,7 @@ shared["load_modules"] = [ # Adds /calc, toggles automatic solving of Math expressions in chat "calc", # Adds aliasing of chat words - "chatalias", + #"chatalias", # Plugin to locate laggy chunks. /lc <n> lists chunks with more than n entities "lagchunks", # Adds /report and /rp, Stores reports with time and location @@ -99,7 +99,9 @@ shared["load_modules"] = [ # a simple replacement for the buggy essentials /vanish "vanish", # ip-tracking utility - "iptracker" + "iptracker", + #server signs for everyone + "serversigns" ] shared["modules"] = {} for module in shared["load_modules"]: diff --git a/serversigns.py b/serversigns.py index c7bc23c..297b727 100644 --- a/serversigns.py +++ b/serversigns.py @@ -3,219 +3,295 @@ from basecommands import simplecommand, Validate import org.bukkit.Material as Material import java.util.UUID as UUID import org.bukkit.Material as Material -import java.util.HashSet as JSet +import org.bukkit.block.BlockFace as BlockFace +blocked_cmds = ("pex", "kick", "ban", "tempban", "pyeval", "sudo", "stop", "reload", "op", "deop", "whitelist") -cmd_use_perm = "utils.svs.cmd" -msg_use_perm = "utils.svs.msg" +def load_signs(): + signs_obj = open_json_file("serversigns", []) + loaded = {} + for entry in signs_obj: + loaded[tuple(entry[:4])] = list(entry[4:]) + return loaded -signs = open_json_file("serversigns", {}) # {("world", x, y, z): ["owner_id", "msg1", "msg2"]} +def save_signs(): + signs_obj = [] + for key, value in signs.iteritems(): + signs_obj.append(key + tuple(value)) + save_json_file("serversigns", signs_obj) -lines = {} #Accumulated messages so players can have longer messages: {"Dico200": "Message...........", ""} +signs = load_signs() # {("world", x, y, z): ["owner_id", "msg1", "msg2"]} -transparent_blocks_set = JSet([Material.AIR, Material.GLASS, Material.STAINED_GLASS]) #used in sender.getTargetBlock() +lines = {} # Accumulated messages so players can have longer messages: {"Dico200": "Message...........", ""} -@simplecommand(cmd = "serversigns", aliases = ["svs", "signmsg"], - description = "Makes something happen when you right click certain signs", - usage = "[claim|unclaim|add <msg>|remove <line>|clear|info|help]", - helpNoargs = True, - senderLimit = 0) -def svs_command(sender, command, label, args): - try: - arg1 = args[0].lower() - if arg1 not in ("add", "remove", "clear", "claim", "unclaim", "help"): - return "&4That argument could not be recognized, use &o/svs &4help for more information" - - sender = server.getPlayer(sender.getName()) - block = sender.getTargetBlock(transparent_blocks_set, 8) - info("Block type: " + str(block.getType())) - if block.getType() not in (Material.SIGN_POST, Material.WALL_SIGN): - return "&4You have to be looking at a sign to use that!" - - loc = fromLoc(block.getLocation()) - sign = getSign(loc) - arglen = len(args) - arg2 = args[1].lower() if arglen > 1 else None - - - if arg1 == "claim": - Validate.isAuthorized(sender, "utils.serversigns.claim") - target = sender - if arg2: - Validate.isAuthorized(sender, "utils.serversigns.admin") - target = server.getOfflinePlayer(arg2) - Validate.notNone(target, signsMsg("That player could not be found", '4')) - - Validate.isPlayer(target) - uuid = uid(sender) - if sign != None: - if sign[0] == uuid: - return signsMsg(identifySign(loc, True) + " was already owned by that player", '4') - else: - sign[0] = uuid - else: - signs[loc] = [uuid] - - return signsMsg("Claimed " + identifySign(loc)) - - - elif arg1 == "unclaim": - Validate.isAuthorized(sender, "utils.serversigns.unclaim") - Validate.isTrue(canEdit(sign, sender), signsMsg("You cannot unclaim the %s!" % identifySign(loc)), '4') - - if not (("-c" in args) and sender.hasPermission("utils.serversigns.admin")): - del signs[locAt] - return signsMsg("The %s was reset successfully" % identifySign(loc)) - sign[0] = "" - return signsMsg("The %s had its owner removed successfully" % identifySign(loc)) - - - elif arg1 == "help": - admin = sender.hasPermission("utils.serversigns.admin") - - return - - - elif arg1 == "add": - Validate.isTrue(canEdit(sign, sender), signsMsg("You cannot edit the %s!" % identifySign(loc)), '4') - line = " ".join(args[1:]) - Validate.isTrue(line != "" and line != None, signsMsg("You have to enter a message to add or accumulate!", '4')) - key = sender.getName() - - Validate.isTrue(key in lines or line[:1] != "/" or sender.hasPermission("utils.serversigns.command"), signsMsg("You cannot add commands to a sign!", '4')) - - if line[-2:] == "++": - if key not in lines: - lines[key] = "" - lines[key] += " " + line[:-2] - elif key in lines: - line = lines[key] + " " + line - sign.append(colorify(line) if line[0] != "/" else line) - return signsMsg("Added line \"%s&a\" to the %s" % (line, identifySign(loc))) - - - elif arg1 == "info": - Validate.notNone(sign, signsMsg("The %s has not been claimed" % identifySign(loc), '4')) - lines = "" - for id, line in enumerate(sign[1:]): - lines += ("\n &a%s: \"%s&a\"" % (id + 1, line)) - msg = signsMsg("Some information about the %s:\n Owner: %s\n Lines: %s" % identifySign(loc), getOwner(sign), lines) - - - elif arg1 == "remove": - Validate.notNone(arg2, signsMsg("You have to enter the ID of the message to remove!", '4')) - try: - id = int(arg2) - except: - return signsMsg("The ID of the message has to be a number and can be found by using &o/svs info", '4') - Validate.isTrue(id != 0 and id < len(sign), signsMsg("The %s has no message with an ID of %s, use &o/svs info &4for all messages." % (identifySign(loc), id), '4')) - sign.remove(id) - return signsMsg("Removed message with id %s from the %s" % (id, identifySign(loc))) - except: - error(trace()) - - - -@hook.event("player.PlayerInteractEvent") -def onClick(event): - if str(event.getAction()) != "RIGHT_CLICK_BLOCK": - return - block = event.getClickedBlock() - if block.getType() not in (Material.WALL_SIGN, Material.SIGN_POST): - return - sign = getSign(fromLoc(block.getLocation())) - if sign != None: - player = event.getPlayer() - for message in sign[1:]: - if message[:1] == "/": - server.dispatchCommand(player, message[1:]) - else: - msg(player, message, usecolor = False) - -def fromLoc(bLoc): #Bukkit Location to ("world", x, y, z) +def fromLoc(bLoc): + """ + # Returns a tuple containing the (bukkit)location's world's name and its x, y and z coordinates + # The format for the tuple is ("world_name", x, y, z) + """ return (bLoc.getWorld().getName(), bLoc.getBlockX(), bLoc.getBlockY(), bLoc.getBlockZ()) def equals(loc1, loc2): + """ + # Returns whether loc1 and loc2 represent the same block + """ for i in range(4): if loc1[i] != loc2[i]: return False return True def getOwner(sign): + """ + # Returns the name of the sign its owner + """ return retrieve_player(sign[0]).getName() def isOwner(sign, player): + """ + # Returns whether the given player owns the sign + """ return sign and sign[0] == uid(player) def canEdit(sign, player): - return player.hasPermission("utils.serversigns.admin") or isOwner(sign, player) + """ + # Returns whether the given player can edit the sign. + # Returns False if the sign wasn't claimed. + """ + return (sign and player.hasPermission("utils.serversigns.admin")) or isOwner(sign, player) def getSign(locAt): + """ + # If data was found for a sign at the given location, returns the data. + # This data follows the format of ["owner_id", "msg1", "msg2"...]. + """ for loc, sign in signs.iteritems(): if equals(locAt, loc): return sign return None -def identifySign(loc, capital = False): - return "%sign at (%s) in %s" % ("S" if capital else "s", ",".join(loc[1:]), loc[0]) - -def signsMsg(msg, colour = 'a'): +def identifySign(loc): + """ + # Returns a string from which the user can tell what sign you're talking about. + # The string follows the format of "sign at (x,y,z) in world_name". + """ + return "sign at (%s) in %s" % (",".join((str(i) for i in loc[1:])), loc[0]) + +def signsMsg(msg, colour = '4'): + """ + # Returns the given msg, prefixed with '[Signs] '. + # The given colour is after applied to the msg. + # The colour defaults to 4 (dark red). + """ return "&c[Signs] &" + colour + msg +@simplecommand(cmd = "serversigns", aliases = ["svs", "signmsg"], + description = "Makes something happen when you right click signs. \nUse /svs help for more details.", + usage = "<claim|reset|add <msg>[++]|remove <ID>|clear|info|help>", + helpNoargs = True, + senderLimit = 0) +def svs_command(sender, command, label, args): + arg1 = args[0].lower() + Validate.isTrue(arg1 in ("claim", "reset", "add", "remove", "info", "clear", "help", "switch", "reverse", "unclaim"), + signsMsg("That argument could not be recognized, use &o/svs help &4for expected arguments")) + Validate.isAuthorized(sender, "utils.serversigns." + arg1) + + #-------------------- Sub commands that don't require any conditions ----------------------- + if arg1 == "help": + admin = sender.hasPermission("utils.serversigns.admin") + msg = signsMsg("Server signs lets you add messages to a sign.", 'a') + msg += "\nRight clicking the sign will display all the messages. Commands" + msg += "\ncan also be added, by prefixing the message with a '/'." + msg += "\nHow to use &b/serversigns&a:" + msg += "\n&b/svs claim" + ("" if not sender.hasPermission("utils.serversigns.admin") else " [owner]") + msg += "\n&a- Claims the sign so that you can add messages to it" + msg += "\n&b/svs info" + msg += "\n&a- Displays information about the (claimed) sign" + msg += "\n&b/svs add <message>[++]" + msg += "\n&a- Adds the message to the sign. Use ++ at the end" + msg += "\n&a- to add the message to your buffer. You can then use" + msg += "\n&a- the same command again to create a longer message." + msg += "\n&b/svs remove <message ID>" + msg += "\n&a- Removes the message with the given ID from the sign." + msg += "\n&a- The ID is given before each message by &b/svs info&a." + msg += "\n&b/svs switch|reverse <message ID 1> <message ID 2>" + msg += "\n&a- Reverses the order in which the given messages are shown." + msg += "\n&b/svs clear" + msg += "\n&a- Removes all messages from the sign." + msg += "\n&b/svs reset|unclaim" + msg += "\n&a- Resets the sign, removing all messages and its owner." + return msg + #------------------------------------------------------------------------------------------- + + block = sender.getTargetBlock(None, 5) + Validate.isTrue(block.getType() in (Material.SIGN_POST, Material.WALL_SIGN), signsMsg("You have to be looking at a sign to use that!")) + + loc = fromLoc(block.getLocation()) + sign = getSign(loc) + signName = identifySign(loc) + arg2 = args[1].lower() if len(args) > 1 else None + + #------------------------ Sub commands that require the block to be a sign ------------------------------- + if arg1 == "claim": + Validate.isTrue(not sign, signsMsg("The %s was already claimed" % signName)) + Validate.isTrue(can_build2(sender, block), signsMsg("You are not permitted to claim signs here")) + target = sender + if arg2: + Validate.isTrue(player.hasPermission("utils.serversigns.admin"), signsMsg("You are not authorized to claim signs for other players")) + target = server.getOfflinePlayer(arg2) + Validate.notNone(target, signsMsg("That player could not be found")) + Validate.isTrue(target.isOnline(), signsMsg("The target has to be online")) + uuid = uid(target) + if sign != None: + if sign[0] == uuid: + return signsMsg("The" + signName + " was already owned by that player") + else: + sign[0] = uuid + else: + signs[loc] = [uuid] + save_signs() + return signsMsg("Claimed the " + signName + ((" for %s" % target.getName()) if (target != sender) else ""), 'a') + #---------------------------------------------------------------------------------------------------------- + + Validate.notNone(sign, signsMsg("The %s has not been claimed" % signName)) + + #----------------------Sub commands that require the sign to be claimed as well------------------------------------ + if arg1 == "info": + sign_lines = "" + for id, line in enumerate(sign[1:]): + sign_lines += ("\n &a%s: \"&f%s&a\"" % (id + 1, line)) + return signsMsg("Properties of the %s:\n Owner: %s\n Lines: %s" % (signName, getOwner(sign), sign_lines), 'a') + #--------------------------------------------------------------------------------------------------------------- + + Validate.isTrue(canEdit(sign, sender), signsMsg("You do not own the %s!" % signName)) + + #---------------------- Sub commands that require you to own targeted sign as well ------------------------- + if arg1 == "add": + line = " ".join(args[1:]) + Validate.isTrue(line != "" and line != None, signsMsg("You have to enter a message to add or accumulate")) + key = sender.getName() + global lines + Validate.isTrue(key in lines or line[:1] != "/" or sender.hasPermission("utils.serversigns.command"), signsMsg("You cannot add commands to a sign!")) + if line[-2:] == "++": + if key not in lines: + lines[key] = "" + lines[key] += " " + line[:-2] + return signsMsg("Added given message to the message you're accumulating. \nYour accumulated message is now as follows: \n&f%s" % lines[key], 'a') + if key in lines: + line = (lines[key] + " " + line)[1:] + Validate.isTrue(line[0] != "/" or line.split(" ")[0][1:] not in blocked_cmds, signsMsg("Usage of that command with server signs is prohibited")) + sign.append(colorify(line) if line[0] != "/" else line) + save_signs() + return signsMsg("Added line \"&f%s&a\" to the %s" % (line, signName), 'a') + + + if arg1 == "remove": + Validate.notNone(arg2, signsMsg("You have to enter the ID of the message to remove!")) + try: + id = int(arg2) + except: + return signsMsg("The ID of the message has to be a number and can be found by using &o/svs info") + Validate.isTrue(id != 0 and id < len(sign), signsMsg("The %s has no message with an ID of %s, use &o/svs info &4for all messages." % (signName, id))) + del sign[id] + return signsMsg("Removed message with id %s from the %s" % (id, signName), 'a') + + + if arg1 in ("switch", "reverse"): + Validate.isTrue(len(args) == 3, signsMsg("You have to enter the 2 IDs of the messages to reverse")) + try: + id1 = int(args[1]) + id2 = int(args[2]) + except: + return signsMsg("The ID of the message has to be a number and can be found by using &o/svs info") + for id in (id1, id2): + Validate.isTrue(id != 0 and id < len(sign), signsMsg("The %s has no message with an ID of %s, use &o/svs info &4for all messages." % (signName, id))) + sign[id1], sign[id2] = sign[id2], sign[id1] + save_signs() + return signsMsg("Reversed the messages with IDs %s and %s of the %s" % (id1, id2, signName), 'a') + + + if arg1 == "clear": + signs[loc] = [sign[0]] + save_signs() + return signsMsg("Removed all messages from the %s" % signName, 'a') + + + if arg1 in ("reset", "unclaim"): + del signs[loc] + save_signs() + return signsMsg("Removed all messages and the owner from the %s, it can now be claimed" % signName, 'a') + #------------------------------------------------------------------------------------------------------- -""" -def eventhook(event, priority = "normal"): - - if "." not in event: - word = "" - for s in event: - if word != "" and s in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": - break; - word += s.lower() - event = "%s.%s" % (word, event) - - def decorator(function): - - @hook.event(event, priority) - def hook(event): - try: - function(event) - except EventException, e: - pass - - return hook - - return decorator - -class EventException(Exception): - def __init__(self, msg): - self.msg = msg - -"" -@eventhook("PlayerInteractEvent") -def x(event): - - p = event.getPlayer() - if p == None: - raise EventException(Stuff) -"" -""" - - - - - +@hook.event("player.PlayerInteractEvent") +def on_click(event): + if str(event.getAction()) != "RIGHT_CLICK_BLOCK": + return + block = event.getClickedBlock() + if block.getType() not in (Material.WALL_SIGN, Material.SIGN_POST): + return + sign = getSign(fromLoc(block.getLocation())) + if sign != None: + player = event.getPlayer() + for message in sign[1:]: + if message[:1] == "/": + server.dispatchCommand(player, message[1:]) + else: + msg(player, message, usecolor = False) +# ---------------------------Sign breaking-------------------------------- +checking_block = False +faces = { + BlockFace.NORTH : (0,1,2,), + BlockFace.SOUTH : (3,), + BlockFace.WEST : (4,), + BlockFace.EAST : (5,), +} +@hook.event("block.BlockBreakEvent", "monitor") +def on_break(event): + try: + 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) + 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()) +def check_sign(event, block, attached = True): + player = event.getPlayer() + sign = getSign(fromLoc(block.getLocation())) + if not can_build2(player, block): + event.setCancelled(True) + msg(event.getPlayer(), signsMsg("You cannot break %s" % ("the sign attached to that block" if attached else "that sign"))) + else: + loc = fromLoc(block.getLocation()) + del signs[loc] + 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) + checking_block = True + server.getPluginManager().callEvent(event) + checking_block = False + return not event.isCancelled() |