summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPixelSergey <sergey.ichtchenko@gmail.com>2015-11-22 19:56:55 +0200
committerPixelSergey <sergey.ichtchenko@gmail.com>2015-11-22 19:56:55 +0200
commite57f721db3a7e4960787099d571c5bc74a92478a (patch)
tree82e0d44e7632f4887c7e43ef6d9ed68f5ea04151
parent2808c5838b33dac74ad3ce34c733b2b7f1199d0a (diff)
parentab42a0cb655d5e4123f8eeb8acd90de3531d0367 (diff)
Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev
-rw-r--r--blockplacemods.py4
-rw-r--r--main.py6
-rw-r--r--serversigns.py418
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
]
)
diff --git a/main.py b/main.py
index 4769bc5..7411d17 100644
--- a/main.py
+++ b/main.py
@@ -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()