summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDico200 <dico.karssiens@gmail.com>2016-05-30 00:08:45 +0200
committerDico200 <dico.karssiens@gmail.com>2016-05-30 00:08:45 +0200
commitfa03a689639435fbf023679b09efb7782820c919 (patch)
treee34eb02113b20902d11de8c7933d88123e2ec572
parent612b86c50ba1e41b7bf26872c5f14f6595dab240 (diff)
parentfe32e7a49cea69678101da332827ca7603a8fe90 (diff)
Merge branch 'dev'
-rw-r--r--blockplacemods.py199
-rw-r--r--chatalias.py469
-rw-r--r--chatgroups.py22
-rw-r--r--damnspam.py8
-rw-r--r--friends.py4
-rwxr-xr-x[-rw-r--r--]helpers.py48
-rw-r--r--imbusy.py358
-rwxr-xr-x[-rw-r--r--]iptracker.py215
-rw-r--r--loginsecurity.py1
-rw-r--r--main.py19
-rw-r--r--misc.py29
-rwxr-xr-xnametags.py37
-rw-r--r--player.py5
-rw-r--r--plugin.yml1
-rw-r--r--pmtoggle.py6
-rw-r--r--serversigns.py473
-rwxr-xr-xsetup.sh4
-rw-r--r--signalstrength.py4
-rw-r--r--synchronizeranks.py84
19 files changed, 1371 insertions, 615 deletions
diff --git a/blockplacemods.py b/blockplacemods.py
index 246f9eb..d012e54 100644
--- a/blockplacemods.py
+++ b/blockplacemods.py
@@ -9,7 +9,18 @@ import org.bukkit.inventory.ItemStack as ItemStack
import org.bukkit.Material as Material
import org.bukkit.event.block.Action as Action
import org.bukkit.block.BlockFace as BlockFace
-import org.bukkit.scheduler.BukkitRunnable as Runnable
+import org.bukkit.scheduler.BukkitRunnable as BukkitRunnable
+
+"""
+ # Permissions:
+ # - utils.toggle: for use of the command
+ # - utils.toggle.cauldron
+ # - utils.toggle.slab
+ # - utils.toggle.furnace
+ # - utils.toggle.piston
+ # - utils.toggle.dropper
+ # - utils.toggle.hopper
+"""
settingInformation = dict( #[setting type, identifying description, detailed description, aliases, (optional) max slot id], setting types: 0 = toggle, default on. 1 = Set your setting to held itemstack, 2 = toggle, default off
cauldron = [0,
@@ -24,14 +35,14 @@ 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,
- # "removal of torches you place on redstone blocks",
- # "Toggles whether redstone torches which you place on redstone blocks will be deleted after a short amount of delay.",
- # ["redstonetorch", "tor"]
- #],
+ torch = [0,
+ "removal of torches you place on redstone blocks",
+ "Toggles whether redstone torches which you place on redstone blocks will be deleted after a short amount of delay.",
+ ["redstonetorch", "tor"]
+ ],
piston = [2,
"rotating pistons, droppers and hoppers to face the block you place them against",
"Toggles whether pistons or sticky pistons which you place will be rotated to face the block which you placed them against.",
@@ -44,7 +55,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
]
)
@@ -55,7 +66,7 @@ defaults = {
2: list
}
-faces = {
+piston_faces = {
BlockFace.DOWN : 0,
BlockFace.UP : 1,
BlockFace.NORTH : 2,
@@ -64,6 +75,14 @@ faces = {
BlockFace.EAST : 5
}
+torch_faces = {
+ 1: BlockFace.WEST,
+ 2: BlockFace.EAST,
+ 3: BlockFace.NORTH,
+ 4: BlockFace.SOUTH,
+ 5: BlockFace.DOWN
+}
+
playerSettings = open_json_file("blockplacemods", {})
for setting, details in settingInformation.iteritems():
@@ -117,14 +136,14 @@ def toggle_command(sender, command, label, args):
elif arg2 in ("toggle", "switch"):
new = not enabled
elif arg2 in ("on", "enable"):
- new = not default
+ new = True
elif arg2 in ("off", "disable"):
- new = default
+ new = False
else:
return " &cArgument '%s' was not recognized. \n Use &o/toggle %s info &cfor more information" % (arg2, setting)
- if enabled == new:
+ if enabled is new:
return " &cAlready %s: &a%s" % ("enabled" if enabled else "disabled", details[1])
- if new == default:
+ if new is default:
values.remove(uuid)
else:
values.append(uuid)
@@ -139,9 +158,11 @@ def toggle_command(sender, command, label, args):
if arg2 == "clear":
if enabled:
del values[uuid]
- return " &aDisabled " + details[1]
+ saveSettings()
+ return " &aDisabled " + details[1]
+ return " &cAlready disabled: " + details[1]
- if arg2 == "details":
+ if arg2 == "info":
return " &aSetting %s:\n &9%s \n&6Accepted arguments: [<slot>|clear|details]" % (setting, details[2])
slot = int(arg2) if arg2.isdigit() else 0
@@ -154,10 +175,11 @@ def toggle_command(sender, command, label, args):
items = values[uuid]
if slot in items:
del items[slot]
- saveSettings()
if len(items) == 0:
del items
+ saveSettings()
return " &aDisabled " + details[1]
+ saveSettings()
return " &aCleared slot %s of setting %s" % (slot, setting)
return " &cSlot %s of setting %s was already cleared!" % (slot, setting)
return " &cAlready disabled: " + details[1]
@@ -186,59 +208,63 @@ def isEnabled(toggleSetting, uuid):
@hook.event("block.BlockPlaceEvent", "monitor")
def on_block_place(event):
- if event.isCancelled():
- return
- player = event.getPlayer()
- if not is_creative(player):
- return
-
- uuid = uid(player)
- block = event.getBlockPlaced()
- material = block.getType()
-
-
- if (material in (Material.WOOD_STEP, Material.STEP)
- and isEnabled("slab", uuid)
- and player.hasPermission("utils.toggle.slab")
- and block.getData() < 8
- ):
- block.setData(block.getData() + 8) # Flip upside down
-
-
- elif (material == Material.CAULDRON
- and isEnabled("cauldron", uuid)
- and player.hasPermission("utils.toggle.cauldron")
- ):
- block.setData(3) #3 layers of water, 3 signal strength
-
-
- elif ((material == Material.FURNACE and player.hasPermission("utils.toggle.furnace"))
- or (material == Material.DROPPER and player.hasPermission("utils.toggle.dropper"))
- or (material == Material.HOPPER and player.hasPermission("utils.toggle.hopper"))
- ):
- stacks = get(str(material).lower()).get(uuid)
- if stacks != None: # Enabled
- state = block.getState()
- inv = state.getInventory()
- for slot, stack in stacks.iteritems():
- inv.setItem(int(slot), toStack(stack))
- state.update()
-
- """
- elif (material == Material.REDSTONE_TORCH_ON
- and event.getBlockAgainst().getType() == Material.REDSTONE_BLOCK
- and isEnabled("torch", uuid)
- and player.hasPermission("utils.toggle.torch")
- ):
- torches_to_break.append(block)
- """
-
+ try:
- if (material in (Material.PISTON_BASE, Material.PISTON_STICKY_BASE)
- and isEnabled("piston", uuid)
- and player.hasPermission("utils.toggle.piston")
- ):
- block.setData(faces[block.getFace(event.getBlockAgainst())])
+ if event.isCancelled():
+ return
+ player = event.getPlayer()
+ if not is_creative(player):
+ return
+
+ uuid = uid(player)
+ block = event.getBlockPlaced()
+ material = block.getType()
+
+
+ if (material in (Material.WOOD_STEP, Material.STEP)
+ and isEnabled("slab", uuid)
+ and player.hasPermission("utils.toggle.slab")
+ and block.getData() < 8
+ ):
+ block.setData(block.getData() + 8) # Flip upside down
+
+
+ elif (material == Material.CAULDRON
+ and isEnabled("cauldron", uuid)
+ and player.hasPermission("utils.toggle.cauldron")
+ ):
+ block.setData(3) #3 layers of water, 3 signal strength
+
+
+ elif ((material == Material.FURNACE and player.hasPermission("utils.toggle.furnace"))
+ or (material == Material.DROPPER and player.hasPermission("utils.toggle.dropper"))
+ or (material == Material.HOPPER and player.hasPermission("utils.toggle.hopper"))
+ ):
+ stacks = get(str(material).lower()).get(uuid)
+ if stacks != None: # Enabled
+ state = block.getState()
+ inv = state.getInventory()
+ for slot, stack in stacks.iteritems():
+ inv.setItem(int(slot), toStack(stack))
+ state.update()
+
+
+ elif (material == Material.REDSTONE_TORCH_ON
+ and isEnabled("torch", uuid)
+ and player.hasPermission("utils.toggle.torch")
+ and block.getData() in torch_faces
+ and block.getRelative(torch_faces[block.getData()]).getType() is Material.REDSTONE_BLOCK
+ ):
+ torches_to_break.append(block)
+
+
+ elif (material in (Material.PISTON_BASE, Material.PISTON_STICKY_BASE)
+ and isEnabled("piston", uuid)
+ and player.hasPermission("utils.toggle.piston")
+ ):
+ block.setData(piston_faces[block.getFace(event.getBlockAgainst())])
+ except:
+ error(trace())
@hook.event("player.PlayerInteractEvent", "monitor")
@@ -257,29 +283,36 @@ def on_interact(event):
if not event2.isCancelled():
block.setData(block.getData() - 1 if block.getData() > 0 else 3)
-"""
+
break_torches = True
torches_to_break = deque()
def stop_breaking_torches():
break_torches = False
- info("Interrupted torch breaking thread")
+ info("[BlockPlaceMods] Interrupted torch breaking thread")
+
+class JBukkitRunnable(BukkitRunnable):
-class torch_breaker(Runnable):
+ def __init__(self, func):
+ self.run = func
- def run():
- try:
- if break_torches:
- for i in range(len(torches_to_break)):
- block = torches_to_break.popleft()
- mat = block.getType()
- if mat == Material.REDSTONE_TORCH_OFF:
- block.setTypeId(0)
- elif mat == Material.REDSTONE_TORCH_ON:
+def torch_breaker():
+
+ try:
+ if break_torches:
+ for i in range(len(torches_to_break)):
+ block = torches_to_break.popleft()
+ mat = block.getType()
+ if mat == Material.REDSTONE_TORCH_OFF:
+ block.setTypeId(0)
+ elif mat == Material.REDSTONE_TORCH_ON:
+ if block.getData() in torch_faces and block.getRelative(torch_faces[block.getData()]).getType() is Material.REDSTONE_BLOCK:
torches_to_break.append(block)
- except:
- error(trace())
-"""
+ except:
+ error(trace())
+
+def schedule_torch_breaker():
+ JBukkitRunnable(torch_breaker).runTaskTimer(server.getPluginManager().getPlugin("RedstonerUtils"), 0, 1)
diff --git a/chatalias.py b/chatalias.py
index dc7db72..bc21e13 100644
--- a/chatalias.py
+++ b/chatalias.py
@@ -1,127 +1,386 @@
-# Chat Aliasing plugin by Curs3d #
-##################################
-# Allows users to alias words,
-# so that when they send a
-# message in chat, it gets
-# replaced by their specified
-# word. Configuration of this
-# plugin is in the "gnl"
-# (general) tag of the JSON
-# file named "aliases". The
-# file is generated if not
-# present. Set values to -1
-# for "unlimited" setting.
+# TODO: Add cg/ac/msg support
+import os
+import mysqlhack
+import org.bukkit as bukkit
+from org.bukkit import *
from helpers import *
-from traceback import format_exc as trace
-data = None
+# Version number and requirements
-def safe_open_json():
- global data
- if data is not None:
- return data
- data = open_json_file("aliases")
- if data is None:
- data = {"gnl":{"max_len":"35","max_entries":"10"}}
- save_json_file("aliases", data)
- return data
+alias_version = "2.1.0"
+helpers_versions = ["1.1.0", "2.0.0"]
+enabled = False
+error_msg = colorify("&cUnspecified error")
+commands_per_page = 5
+global_aliases = {"./":"/"}
+data = {}
+use_mysql = True
+# Permissions:
-@hook.command("alias", usage = "/<command> [to_alias] [alias...]", desc = "Aliases words in chat")
-def on_alias_command(sender, cmd, label, args):
+# Grants full access immediately
+permission_ALL = "utils.alias.*"
+# Access to the command to display the help screen
+permission_BASE = "utils.alias"
+# Make replacements only when the user has this permission
+permission_USE = "utils.alias.use"
+# Modify aliases
+permission_MODIFY = "utils.alias.modify"
+permission_MODIFY_OTHERS = "utils.alias.modify.others"
+# List aliases
+permission_LIST = "utils.alias.list"
+permission_LIST_OTHERS = "utils.alias.list.others"
+# Set alias amounts/length limits, e.g. utils.alias.amount.420
+permission_AMOUNT = "utils.alias.amount."
+permission_LENGTH = "utils.alias.length."
+# See when the plugin was disabled due to version errors
+permission_INFO = "utils.alias.info"
+permission_FINFO = "utils.alias.finfo"
- if not is_player(sender):
- msg(sender, "Sorry, Console cannot alias words")
- return True
+########
+# CODE #
+########
- if not sender.hasPermission("utils.alias.allowed"):
- plugin_header(recipient = sender, name = "Chat Alias")
- noperm(sender)
- return True
+def safe_open_json(uuid):
+ if not os.path.exists("plugins/redstoner-utils.py.dir/files/aliases"):
+ os.makedirs("plugins/redstoner-utils.py.dir/files/aliases")
+ value = open_json_file("aliases/" + uuid)
+ if value is None:
+ value = dict(global_aliases)
+ save_json_file("aliases/" + uuid, value)
+ return value
- if len(args) == 0:
- plugin_header(recipient = sender, name = "Chat Alias")
- msg(sender, "This is a plugin that allows you to type in chat and have words replaced by other ones automatically!")
- msg(sender, "\nCommands:")
- msg(sender, "/alias <word>: removes <word> from aliased words. Use * to remove all aliased words.")
- msg(sender, "/alias <word> <others...>: Will change <word> to <others...> in chat")
- msg(sender, "\nYour Aliases:")
- data = safe_open_json()
- try:
- for alias, value in data[str(sender.getUniqueId())].items():
- msg(sender, "%s ==> %s" % (alias, value))
- except KeyError:
- pass
- return True
- elif len(args) == 1:
- data = safe_open_json()
- if args[0] == "*":
- try:
- del data[str(sender.getUniqueId())]
- except KeyError:
- plugin_header(recipient = sender, name = "Chat Alias")
- msg(sender, "No alias data to remove!")
- return True
- save_json_file("aliases", data)
- plugin_header(recipient = sender, name = "Chat Alias")
- msg(sender, "ALL alias data successfuly removed!")
+@hook.command("alias",
+ usage="/<command> <add, remove, list, help> [...]",
+ desc="Allows aliasing of words")
+def on_alias_command(sender, cmd, label, args):
+ if not is_player(sender):
+ msg(sender, "&cThe console cannot use aliases!")
+ return True
+ try:
+ args = array_to_list(args)
+ if not enabled:
+ disabled_fallback(sender)
return True
-
- try:
- if data[str(sender.getUniqueId())].pop(args[0], None) is None:
- plugin_header(recipient = sender, name = "Chat Alias")
- msg(sender, "Could not remove: alias not present!")
- return True
- except KeyError:
- plugin_header(recipient = sender, name = "Chat Alias")
- msg(sender, "Could not remove: you do not have any aliases!")
+ if not hasPerm(sender, permission_BASE):
+ plugin_header(recipient=sender, name="Alias")
+ noperm(sender)
return True
-
- save_json_file("aliases", data)
- plugin_header(recipient = sender, name = "Chat Alias")
- msg(sender, "Alias for %s successfuly removed" % args[0])
+ return subcommands[args[0].lower()](sender, args[1:])
+ except:
+ return subcommands["help"](sender, "1")
+
+
+def help(sender, args):
+ commands = [colorify("&e/alias help [page]")]
+ if hasPerm(sender, permission_LIST):
+ commands += [colorify("&e/alias list &7- Lists all your aliases")]
+ if hasPerm(sender, permission_MODIFY):
+ commands += [colorify("&e/alias add <word> <alias> &7- Add an alias")]
+ commands += [colorify("&e/alias remove <word> &7- Remove an alias")]
+ if can_remote(sender):
+ while len(commands) < commands_per_page:
+ commands += [""]
+ commands += [colorify("&7Following commands will be executed on <player> yet all output will be redirected to you, except when you set silent to false, then <player> will see it too.")]
+ if hasPerm(sender, permission_LIST_OTHERS):
+ commands += [colorify("&e/alias player <name> list [silent]")]
+ if hasPerm(sender, permission_MODIFY_OTHERS):
+ commands += [colorify("&e/alias player <name> add <word> <alias> [silent]")]
+ commands += [colorify("&e/alias player <name> remove <word> [silent]")]
+ pages = (len(commands)-1)/commands_per_page + 1
+ page = 1
+ if len(args) != 0:
+ page = int(args[0])
+ if (page > pages):
+ page = pages
+ if page < 1:
+ page = 1
+ msg(sender, colorify("&e---- &6Help &e-- &6Page &c" + str(page) + "&6/&c" + str(pages) + " &e----"))
+ page -= 1
+ to_display = commands[5*page:5*page+5]
+ for message in to_display:
+ msg(sender, message)
+ if page+1 < pages:
+ msg(sender, colorify("&6To display the next page, type &c/alias help " + str(page+2)))
+ return True
+
+
+@hook.event("player.PlayerJoinEvent", "high")
+def on_join(event):
+ if enabled:
+ t = threading.Thread(target=load_data, args=(uid(event.getPlayer()), ))
+ t.daemon = True
+ t.start()
+ else:
+ if event.getPlayer().hasPermission(permission_FINFO):
+ disabled_fallback(event.getPlayer())
+
+
+@hook.event("player.AsyncPlayerChatEvent", "high")
+def on_player_chat(event):
+ if enabled:
+ if event.isCancelled():
+ return
+ player = event.getPlayer()
+ if not hasPerm(player, permission_USE):
+ return
+ msg_limit = int(get_permission_content(player, permission_LENGTH))
+ for alias, value in data[str(uid(player))].items():
+ if player.hasPermission("essentials.chat.color"):
+ event.setMessage(event.getMessage().replace(colorify(alias), colorify(value)))
+ else:
+ event.setMessage(event.getMessage().replace(alias, value))
+ if not player.hasPermission(permission_ALL) and len(event.getMessage()) > msg_limit:
+ event.setCancelled(True)
+ plugin_header(player, "Alias")
+ msg(player, "The message you wanted to generate would exceed the length limit limit of %d. Please make it shorter!" % msg_limit)
+ return
+
+
+def hasPerm(player, permission):
+ return (player.hasPermission(permission)) or (player.hasPermission(permission_ALL))
+
+
+def disabled_fallback(receiver):
+ if not hasPerm(receiver, permission_INFO):
+ msg(receiver, colorify("&cUnknown command. Use &e/help&c, &e/plugins &cor ask a mod."))
+ else:
+ msg(receiver, colorify("&cPlugin alias v" + alias_version + " has experienced an &eEMERGENCY SHUTDOWN:"))
+ msg(receiver, error_msg)
+ msg(receiver, colorify("&cPlease contact a dev/admin (especially pep :P) about this to take a look at it."))
+
+
+def can_remote(player):
+ return hasPerm(player, permission_LIST_OTHERS) or hasPerm(player, permission_MODIFY_OTHERS)
+
+
+def add(sender, args):
+ plugin_header(sender, "Alias")
+ uuid = uid(sender)
+ args = [args[0]] + [" ".join(args[1:])]
+ if (args[0] not in data[uuid]) and is_alias_limit_reached(sender, sender):
return True
-
- elif len(args) >= 2:
- data = safe_open_json()
- alias = " ".join(args[1:])
- try:
- if len(alias) > int(data["gnl"]["max_len"]) and int(data["gnl"]["max_len"]) >= 0:
- plugin_header(recipient = sender, name = "Chat Alias")
- msg(sender, "Please do not alias long words/sentences.")
- return True
-
- if len(data[str(sender.getUniqueId())]) >= int(data["gnl"]["max_entries"]) and int(data["gnl"]["max_entries"]) >= 0:
- plugin_header(recipient = sender, name = "Chat Alias")
- msg(sender, "You have reached the maximum amount of alias entries! Sorry!")
- return True
- except KeyError:
- data[str(sender.getUniqueId())] = {}
-
- data[str(sender.getUniqueId())][args[0]] = alias
- save_json_file("aliases", data)
- plugin_header(recipient = sender, name = "Chat Alias")
- msg(sender, "Chat Alias %s ==> %s successfully created!" % (args[0], alias))
+ if not add_alias_data(uuid, str(args[0]), args[1]):
+ msg(sender, colorify("&c") + "Could not add this alias because it would cause some sequences to be replaced multiple times", usecolor = False)
return True
-
+ msg(sender, colorify("&7Alias: ") + args[0] + colorify("&7 -> " + args[1] + colorify("&7 was succesfully created!")), usecolor=sender.hasPermission("essentials.chat.color"))
+ return True
+
+
+def radd(sender, args):
+ plugin_header(sender, "Alias")
+ args = args[0:2] + [" ".join(args[2:len(args)-1])] + [args[len(args)-1]]
+ if is_player(sender):
+ sender_name = colorify(sender.getDisplayName())
else:
+ sender_name = colorify("&6Console")
+ target = server.getPlayer(args[0])
+ if target == None:
+ msg(sender, "&cThat player is not online")
+ return True
+ uuid = uid(target)
+ if args[3].lower() == "false":
+ plugin_header(target, "Alias")
+ msg(target, "&cPlayer " + sender_name + " &cis creating an alias for you!")
+ elif args[3].lower() != "true":
+ args[2] += " " + args[3]
+ if (args[1] not in data[uuid]) and is_alias_limit_reached(target, sender, args[3].lower() == "false"):
+ return True
+ if len(args) == 3:
+ args += ["true"]
+ if not add_alias_data(uuid, str(args[1]), str(args[2])):
+ message = colorify("&c") + "Could not add this alias because it would cause some sequences to be replaced multiple times"
+ msg(sender, message)
+ if args[3].lower() == "false":
+ msg(target, message)
+ return True
+ msg(sender, colorify("&7Alias: ") + args[1] + colorify("&7 -> " + args[2] + colorify("&7 was succesfully created!")), usecolor=target.hasPermission("essentials.chat.color"))
+ if args[3].lower() == "false":
+ msg(target, colorify("&7Alias: ") + args[1] + colorify("&7 -> " + args[2] + colorify("&7 was succesfully created!")), usecolor=target.hasPermission("essentials.chat.color"))
+ return True
+
+
+def is_alias_limit_reached(player, recipient, not_silent = False):
+ if player.hasPermission(permission_ALL):
return False
+ alias_limit = int(get_permission_content(player, permission_AMOUNT))
+ if len(data[uid(player)]) >= alias_limit:
+ message = ("&cYour limit of %d has been reached" if player is recipient else "&cThe limit of %d has been reached for that player") % alias_limit
+ msg(recipient, message)
+ if not_silent:
+ msg(player, message)
+ return True
+ return False
-@hook.event("player.AsyncPlayerChatEvent", "high")
-def on_player_chat(event):
- playerid = str(event.getPlayer().getUniqueId())
- data = safe_open_json()
+def add_alias_data(puuid, aliased, new_alias):
+ prior = data[puuid]
+
+ # prevent 2 -> 3 if there is 1 -> 2
+ if aliased not in prior:
+ for alias in prior.values():
+ if aliased in alias:
+ return False
+
+ # prevent 1 -> 2 if there is 2 -> 3
+ for sequence in prior:
+ if sequence in new_alias:
+ return False
+
+ prior[aliased] = new_alias
+ save_data(puuid)
+ return True
+
+
+def remove(sender, args):
+ plugin_header(sender, "Alias")
+ try:
+ msg(sender, colorify("&7Successfully removed alias ") + args[0] + colorify(" &7-> ") + data[uid(sender)].pop(args[0]) + colorify("&7!"), usecolor=sender.hasPermission("essentials.chat.color"))
+ save_data(uid(sender))
+ except:
+ msg(sender, colorify("&cCould not remove alias ") + args[0] + colorify(", it does not exist."), usecolor=sender.hasPermission("essentials.chat.color"))
+ return True
+
+
+def rremove(sender, args):
+ plugin_header(sender, "Alias")
+ target = get_player(args[0])
+ if is_player(sender):
+ sender_name = colorify(sender.getDisplayName())
+ else:
+ sender_name = colorify("&6Console")
+ if args[2].lower() == "false":
+ plugin_header(target, "Alias")
+ msg(target, "&cPlayer " + sender_name + " &cis removing an alias for you!")
+ try:
+ alias = data[uid(target)].pop(args[1])
+ msg(sender, colorify("&7Successfully removed alias ") + args[1] + colorify(" &7-> ") + alias + colorify("&7!"), usecolor=sender.hasPermission("essentials.chat.color"))
+ if args[2].lower() == "false":
+ msg(target, colorify("&7Successfully removed alias ") + args[1] + colorify(" &7-> ") + alias + colorify("&7!"), usecolor=sender.hasPermission("essentials.chat.color"))
+ save_data(uid(target))
+ except:
+ msg(sender, colorify("&cCould not remove alias ") + args[1] + colorify(", it does not exist."), usecolor=sender.hasPermission("essentials.chat.color"))
+ if args[2].lower() == "false":
+ msg(target, colorify("&cCould not remove alias ") + args[1] + colorify(", it does not exist."), usecolor=sender.hasPermission("essentials.chat.color"))
+ return True
+
+
+def list_alias(sender, args):
+ plugin_header(sender, "Alias")
+ msg(sender, "&7You have a total of " + str(len(data[uid(sender)])) + " aliases:")
+ for word, alias in data[str(uid(sender))].items():
+ msg(sender, colorify("&7") + word + colorify("&7 -> ") + alias, usecolor=sender.hasPermission("essentials.chat.color"))
+ return True
+
+
+def rlist_alias(sender, args):
+ plugin_header(sender, "Alias")
+ target = get_player(args[0])
+ if is_player(sender):
+ sender_name = colorify(sender.getDisplayName())
+ else:
+ sender_name = colorify("&6Console")
+ if len(args) == 1:
+ args += ["true"]
+ msg(sender, "Player " + args[0] + " has following aliases (" + str(len(data[uid(target)])) + " in total):")
+ if args[1].lower() == "false":
+ plugin_header(target, "Alias")
+ msg(target, "&cPlayer " + sender_name + " &cis listing your aliases")
+ for word, alias in data[str(uid(target))].items():
+ msg(sender, colorify("&7") + word + colorify("&7 -> ") + alias, usecolor=target.hasPermission("essentials.chat.color"))
+ return True
- if event.isCancelled():
- return
+def remote(sender, args):
try:
- crashtest = data[playerid].items()
- except KeyError:
- return
+ return remotes[args[1].lower()](sender, [args[0]] + args[2:])
+ except:
+ return subcommands["help"](sender, ["2"])
- for alias, value in data[playerid].items():
- event.setMessage(event.getMessage().replace(alias, value))
+
+def load_data(uuid):
+ if use_mysql:
+ try:
+ t = threading.Thread(target=load_data_thread, args=(uuid,))
+ t.daemon = True
+ t.start()
+ except:
+ error(trace())
+ else:
+ data[uuid] = safe_open_json(uuid)
+
+def load_data_thread(uuid):
+ conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
+ curs = conn.cursor()
+ curs.execute("SELECT `alias` FROM `chatalias` WHERE `uuid` = ?;", (uuid, ))
+ results = curs.fetchall()
+ if len(results) == 0:
+ value = dict(global_aliases)
+ curs.execute("INSERT INTO `chatalias` VALUES (?,?);", (uuid, json_dumps(results), ))
+ conn.commit()
+ else:
+ value = json_loads(results[0][0])
+ curs.close()
+ conn.close()
+ data[uuid] = value
+
+
+def save_data(uuid):
+ if use_mysql:
+ try:
+ t = threading.Thread(target=save_data_thread, args=(uuid,))
+ t.daemon = True
+ t.start()
+ except:
+ error(trace())
+ else:
+ save_json_file("aliases/" + uuid, data[uuid])
+
+def save_data_thread(uuid):
+ conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
+ curs = conn.cursor()
+ try:
+ curs.execute("UPDATE `chatalias` SET `alias` = ? WHERE `uuid` = ?;", (json_dumps(data[uuid]), uuid, ))
+ except:
+ error(trace())
+ conn.commit()
+ curs.close()
+ conn.close()
+
+
+# Subcommands:
+subcommands = {
+ "help": help,
+ "?": help,
+ "add": add,
+ "remove": remove,
+ "del": remove,
+ "delete": remove,
+ "player": remote,
+ "remote": remote,
+ "list": list_alias
+}
+
+remotes = {
+ "add": radd,
+ "remove": rremove,
+ "del": rremove,
+ "delete": rremove,
+ "list": rlist_alias,
+}
+
+# OnModuleLoad
+
+enabled = helpers_version in helpers_versions
+if not enabled:
+ error_msg = colorify("&6Incompatible versions detected (&chelpers.py&6)")
+for player in server.getOnlinePlayers():
+ if enabled:
+ t = threading.Thread(target=load_data, args=(uid(player), ))
+ t.daemon = True
+ t.start()
+ else:
+ if player.hasPermission(permission_FINFO):
+ disabled_fallback(player)
diff --git a/chatgroups.py b/chatgroups.py
index 326b8d3..be29e53 100644
--- a/chatgroups.py
+++ b/chatgroups.py
@@ -21,6 +21,8 @@ def on_chatgroup_command(sender, command, label, args):
if len(args) == 1 and args[0] == "leave":
if sender_id in groups.keys():
groupchat(sender, "left the group", True)
+ if sender in cg_toggle_list:
+ cg_toggle_list.remove(p)
group = groups[sender_id]
del(groups[sender_id])
save_groups()
@@ -43,11 +45,18 @@ def on_chatgroup_command(sender, command, label, args):
msg(sender, "&aUse chat like '&e%s<message>' to send messages to this group." % get_key(sender_id))
elif len(args) == 1 and args[0] == "key":
msg(sender, "&aYour chatgroup key is currently: '&c%s&a'" % get_key(sender_id))
+ elif len(args) == 1 and args[0] == "tpahere":
+ if sender_id in groups.keys():
+ do_for_chatgroup(groups[sender_id], send_tpa_request, sender)
+ msg(sender, "&aSent a tpahere request to all users in your chatgroup")
+ else:
+ msg(sender, "&cYou have to be in a chatgroup to do that")
else:
msg(sender, "&e/chatgroup join <name>")
msg(sender, "&e/chatgroup leave")
msg(sender, "&e/chatgroup info")
msg(sender, "&e/chatgroup key")
+ msg(sender, "&e/chatgroup tpahere")
@hook.command("cgt")
@@ -72,11 +81,19 @@ def groupchat(sender, message, ann = False):
mesg = "&8[&bCG&8] &e&o%s&e&o %s" % (name, message)
else:
mesg = "&8[&bCG&8] &f%s&f: &6%s" % (name, message)
+ mesg = colorify(mesg)
+
info("[ChatGroups] %s (%s): %s" % (sender.getDisplayName(), group, message))
- for receiver in server.getOnlinePlayers():
- groups.get(uid(receiver)) == group and msg(receiver, mesg)
+ do_for_chatgroup(group, msg, mesg, usecolor = False)
+def do_for_chatgroup(group, func, *args, **kwargs):
+ for receiver in server.getOnlinePlayers():
+ if groups.get(uid(receiver)) == group:
+ func(receiver, *args, **kwargs)
+def send_tpa_request(receiver, sender):
+ if not receiver == sender:
+ runas(sender, "/tpahere " + receiver.getName())
def save_groups():
save_json_file("chatgroups", groups)
@@ -115,5 +132,6 @@ def chatgroupkey_command(sender, command, label, args):
save_keys()
return "&aYour chatgroup key was set to: '&c%s&a'" % key
+
def save_keys():
save_json_file("chatgroup_keys", cg_keys)
diff --git a/damnspam.py b/damnspam.py
index 6a4c2b3..e9f9b84 100644
--- a/damnspam.py
+++ b/damnspam.py
@@ -36,9 +36,9 @@ def on_dammnspam_command(sender, command, label, args):
msg(sender, "&c/damnspam <seconds after off> <seconds after on> &e(Levers only)")
return True
#Gittestlol
- if not is_creative(sender):
- msg(sender, "&cYou can only do this in Creative mode.")
- return True
+ if not is_creative(sender):
+ msg(sender, "&cYou can only do this in Creative mode.")
+ return True
# /damnspam <secs>
if len(args) == 1:
@@ -47,8 +47,6 @@ def on_dammnspam_command(sender, command, label, args):
timeout_on = round(float(timeout_on), 2)
timeout_off = timeout_on
if 60 >= timeout_on <= -2 or timeout_on == 0:
- timeout_on = False
- if timeout_on == False:
msg(sender, "&cThe timeout must be within 0-60 or -1.")
return True
except ValueError:
diff --git a/friends.py b/friends.py
index 870560e..130954a 100644
--- a/friends.py
+++ b/friends.py
@@ -5,6 +5,10 @@ friends = open_json_file("friends", {}) # {Player_UUID:[List_of_friend
friend_join_sound = "random.orb"
+def is_friend_of(player, other):
+ lst = friends.get(uid(player))
+ return lst is not None and uid(other) in lst
+
@hook.event("player.PlayerJoinEvent", "high") # creates sound and sends a bold message on friend join
def fjm(event): # friend join message
diff --git a/helpers.py b/helpers.py
index 898dea7..d6e46bd 100644..100755
--- a/helpers.py
+++ b/helpers.py
@@ -11,8 +11,6 @@ import org.bukkit.block as bblock
import org.bukkit.event.entity as entity
import org.bukkit.command.ConsoleCommandSender
from org.bukkit.entity import *
-from player import get_py_player
-from player import py_players
#Imports for async query
from secrets import *
@@ -22,7 +20,7 @@ import threading
from traceback import format_exc as trace
-
+helpers_version = "2.0.0"
shared = {} # this dict can be used to share stuff across modules
server = bukkit.Bukkit.getServer()
@@ -87,7 +85,7 @@ def colorify(text):
"""
replace &-codes with real color codes
"""
- return sub("&" + u"\u00A7", "&", "%s" % sub("&(?=[?\\da-fk-or])", u"\u00A7", "%s" % text))
+ return sub("&(?=[?\\da-fk-or])", u"\u00A7", "%s" % text)
def stripcolors(text):
@@ -254,24 +252,12 @@ def save_json_file(filename, obj):
error("Failed to write to %s: %s" % (filename, e))
-def toggle(player, ls, name = "Toggle", add = None):
- """
- Toggles presence of a player's UUID in a list
- If add is given, True explicitely adds it whereas False removes it
- """
- pid = uid(player)
- if pid in ls or add == False:
- ls.remove(pid)
- msg(player, "&a%s turned off!" % name)
- elif add != False:
- ls.append(pid)
- msg(player, "&a%s turned on!" % name)
-
def send_JSON_message(playername, message):
bukkit.Bukkit.getServer().dispatchCommand(bukkit.Bukkit.getServer().getConsoleSender(), "tellraw " + playername + " " + message)
-def isIP(tocheck):
+# Allows to check if a String is a valid IPv4 or not. Accepts any string, returns true if the String is a valid IPv4
+def is_ip(tocheck):
subsets = ["","","",""]
i = 0
for j in range(0,len(tocheck)):
@@ -289,3 +275,29 @@ def isIP(tocheck):
if not ((int(subsets[j]) >= 0) & (int(subsets[j]) <= 255)):
return False
return True
+
+
+# Allows the use of e.g. numeric permission nodes like "permission.amount.5" and similar.
+# To get the data fetch the player and the start of the permission node, looking like "permission.amount."
+def get_permission_content(player, permnode):
+ perms = player.getEffectivePermissions()
+ for perm in perms:
+ if str(perm.getPermission()).startswith(permnode):
+ return str(perm.getPermission())[len(permnode):]
+
+
+def array_to_list(array):
+ return_list = []
+ for a in array:
+ return_list.append(a)
+ return return_list
+
+
+#debug wrapper
+def debug(func):
+ def wrap(*args, **kwargs):
+ try:
+ func(*args, **kwargs)
+ except:
+ print(trace())
+ return wrap
diff --git a/imbusy.py b/imbusy.py
index 64fa30b..ec6c57b 100644
--- a/imbusy.py
+++ b/imbusy.py
@@ -1,107 +1,303 @@
-# I'M BUSY! Plugin by Curs3d #
-##############################
-# Concept by CookieManors :D #
-# http://bit.ly/1GnNPW8 #
-##############################
-# This plugin permits users to
-# send a command that renders
-# them "busy", not letting them
-# to get tpa requests or direct
-# messages, except from console.
-# On restart, all busy data will
-# be cleared.
+"""
+This plugin permits users to
+send a command that renders
+them "busy", not letting them
+to get tpa requests or direct
+messages, except from console.
+On restart, all busy data will
+be cleared.
+"""
from helpers import *
-from basecommands import simplecommand
-from traceback import format_exc as trace
-busy_players = []
+from friends import is_friend_of
+import org.bukkit.command.Command as Command
+imbusy_version = "v1.1.0"
-def unclear():
- msg(sender, "Umm, what? Sorry, directions unlclear, got head stuck in washing machine")
+base_permission = "utils.imbusy" # for /busy status
+use_permission = "utils.imbusy.use" # for being busy
+override_permission = "utils.imbusy.override" # for being able to bother busy people
-@hook.command("busy",
- aliases = ["focus"],
- usage = "/<command> <on|off|status>",
- description = "Sets busy mode on, you cannot recieve tpas and MSGs"
+busy_players = {} # name : false/true where false is normal busy and true is super busy
+
+
+@hook.command("imbusy",
+ aliases = ["busy"],
+ usage = "/<command> [on, off, status/check]",
+ description = "Offers control over your busy status"
)
def on_busy_command(sender, cmd, label, args):
-
if not is_player(sender):
- msg(sender, "Sorry, Console cannot be busy")
- return True
+ msg(sender, "&7Sorry, Console cannot be busy")
+ return True
+
+ plugin_header(recipient = sender, name = "I'M BUSY!")
- if not sender.hasPermission("utils.busy.allowed"):
- plugin_header(recipient = sender, name = "I'M BUSY!")
+ if not sender.hasPermission(base_permission):
noperm(sender)
return True
if len(args) == 0:
- plugin_header(recipient = sender, name = "I'M BUSY!")
- msg(sender, "This plugin allows being busy, and when turned on you will not recieve any direct messages or tpa requests.")
- msg(sender, "\nCommands:")
- msg(sender, "/busy on: turns on busy mode")
- msg(sender, "/busy off: turns off busy mode")
- msg(sender, "/busy status [player]: shows your or [player]'s current busy status.")
+ return toggle(sender)
+
+ arg0 = args[0].lower()
+ if arg0 == "on":
+ return on(sender)
+ if arg0 == "off":
+ return off(sender)
+ if arg0 in ("status", "check"):
+ return status(sender, args[1:])
+ if arg0 == "super":
+ return super_cmd(sender)
+ return help(sender)
+
+
+def toggle(sender):
+ if not sender.hasPermission(use_permission):
+ noperm(sender)
return True
+ sender_name = sender.getName()
+ if sender_name in busy_players:
+ del busy_players[sender_name]
+ broadcast(None, sender.getDisplayName() + " &7is no longer busy...")
+ else:
+ busy_players.append(sender_name)
+ broadcast(None, sender.getDisplayName() + " &7is now busy...")
+ return True
- elif len(args) == 1:
- if args[0] == "on":
- if sender.getName() in busy_players:
- plugin_header(recipient = sender, name = "I'M BUSY!")
- msg(sender, "You cannot be even more focused than this without being a jedi!")
- return True
- busy_players.append(sender.getName())
- plugin_header(recipient = sender, name = "I'M BUSY!")
- broadcast(None, "%s is now SUPER busy! Don't even TRY bothering them, it will not work!" % sender.getName())
- return True
-
- elif args[0] == "off":
- plugin_header(recipient = sender, name = "I'M BUSY!")
- try:
- busy_players.remove(sender.getName())
- msg(sender, "Master has sent /busy command, %s is freeee!" % sender.getName())
- return True
- except ValueError:
- msg(sender, "You are not busy! You cannot be even less busy! Are you perhaps bored?")
- return True
-
- elif args[0] == "status":
- plugin_header(recipient = sender, name = "I'M BUSY!")
- if sender.getName() in busy_players:
- msg(sender, "You are super-duper busy and concentrated right now. Think, think, think!")
- return True
- else:
- msg(sender, "You are completely unable to focus right now.")
- return True
- else:
- plugin_header(recipient = sender, name = "I'M BUSY!")
- unclear()
- return False
+def help(sender):
+ msg(sender, "Let's you put yourself in busy status, preventing pms and tpa requests from other players")
+ msg(sender, "\n&eCommands:")
+ msg(sender, "&e/busy &7- Toggles busy status")
+ msg(sender, "&e/busy on &7- Turns on busy status")
+ msg(sender, "&e/busy off &7- Turns off busy status")
+ msg(sender, "&e/busy status [player] &7- shows your or [player]'s current busy status")
+ msg(sender, "&e/busy super &7- sets your status to SUPER busy such that even friends can not bother you")
+ return True
+
+
+def on(sender):
+ if not sender.hasPermission(use_permission):
+ noperm(sender)
+ return True
+ sender_name = sender.getName()
+ if busy_players.get(sender_name) is False: # can be None, False or True
+ msg(sender, "&7You are already busy!")
+ else:
+ busy_players[sender_name] = False # busy but not super busy
+ broadcast(None, sender.getDisplayName() + " &7is now busy...")
+ return True
- elif len(args) == 2 and args[0] == "status":
- plugin_header(recipient = sender, name = "I'M BUSY!")
- if args[1] in busy_players:
- msg(sender, "Yes, %s is busy. Shhh..." % args[1])
- return True
+
+def off(sender):
+ if not sender.hasPermission(use_permission):
+ noperm(sender)
+ return True
+ sender_name = sender.getName()
+ if sender_name not in busy_players:
+ msg(sender, "&7You are not busy! You cannot be even less busy! Are you perhaps bored?")
+ return True
+ del busy_players[sender_name]
+ broadcast(None, sender.getDisplayName() + " &7is no longer busy...")
+ return True
+
+
+def status(sender, args):
+ if not sender.hasPermission(base_permission):
+ noperm(sender)
+ return True
+ if len(args) == 0:
+ if sender.getName() in busy_players:
+ if busy_players[sender_name] is False:
+ msg(sender, "&7You are currently busy.")
+ else:
+ msg(sender, "&7You are currently SUPER busy.")
else:
- msg(sender, "No, you're good. Feel free to chat with %s!" % args[1])
- return True
+ msg(sender, "&7You are currently not busy.")
+ else:
+ target = server.getPlayer(args[0])
+ if target is None:
+ msg(sender, "&7That player is not online")
+ elif target.getName() in busy_players:
+ if busy_players[target.getName()] is False:
+ msg(sender, "&7Player %s &7is currently busy." % target.getDisplayName())
+ else:
+ msg(sender, "&7Player %s &7is currently SUPER busy." % target.getDisplayName())
+ else:
+ msg(sender, "&7Player %s &7is currently not busy." % target.getDisplayName())
+ return True
+
+def super_cmd(sender):
+ if not sender.hasPermission(use_permission):
+ noperm(sender)
+ return True
+ sender_name = sender.getName()
+ if busy_players.get(sender_name) is True:
+ msg(sender, "&7You are already SUPER busy!")
else:
- plugin_header(recipient = sender, name = "I'M BUSY!")
- unclear()
+ busy_players[sender_name] = True # SUPER busy
+ broadcast(None, sender.getDisplayName() + " &7is now SUPER busy...")
+ return True
+
+
+@hook.event("player.PlayerQuitEvent", "lowest")
+def on_player_leave(event):
+ player_name = event.getPlayer().getName()
+ if player_name in busy_players:
+ del busy_players[player_name]
+
+
+#---- Dicode for catching any bothering of busy people ----
+
+
+reply_targets = {}
+
+
+def can_send(sender, target):
+ if not target.getName() in busy_players:
+ return True
+ if target is sender or sender.hasPermission(override_permission):
+ return True
+ return busy_players[target.getName()] is False and is_friend_of(target, sender)
+
+
+def whisper(sender, target_name):
+ target = server.getPlayer(target_name)
+
+ if target is not None:
+ if not can_send(sender, target):
+ msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
+ return False
+
+ reply_targets[sender.getName()] = target.getName()
+
+ # allow the target to reply regardless of sender being busy
+ if target.getName() in reply_targets:
+ del reply_targets[target.getName()]
+ return True
+
+
+def reply(sender):
+ if sender.getName() in reply_targets:
+ target = server.getPlayer(reply_targets[sender.getName()])
+ if target is not None:
+ if not can_send(sender, target):
+ msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
+ return False
+
+ # allow the target to reply regardless of sender being busy
+ if target.getName() in reply_targets:
+ del reply_targets[target.getName()]
+ return True
+
+
+class CommandWrapper(Command):
+
+ def __init__(self, wrapped, checker):
+ Command.__init__(self, wrapped.getName())
+ self.setDescription(wrapped.getDescription())
+ self.setPermission(wrapped.getPermission())
+ self.setUsage(wrapped.getUsage())
+ self.setAliases(wrapped.getAliases())
+ self.wrapped = wrapped
+ self.checker = checker
+
+ def execute(self, sender, label, args):
+ try:
+ if not is_player(sender) or self.checker(sender, args):
+ return self.wrapped.execute(sender, label, args)
+ except:
+ error(trace())
+ return True
+
+ def tabComplete(self, sender, alias, args):
+ return self.wrapped.tabComplete(sender, alias, args)
+
+
+def msg_command_checker(sender, args):
+ return len(args) <= 1 or whisper(sender, args[0])
+
+def reply_command_checker(sender, args):
+ return len(args) == 0 or reply(sender)
+
+def tpa_command_checker(sender, args):
+ if len(args) == 0:
+ return True
+ target = server.getPlayer(args[0])
+ if target is not None and not can_send(sender, target):
+ msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
+ return False
+ return True
+
+def tpahere_command_checker(sender, args):
+ return tpa_command_checker(sender, args)
+
+def mail_command_checker(sender, args):
+ info("Mail command executed")
+ if len(args) < 3 or args[0].lower() != "send":
+ return True
+ target = server.getPlayer(args[1])
+ if target is not None and not can_send(sender, target):
+ msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
+ return True
@hook.event("player.PlayerCommandPreprocessEvent", "monitor")
-def on_cmd_preprocess_event(event):
+def on_player_command_preprocess(event):
message = event.getMessage().split(" ")
- if message[0] == "/msg" or message[0] == "/w" or message[0] == "/m" or \
- message[0] == "/tell" or message[0] == "/tpa" or message[0] == "/tpahere":
- if message[1] in busy_players:
- plugin_header(recipient = event.getPlayer(), name = "I'M BUSY!")
- msg(event.getPlayer(), "We are sorry, but %s is currently busy. Please try again later." % message[1])
- event.setCancelled(True)
+ if len(message) > 1 and message[0].lower() in ("/tell", "/minecraft:tell") and not whisper(event.getPlayer(), message[1]):
+ event.setCancelled(True)
+
+
+def replace_ess_commands():
+
+ try:
+ map_field = server.getPluginManager().getClass().getDeclaredField("commandMap")
+ map_field.setAccessible(True)
+ command_map = map_field.get(server.getPluginManager())
+
+ commands_field = command_map.getClass().getDeclaredField("knownCommands")
+ commands_field.setAccessible(True)
+ map = commands_field.get(command_map)
+
+ ess_msg_cmd = map.get("essentials:msg")
+ ess_reply_cmd = map.get("essentials:reply")
+ ess_tpa_cmd = map.get("essentials:tpa")
+ ess_tpahere_cmd = map.get("essentials:tpahere")
+ ess_mail_cmd = map.get("essentials:mail")
+
+ msg_cmd_wrapper = CommandWrapper(ess_msg_cmd, msg_command_checker)
+ reply_cmd_wrapper = CommandWrapper(ess_reply_cmd, reply_command_checker)
+ tpa_cmd_wrapper = CommandWrapper(ess_tpa_cmd, tpa_command_checker)
+ tpahere_cmd_wrapper = CommandWrapper(ess_tpahere_cmd, tpahere_command_checker)
+ mail_cmd_wrapper = CommandWrapper(ess_mail_cmd, mail_command_checker)
+
+ iterator = map.entrySet().iterator()
+ wrapped_commands = []
+ while iterator.hasNext():
+ entry = iterator.next()
+ value = entry.getValue()
+ changed = True
+ if value is ess_msg_cmd:
+ entry.setValue(msg_cmd_wrapper)
+ elif value is ess_reply_cmd:
+ entry.setValue(reply_cmd_wrapper)
+ elif value is ess_tpa_cmd:
+ entry.setValue(tpa_cmd_wrapper)
+ elif value is ess_tpahere_cmd:
+ entry.setValue(tpahere_cmd_wrapper)
+ elif value is ess_mail_cmd:
+ entry.setValue(mail_cmd_wrapper)
+ else:
+ changed = False
+ if changed:
+ wrapped_commands.append(entry.getKey())
+ info("[imbusy] wrapped commands: /" + ", /".join(wrapped_commands))
+
+ except:
+ error("[Imbusy] Failed to wrap essentials commands")
+ error(trace())
diff --git a/iptracker.py b/iptracker.py
index 8bbd053..969a822 100644..100755
--- a/iptracker.py
+++ b/iptracker.py
@@ -1,107 +1,108 @@
-import mysqlhack
-import org.bukkit as bukkit
-import json
-from java.util import UUID as UUID
-from helpers import *
-from org.bukkit import *
-from traceback import format_exc as trace
-from iptracker_secrets import *
-
-
-iptrack_permission = "utils.iptrack"
-
-
-@hook.event("player.PlayerJoinEvent", "low")
-def on_player_join(event):
- t = threading.Thread(target=on_player_join_thread, args=(event, ))
- t.daemon = True
- t.start()
-
-def on_player_join_thread(event):
- player = event.getPlayer()
- ip = player.getAddress().getHostString()
- uuid = uid(player)
- conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
- curs = conn.cursor()
- curs.execute("SELECT ips FROM uuid2ips WHERE uuid = ?", (uuid, ))
- results = curs.fetchall()
- if len(results) == 0:
- ips = []
- else:
- ips = json.loads(results[0][0])
- curs.execute("SELECT uuids FROM ip2uuids WHERE ip = ?", (ip, ))
- results = curs.fetchall()
- if len(results) == 0:
- uuids = []
- else:
- uuids = json.loads(results[0][0])
- new_ip_entry = (len(ips) == 0)
- new_uuid_entry = (len(uuids) == 0)
- if ip not in ips:
- ips.append(ip)
- if new_ip_entry:
- curs.execute("INSERT INTO uuid2ips VALUES (?,?)", (uuid, json.dumps(ips), ))
- else:
- curs.execute("UPDATE uuid2ips SET ips = ? WHERE uuid = ?", (uuid, json.dumps(ips), ))
- if uuid not in uuids:
- uuids.append(uuid)
- if new_uuid_entry:
- curs.execute("INSERT INTO ip2uuids VALUES (?,?)", (ip, json.dumps(uuids), ))
- else:
- curs.execute("UPDATE ip2uuids SET uuids = ? WHERE uuid = ?", (ip, json.dumps(uuids), ))
- conn.commit()
- curs.close()
- conn.close()
-
-
-@hook.command("getinfo")
-def on_getinfo_command(sender, args):
- t = threading.Thread(target=on_player_join_thread, args=(sender, args))
- t.daemon = True
- t.start()
-
-def on_getinfo_command_thread(sender, args):
- if(sender.hasPermission(iptrack_permission)):
- if not checkargs(sender, args, 1, 1):
- return False
- else:
- if isIP(args[0]):
- conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
- curs = conn.cursor()
- curs.execute("SELECT uuids FROM ip2uuids WHERE ip = ?", (args[0], ))
- results = curs.fetchall()
- curs.close()
- conn.close()
- if len(results) == 0:
- msg(sender, "IP " + args[0] + " is not registered in the database, maybe you got a number wrong?")
- else:
- uuids = json.loads(results[0][0])
- msg(sender, "IP " + args[0] + " was seen with " + str(len(uuids)) + " different Accounts:")
- for i in range(0, len(uuids)):
- p=Bukkit.getOfflinePlayer(UUID.fromString(uuids[i]))
- if is_player(sender):
- send_JSON_message(sender.getName(), '["",{"text":"' + p.getName() + ' - (uuid: ' + uuids[i] + '","color":"gold","clickEvent":{"action":"run_command","value":"/getinfo ' + p.getName() + '"},"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"To search for ' + p.getName() + ' in the database, simply click the name!","color":"gold"}]}}}]')
- else:
- msg(sender,p.getName() + " - (uuid: " + uuids[i] + ")")
- else:
- target = Bukkit.getOfflinePlayer(args[0])
- uuid = target.getUniqueId()
- conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
- curs = conn.cursor()
- curs.execute("SELECT ips FROM uuid2ips WHERE uuid = ?", (uuid.toString(), ))
- results = curs.fetchall()
- curs.close()
- conn.close()
- if len(results) == 0:
- msg(sender, "Player " + args[0] + " is not registered in the database, maybe you misspelled the name?")
- else:
- ips = json.loads(results[0][0])
- msg(sender, "Player " + args[0] + " was seen with " + str(len(ips)) + " different IPs:")
- for i in range(0, len(ips)):
- if is_player(sender):
- send_JSON_message(sender.getName(), '["",{"text":"' + ips[i] + '","color":"gold","clickEvent":{"action":"run_command","value":"/getinfo ' + ips[i] + '"},"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"To search for the IP ' + ips[i] + ' in the database, simply click the IP!","color":"gold"}]}}}]')
- else:
- msg(sender,ips[i])
- else:
- noperm(sender)
- return True
+import mysqlhack
+import org.bukkit as bukkit
+import json
+from java.util import UUID as UUID
+from helpers import *
+from org.bukkit import *
+from traceback import format_exc as trace
+from iptracker_secrets import *
+
+
+iptrack_permission = "utils.iptrack"
+iptrack_version = "1.1.0"
+
+
+@hook.event("player.PlayerJoinEvent", "low")
+def on_player_join(event):
+ t = threading.Thread(target=on_player_join_thread, args=(event, ))
+ t.daemon = True
+ t.start()
+
+def on_player_join_thread(event):
+ player = event.getPlayer()
+ ip = player.getAddress().getHostString()
+ uuid = uid(player)
+ conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
+ curs = conn.cursor()
+ curs.execute("SELECT ips FROM uuid2ips WHERE uuid = ?", (uuid, ))
+ results = curs.fetchall()
+ if len(results) == 0:
+ ips = []
+ else:
+ ips = json.loads(results[0][0])
+ curs.execute("SELECT uuids FROM ip2uuids WHERE ip = ?", (ip, ))
+ results = curs.fetchall()
+ if len(results) == 0:
+ uuids = []
+ else:
+ uuids = json.loads(results[0][0])
+ new_ip_entry = (len(ips) == 0)
+ new_uuid_entry = (len(uuids) == 0)
+ if ip not in ips:
+ ips.append(ip)
+ if new_ip_entry:
+ curs.execute("INSERT INTO uuid2ips VALUES (?,?)", (uuid, json.dumps(ips), ))
+ else:
+ curs.execute("UPDATE uuid2ips SET ips = ? WHERE uuid = ?", (json.dumps(ips), uuid, ))
+ if uuid not in uuids:
+ uuids.append(uuid)
+ if new_uuid_entry:
+ curs.execute("INSERT INTO ip2uuids VALUES (?,?)", (ip, json.dumps(uuids), ))
+ else:
+ curs.execute("UPDATE ip2uuids SET uuids = ? WHERE ip = ?", (json.dumps(uuids), ip, ))
+ conn.commit()
+ curs.close()
+ conn.close()
+
+
+@hook.command("getinfo")
+def on_getinfo_command(sender, args):
+ t = threading.Thread(target=on_getinfo_command_thread, args=(sender, args))
+ t.daemon = True
+ t.start()
+
+def on_getinfo_command_thread(sender, args):
+ if(sender.hasPermission(iptrack_permission)):
+ if not checkargs(sender, args, 1, 1):
+ return False
+ else:
+ if is_ip(args[0]):
+ conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
+ curs = conn.cursor()
+ curs.execute("SELECT uuids FROM ip2uuids WHERE ip = ?", (args[0], ))
+ results = curs.fetchall()
+ curs.close()
+ conn.close()
+ if len(results) == 0:
+ msg(sender, "IP " + args[0] + " is not registered in the database, maybe you got a number wrong?")
+ else:
+ uuids = json.loads(results[0][0])
+ msg(sender, "IP " + args[0] + " was seen with " + str(len(uuids)) + " different Accounts:")
+ for i in range(0, len(uuids)):
+ p=Bukkit.getOfflinePlayer(UUID.fromString(uuids[i]))
+ if is_player(sender):
+ send_JSON_message(sender.getName(), '["",{"text":"' + p.getName() + ' - (uuid: ' + uuids[i] + '","color":"gold","clickEvent":{"action":"run_command","value":"/getinfo ' + p.getName() + '"},"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"To search for ' + p.getName() + ' in the database, simply click the name!","color":"gold"}]}}}]')
+ else:
+ msg(sender,p.getName() + " - (uuid: " + uuids[i] + ")")
+ else:
+ target = Bukkit.getOfflinePlayer(args[0])
+ uuid = target.getUniqueId()
+ conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
+ curs = conn.cursor()
+ curs.execute("SELECT ips FROM uuid2ips WHERE uuid = ?", (uuid.toString(), ))
+ results = curs.fetchall()
+ curs.close()
+ conn.close()
+ if len(results) == 0:
+ msg(sender, "Player " + args[0] + " is not registered in the database, maybe you misspelled the name?")
+ else:
+ ips = json.loads(results[0][0])
+ msg(sender, "Player " + args[0] + " was seen with " + str(len(ips)) + " different IPs:")
+ for i in range(0, len(ips)):
+ if is_player(sender):
+ send_JSON_message(sender.getName(), '["",{"text":"' + ips[i] + '","color":"gold","clickEvent":{"action":"run_command","value":"/getinfo ' + ips[i] + '"},"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"To search for the IP ' + ips[i] + ' in the database, simply click the IP!","color":"gold"}]}}}]')
+ else:
+ msg(sender,ips[i])
+ else:
+ noperm(sender)
+ return True
diff --git a/loginsecurity.py b/loginsecurity.py
index edf51e9..4fbb307 100644
--- a/loginsecurity.py
+++ b/loginsecurity.py
@@ -7,6 +7,7 @@ from login_secrets import * #Don't forget to make login_secrets aswell
import mysqlhack
from com.ziclix.python.sql import zxJDBC
from java.lang import Runnable
+from player import get_py_player, py_players
wait_time = 30 #seconds
admin_perm = "utils.loginsecurity.admin"
diff --git a/main.py b/main.py
index 4769bc5..fba0c5a 100644
--- a/main.py
+++ b/main.py
@@ -19,12 +19,17 @@ except:
@hook.enable
def on_enable():
+ if "blockplacemods" in shared["modules"]:
+ shared["modules"]["blockplacemods"].schedule_torch_breaker()
+ if "imbusy" in shared["modules"]:
+ shared["modules"]["imbusy"].replace_ess_commands()
info("RedstonerUtils enabled!")
@hook.disable
def on_disable():
- shared["modules"]["reports"].stop_reporting()
+ if "reports" in shared["modules"]:
+ shared["modules"]["reports"].stop_reporting()
info("RedstonerUtils disabled!")
@@ -44,6 +49,8 @@ shared["load_modules"] = [
"calc",
# Adds aliasing of chat words
"chatalias",
+ # For players to point friends
+ "friends",
# 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
@@ -89,7 +96,7 @@ shared["load_modules"] = [
# Servercontrol extension for telnet access to logs/AC
#"servercontrol",
# Script helper plugin
- "scriptutils",
+ "scriptutils",
# Per-player notes
"tag",
# vanish toggle module - temporary fix
@@ -98,8 +105,12 @@ shared["load_modules"] = [
"punishments",
# a simple replacement for the buggy essentials /vanish
"vanish",
- # ip-tracking utility
- "iptracker"
+ # ip-tracking utility - disabled as of instability
+ #"iptracker",
+ #server signs for everyone
+ "serversigns",
+ # Makes player's names colored, sorts tab list by rank
+ "nametags"
]
shared["modules"] = {}
for module in shared["load_modules"]:
diff --git a/misc.py b/misc.py
index c6da200..026650e 100644
--- a/misc.py
+++ b/misc.py
@@ -7,6 +7,7 @@ import thread
import org.bukkit.inventory.ItemStack as ItemStack
import org.bukkit.Bukkit as Bukkit
from basecommands import simplecommand, Validate
+import java.util.Arrays as Arrays
@@ -113,9 +114,20 @@ def rs_material_broken_by_flow(material):
length = len(parts)
return length > 1 and (parts[0] == "DIODE" or parts[1] in ("TORCH", "WIRE", "BUTTON", "HOOK") or (length == 3 and parts[1] == "COMPARATOR"))
+
+@hook.event("player.PlayerInteractEvent")
+def on_interact(event):
+ if (not event.isCancelled()
+ and str(event.getAction()) == "RIGHT_CLICK_BLOCK"
+ and str(event.getMaterial()) in ("REDSTONE_COMPARATOR_OFF", "REDSTONE_COMPARATOR_ON")
+ and not can_build(player, event.getClickedBlock())
+ ):
+ event.setCancelled(True)
+
+
sudo_blacklist = ["pyeval", "script_backup_begin", "script_backup_end", "script_backup_error", "script_backup_database_begin", "script_backup_database_dumps", "script_backup_database_end",
"script_backup_database_error", "script_backup_database_abort", "script_trim", "script_trim_result", "script_spigot_update", "script_disk_filled", "script_restart", "script_restart_abort",
-"script_stop", "script_stop_abort", "script_shutdown", "stop", "esudo", "essentials:sudo"]
+"script_stop", "script_stop_abort", "script_shutdown", "stop", "esudo", "essentials:sudo", "sudo", "essentials:esudo"]
@simplecommand("sudo",
usage = "<player> [cmd..]",
@@ -161,7 +173,8 @@ def on_pluginversions_command(sender, command, label, args):
"""
try:
plugin_header(sender, "Plugin versions")
- plugins = [pl.getDescription() for pl in list(ArrayList(java_array_to_list(server.getPluginManager().getPlugins())))]
+ raw_plugins = server.getPluginManager().getPlugins() # Plugin[]
+ plugins = [raw_plugins[i].getDescription() for i in range(len(raw_plugins))]
info(type(plugins[0]).__name__)
plugins.sort(key = lambda pl: pl.getDescription().getName())
msg(sender, "&3Listing all " + str(len(plugins)) + " plugins and their version:")
@@ -199,12 +212,12 @@ def eval_thread(sender, code):
msg(sender, ">>> %s: %s" % (eclass.__name__, e) + "\n ", False, "c")
thread.exit()
-pythoners = [
-"e452e012-2c82-456d-853b-3ac8e6b581f5", # Nemes
-"ae795aa8-6327-408e-92ab-25c8a59f3ba1", # jomo
-"305ccbd7-0589-403e-a45b-d791dcfdee7d", # PanFritz
-"51f2ad3c-6cc8-40ea-aa2b-f25970316921" # Dico
-]
+pythoners = (
+ "e452e012-2c82-456d-853b-3ac8e6b581f5", # Nemes
+ "ae795aa8-6327-408e-92ab-25c8a59f3ba1", # jomo
+ "d2693e91-93e1-4e3f-929f-f38e1ce8df03", # Pepich1851
+ "51f2ad3c-6cc8-40ea-aa2b-f25970316921" # Dico200
+)
@simplecommand("pyeval",
usage = "[code..]",
diff --git a/nametags.py b/nametags.py
new file mode 100755
index 0000000..4d86bbe
--- /dev/null
+++ b/nametags.py
@@ -0,0 +1,37 @@
+from helpers import *
+
+##############################################################
+# #
+# This module automatically puts people in the corresponding #
+# scoreboard team so that their name is colored properly and #
+# tab will be nicely sorted. #
+# #
+##############################################################
+
+ranks = ["visitor", "member", "builder", "trusted", "trainingmod", "mod", "admin"]
+# prefixes are used for sorting in the tab list
+prefixes = {"admin":"a", "mod":"b", "trainingmod":"c", "trusted":"d", "builder":"e", "member":"f","visitor":"g"}
+
+@hook.event("player.PlayerJoinEvent", "low")
+def on_player_join(event):
+ player = event.getPlayer()
+ team = get_team(player)
+ if team:
+ cmd = "scoreboard teams join %s %s" % (team, player.getName())
+ server.dispatchCommand(server.getConsoleSender(), cmd)
+
+def get_rank(player):
+ player_rank = None
+ for rank in ranks:
+ if not player.hasPermission("group.%s" % rank):
+ break
+ player_rank = rank
+ if not player_rank:
+ warn("Couldn't find rank for player %s" % player.getName())
+ return player_rank
+
+def get_team(player):
+ rank = get_rank(player)
+ if rank:
+ prefix = prefixes.get(rank)
+ return "_".join([prefix, rank]) \ No newline at end of file
diff --git a/player.py b/player.py
index 0f4a47f..b1a2ddd 100644
--- a/player.py
+++ b/player.py
@@ -25,5 +25,6 @@ def on_join(event):
@hook.event("player.PlayerQuitEvent","highest")
def on_leave(event):
- py_players.remove(get_py_player(event.getPlayer()))
-
+ player = get_py_player(event.getPlayer())
+ if player in py_players:
+ py_players.remove(player)
diff --git a/plugin.yml b/plugin.yml
index 4991e40..bdd5acb 100644
--- a/plugin.yml
+++ b/plugin.yml
@@ -2,4 +2,3 @@ name: RedstonerUtils
main: main.py
version: 3.1.0
author: redstone_sheep
-
diff --git a/pmtoggle.py b/pmtoggle.py
index e1bac06..19caf9e 100644
--- a/pmtoggle.py
+++ b/pmtoggle.py
@@ -5,7 +5,11 @@ from java.util.UUID import fromString as juuid
toggle_dict = {}
permission = "utils.pmtoggle"
-@hook.command("tm")
+@hook.command("pmtoggle",
+ aliases = ["tm", "mt", "tmsg", "msgt", "pmt", "tpm"],
+ usage = "/<command> [player]",
+ description = "Toggle automatic sending of messages"
+ )
def on_toggle_message_command(sender, command, label, args):
if not sender.hasPermission(permission) or not is_player(sender):
noperm(sender)
diff --git a/serversigns.py b/serversigns.py
index c7bc23c..d5a4829 100644
--- a/serversigns.py
+++ b/serversigns.py
@@ -3,219 +3,338 @@ 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
-
-
-cmd_use_perm = "utils.svs.cmd"
-msg_use_perm = "utils.svs.msg"
-
-signs = open_json_file("serversigns", {}) # {("world", x, y, z): ["owner_id", "msg1", "msg2"]}
-
-lines = {} #Accumulated messages so players can have longer messages: {"Dico200": "Message...........", ""}
-
-transparent_blocks_set = JSet([Material.AIR, Material.GLASS, Material.STAINED_GLASS]) #used in sender.getTargetBlock()
-
-@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)
+import org.bukkit.block.BlockFace as BlockFace
+
+commands_whitelist = (
+ "mail", "email", "memo",
+ "echo", "ping",
+ "cg join",
+ "cg info",
+ "chatgroup join",
+ "chatgroup info",
+ "i",
+ "item",
+ "p h", "plot home", "plot h", "p home", "plotme home", "plotme h",
+ "up",
+ "tppos",
+ "seen"
+)
+
+max_line_length = 256
+max_lines = 20
+
+def load_signs():
+ signs_obj = open_json_file("serversigns", [])
+ loaded = {}
+ for entry in signs_obj:
+ loaded[tuple(entry[:4])] = list(entry[4:])
+ return loaded
+
+def save_signs():
+ signs_obj = []
+ for key, value in signs.iteritems():
+ signs_obj.append(key + tuple(value))
+ save_json_file("serversigns", signs_obj)
+
+# {("world", x, y, z): ["owner_id", "msg1", "msg2"]}
+signs = load_signs()
+
+# Accumulated messages so players can have longer messages: {"Dico200": "Message...........", ""}
+lines = {}
+
+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", "rem", "del", "delete", "info", "lines",
+ "clear", "help", "switch", "reverse", "unclaim", "commands", "whitelist", "wl"),
+ 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|lines"
+ 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."
+ msg += "\n&b/svs commands|whitelist|wl"
+ msg += "\n&a- Shows a list of whitelisted commands"
+ return msg
+
+ if arg1 in ("commands", "whitelist", "wl"):
+ return signsMsg("Whitelisted commands: &3" + ", ".join(commands_whitelist), 'a')
+ #-------------------------------------------------------------------------------------------
+
+ 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 in ("info", "lines"):
+ 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":
+ Validate.isTrue(len(sign) - 1 <= max_lines, signsMsg("This sign already has the maximum amount of lines, you cannot add more"))
+
+ 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] = ""
+ Validate.isTrue(len(lines[key]) + len(line[:-2]) + 1 <= max_line_length, signsMsg("This line would be too long, so the given message was not added to the accumulated message"))
+ 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(len(line) <= max_line_length, signsMsg("This line would be too long, so it was not added to the sign. It is however still accumulated."))
+
+ if line[0] == "/":
+ cmd = line[1:].lower()
+ whitelisted = False
+ for wl_cmd in commands_whitelist:
+ if cmd[:len(wl_cmd)] == wl_cmd:
+ whitelisted = True
+ break
+ Validate.isTrue(whitelisted, signsMsg("That command is not whitelisted for use with serversigns"))
+
+ if key in lines:
+ del lines[key]
+
+ 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 in ("remove", "rem", "del", "delete"):
+ 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()
diff --git a/setup.sh b/setup.sh
index 336376f..e542e09 100755
--- a/setup.sh
+++ b/setup.sh
@@ -25,7 +25,7 @@ mkdir -v "build"
cd "build"
echo -e "\n> Downloading Spigot build tools"
-curl --progress-bar -Lo "buildtools.jar" "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
+curl --progress-bar -Lo "BuildTools.jar" "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
echo -e "\n> Building Spigot, this will take a while ..."
java -jar BuildTools.jar > /dev/null
@@ -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/signalstrength.py b/signalstrength.py
index 10a4933..d51f35a 100644
--- a/signalstrength.py
+++ b/signalstrength.py
@@ -109,9 +109,7 @@ def get_entire_container(container):
helpSubcmd = True,
senderLimit = 0)
def on_signalstrength_command(sender, command, label, args):
- if not sender.hasPermission("utils.ss"):
- noperm(sender)
- return None
+
if len(args) > 0 and args[0].lower() in ("default", "defaults", "setdefaults"):
strength, item_type, item_data = get_data(sender, args[1:])
diff --git a/synchronizeranks.py b/synchronizeranks.py
index 97439e0..4509185 100644
--- a/synchronizeranks.py
+++ b/synchronizeranks.py
@@ -3,6 +3,14 @@ from secrets import *
import mysqlhack
from com.ziclix.python.sql import zxJDBC
+"""
+WORK IN PROGRESS
+"""
+
+#-----------------------Config--------------------------
+
+config_file = "website-roles"
+
ranks = {
"member" : 3,
"builder" : 7,
@@ -13,33 +21,42 @@ ranks = {
"admin" : 5
}
+ranks = open_json_file(config_file, ranks)
+
+def save_ranks():
+ save_json_file(config_file, ranks)
+
+#-----------------------Event---------------------------
@hook.event("player.PlayerJoinEvent", "normal")
def on_player_join(event):
user = event.getPlayer()
uuid = uid(player).replace("-", "")
- role = get_role(uuid)
- if role in [1, 2, 6]: #Disabled/Banned/Superadmin
- return
- if role:
- for rank in ranks:
- if user.hasPermission("group." + rank):
- if role != ranks[rank]:
- set_role(uuid, ranks[rank])
- return
- if not user.hasPlayedBefore():
- return
- if role == None:
- msg(user, "&cYou haven't registed yet! Make sure to do so on redstoner.com")
+ sql_instruction
+
+ def callback_thing(role, args):
+
+ if role in [1, 2, 6]: #Disabled/Banned/Superadmin
+ return
+ if role != None:
+ for rank in ranks:
+ if user.hasPermission("group." + rank):
+ if role != ranks[rank]:
+ set_role(uuid, ranks[rank])
+ elif user.hasPlayedBefore():
+ msg(user, "&cYou haven't registed yet! Make sure to do so on redstoner.com")
def get_role(uuid):
- return execute_query("SELECT `role_id` FROM users WHERE `uuid` = ? LIMIT 1", uuid)[0][17]
+ results = execute_query("SELECT `role_id` FROM users WHERE `uuid` = ? LIMIT 1;", uuid)
+ return results[0][0]
+ # Returns a table with 1 row (LIMIT 1) and 1 column (SELECT `role_id`), so we're looking for the first row of the first column.
def set_role(uuid, role_id):
- execute_update("UPDATE users SET `role_id` = %d WHERE `uuid` = ?" % role_id, uuid)
+ execute_update("UPDATE users SET `role_id` = ? WHERE `uuid` = ?;", (role_id, uuid,))
+ # %d is like %s for integers (unlogically, you'd expect something like %i), though %s also works here.
def execute_query(query, uuid):
@@ -56,5 +73,40 @@ def execute_update(update, uuid):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute(update, (uuid,))
+ conn.commit()
curs.close()
- conn.close() \ No newline at end of file
+ conn.close()
+
+def get_role(uuid):
+ sql_instruction()
+
+#--------------------------------Queries / Updates----------------------------
+
+def sql_instruction(instruction, args, fetch = True, callback_func = ignored_func, callback_args = tuple()):
+ thread = threading.Thread(target = curs_instruction, args = (instruction_executor, instruction, fetch, callback_func, callback_args))
+ thread.start()
+
+
+def curs_instruction(func, instruction, fetch, callback_func, callback_args):
+ conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
+ curs = conn.getCursor()
+
+ if fetch:
+ returned = func(curs, instruction, fetch)
+ curs.close()
+ conn.close()
+ callback_func(returned, callback_args)
+
+ else:
+ func(curs, instruction, fetch)
+ conn.commit()
+ curs.close()
+ conn.close()
+
+
+def instruction_executor(curs, instruction, fetch):
+ curs.execute(instruction)
+ return curs.fetchall() if fetch else None
+
+def ignored_func(*args):
+ pass \ No newline at end of file