Merge branch 'dev'

This commit is contained in:
NEMESIS13cz
2015-11-01 13:42:11 +01:00
16 changed files with 981 additions and 29 deletions

View File

@@ -1,13 +1,67 @@
from helpers import *
to_see_permission = "utils.showpermission" # See cmd permission in help
"""
@simplecommand is a decorator which is meant to replace @hook.command in redstoner-utils, where useful.
It takes care of checks such as whether the sender is a player, whether they have permission,
whether there are enough argumens, and also takes care of a help message.
On top of that, it makes the code shorter and easier to write with features like Validate, and returning a message instead of a boolean value.
@simplecommand has an inbuilt tracing feature, so you won't have to put all your code in a try/except statement anymore.
Make sure to `from basecommands import simplecommand` before using this decorator.
The arguments are as follows:
* cmd: the command, self explanatory (required);
* aliases: A list containing any aliases for the command, like shortcuts;
* usage: a String defining the expected arguments for the command. Example:
Let's say I have a command /tp <player_to_teleport> <destination_player>. The usage is: "<player_to_teleport> <destination_player>".
I suggest we use the same format throughout redstoner-utils:
- Separate arguments by spaces;
- Use <> if the argument is required, and [] if the argument is optional;
- Add .. to the argument's identifier (name) if it is for example a message (containing spaces).
for example in /msg, the usage would be "<player> <msg..>"
* description: a description of what the command does. Defaults to "Handles cmd".
This is used for the help message, where the description is (meant to be) indented. To keep this indentation
with longer descriptions, call the help message (with the command, ingame) and add '\n'
when it jumps to a new line in the chat. The decorator will take care of the indentation after that.
* senderLimit: an integer resembling the accepted sender type. Defaults to -1. Use:
-1 for console as well as players;
0 for players only;
1 for console only.
* amin: an integer resembling the minimum amount of arguments. Defaults to 0
* amax: an integer resembling the maximum amount of arguments. Defaults to -1, which means that there is no maximum.
* helpNoargs: a boolean value resembling whether the help message should be displayed when no arguments are given.
Defaults to False.
* helpSubcmd: a boolean value resembling whether the help message should be displayed when the first argument.lower() equals "help".
Defaults to False.
Comments on the function added to the decorator:
It should return a message to send to the player. Color codes are translated automatically. It can return None or an empty string to send nothing.
Returning "HELP" makes it show the help message.
Inside the function, calls to static methods in the class Validate can be used to make the code shorter and easier to write (maybe not easier to read).
For example, to make sure that a condition is met, use Validate.isTrue(condition, message to send to the player if the condition is not met)
Don't forget to `from basecommands import Validate` if you wish to make use of this.
For all other Validate checks, see the code below. Feel free to add your own.
Instead of returning a message mid-code to describe an error, you can also use raise CommandException(msg), but it is almost always possible
to replace this return statement with a call to one of the functions in the Validate class. Once again, if you use raise CommandException(msg),
don't forget to `from basecommands import CommandException`.
"""
to_see_permission = "utils.showpermission" # See cmd permission in help
def isSenderValid(senderLimit, isPlayer):
return True if senderLimit == -1 else senderLimit != isPlayer
def invalidSenderMsg(isPlayer):
return "&cThat command can only be run from the console" if isPlayer else "&cThat command can only be run by players"
return "&cThat command can only be used by " + ("the console" if isPlayer else "players")
def helpMsg(sender, cmd, description, usage, aliases, permission):
help_msg = "&aInformation about command /%s:\n &9%s" % (cmd, description.replace("\n", "\n "))
@@ -65,7 +119,7 @@ def simplecommand(cmd,
except CommandException, e:
return e.message
except Exception, e:
error(e.message, trace())
error(trace())
return "&cAn internal error occurred while attempting to perform this command"
return call

View File

@@ -11,7 +11,7 @@ calc_perm_power = "utils.calc.power"
def calc(sender, text):
try:
return do_calc(sender, text)
return do_calc(sender, text.lower())
except:
return None

127
chatalias.py Normal file
View File

@@ -0,0 +1,127 @@
# 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.
from helpers import *
from traceback import format_exc as trace
data = None
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
@hook.command("alias", usage = "/<command> [to_alias] [alias...]", desc = "Aliases words in chat")
def on_alias_command(sender, cmd, label, args):
if not is_player(sender):
msg(sender, "Sorry, Console cannot alias words")
return True
if not sender.hasPermission("utils.alias.allowed"):
plugin_header(recipient = sender, name = "Chat Alias")
noperm(sender)
return True
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!")
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!")
return True
save_json_file("aliases", data)
plugin_header(recipient = sender, name = "Chat Alias")
msg(sender, "Alias for %s successfuly removed" % args[0])
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))
return True
else:
return False
@hook.event("player.AsyncPlayerChatEvent", "high")
def on_player_chat(event):
playerid = str(event.getPlayer().getUniqueId())
data = safe_open_json()
if event.isCancelled():
return
try:
crashtest = data[playerid].items()
except KeyError:
return
for alias, value in data[playerid].items():
event.setMessage(event.getMessage().replace(alias, value))

View File

@@ -6,6 +6,7 @@ import org.bukkit as bukkit
import org.bukkit.Location as Location
import org.bukkit.entity.Player as Player
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause as TeleportCause
import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
import org.bukkit.block as bblock
import org.bukkit.event.entity as entity
import org.bukkit.command.ConsoleCommandSender
@@ -86,7 +87,7 @@ def colorify(text):
"""
replace &-codes with real color codes
"""
return sub("&(?=[?\\da-fk-or])", u"\u00A7", "%s" % text)
return sub("&" + u"\u00A7", "&", "%s" % sub("&(?=[?\\da-fk-or])", u"\u00A7", "%s" % text))
def stripcolors(text):
@@ -143,6 +144,15 @@ def is_player(obj):
return (isinstance(obj, Player))
def can_build(player, block):
"""
return True if the player can change/build at the location of given block
"""
event = BlockBreakEvent(block, player)
server.getPluginManager().callEvent(event)
return not event.isCancelled()
def checkargs(sender, args, amin, amax):
"""
check if a command has a valid amount of args, otherwise notify the sender
@@ -255,4 +265,27 @@ def toggle(player, ls, name = "Toggle", add = None):
msg(player, "&a%s turned off!" % name)
elif add != False:
ls.append(pid)
msg(player, "&a%s turned on!" % name)
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):
subsets = ["","","",""]
i = 0
for j in range(0,len(tocheck)):
if not (tocheck[j] in "0123456789."):
return False
elif tocheck[j] == ".":
i += 1
if (i >= 4):
return False
else:
subsets[i] += tocheck[j]
if not (i == 3):
return False
for j in range(0,3):
if not ((int(subsets[j]) >= 0) & (int(subsets[j]) <= 255)):
return False
return True

107
imbusy.py Normal file
View File

@@ -0,0 +1,107 @@
# 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.
from helpers import *
from basecommands import simplecommand
from traceback import format_exc as trace
busy_players = []
def unclear():
msg(sender, "Umm, what? Sorry, directions unlclear, got head stuck in washing machine")
@hook.command("busy",
aliases = ["focus"],
usage = "/<command> <on|off|status>",
description = "Sets busy mode on, you cannot recieve tpas and MSGs"
)
def on_busy_command(sender, cmd, label, args):
if not is_player(sender):
msg(sender, "Sorry, Console cannot be busy")
return True
if not sender.hasPermission("utils.busy.allowed"):
plugin_header(recipient = sender, name = "I'M BUSY!")
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 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
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
else:
msg(sender, "No, you're good. Feel free to chat with %s!" % args[1])
return True
else:
plugin_header(recipient = sender, name = "I'M BUSY!")
unclear()
return False
@hook.event("player.PlayerCommandPreprocessEvent", "monitor")
def on_cmd_preprocess_event(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)

107
iptracker.py Normal file
View File

@@ -0,0 +1,107 @@
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

19
main.py
View File

@@ -19,7 +19,6 @@ except:
@hook.enable
def on_enable():
shared["modules"]["vanishfix"].enabled()
info("RedstonerUtils enabled!")
@@ -39,10 +38,12 @@ shared["load_modules"] = [
"adminchat",
# Adds /badge, allows to give players achievements
"badges",
# Adds a few block placement corrections/mods
"blockplacemods",
# Adds a few block placement corrections/mods
"blockplacemods",
# Adds /calc, toggles automatic solving of Math expressions in chat
"calc",
# Adds aliasing of chat words
"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
@@ -53,6 +54,8 @@ shared["load_modules"] = [
"webtoken",
# Adds /lol, broadcasts random funyy messages. A bit like the splash text in the menu
"saylol",
# Adds /signalstrength, lets you request a signal strength and an amount of items will be inserted into target container to meet that strength.
"signalstrength",
# Shows the owner of a skull when right-clicked
"skullclick",
# Adds /listen, highlights chat and plays a sound when your name was mentioned
@@ -71,6 +74,8 @@ shared["load_modules"] = [
"check",
# Adds /an, a command you can use to share thoughts/plans/news
"adminnotes",
# Adds busy status to players
"imbusy",
# Adds /imout, displays fake leave/join messages
"imout",
#adds snowbrawl minigame
@@ -88,9 +93,13 @@ shared["load_modules"] = [
# Per-player notes
"tag",
# vanish toggle module - temporary fix
"vanishfix",
#"vanishfix",
# obisidian mining punishment plugin
"punishments"
"punishments",
# a simple replacement for the buggy essentials /vanish
"vanish",
# ip-tracking utility
"iptracker"
]
shared["modules"] = {}
for module in shared["load_modules"]:

View File

@@ -4,7 +4,7 @@ from traceback import format_exc as print_traceback
mentions = open_json_file("mentio", {}) # contains a list of keywords for each player (uuid)
max_amount = 3
max_amount = 1000
arrow = colorify(u"&r&7\u2192&r")
colors_reg = reg_compile(u"\u00A7[\\da-fk-or]") # finds color codes
@@ -13,7 +13,7 @@ def saveMentions():
save_json_file("mentio", mentions)
@hook.event("player.AsyncPlayerChatEvent", "high")
@hook.event("player.AsyncPlayerChatEvent", "monitor")
def onChat(event):
if not event.isCancelled():
sender = event.getPlayer()
@@ -70,7 +70,7 @@ def add_keyword(sender, args):
keywords = get_keywords(sender)
new_word = stripcolors(args[1].lower())
if len(keywords) >= max_amount:
if (len(keywords) >= max_amount) and (max_amount >= 0):
msg(sender, "&cYou are already listening for %s words! Try &6/mentio del <word>" % max_amount)
return True
@@ -146,4 +146,4 @@ def onListenCommand(sender, command, label, args):
show_help(sender)
else:
show_help(sender)
return True
return True

26
misc.py
View File

@@ -6,7 +6,7 @@ from sys import exc_info
import thread
import org.bukkit.inventory.ItemStack as ItemStack
import org.bukkit.Bukkit as Bukkit
from basecommands import simplecommand
from basecommands import simplecommand, Validate
@@ -70,7 +70,6 @@ def cmd_event2(event):
""" Disabled while builder can't access Trusted
@hook.event("player.PlayerGameModeChangeEvent", "low")
def on_gamemode(event):
@@ -203,7 +202,8 @@ def eval_thread(sender, code):
pythoners = [
"e452e012-2c82-456d-853b-3ac8e6b581f5", # Nemes
"ae795aa8-6327-408e-92ab-25c8a59f3ba1", # jomo
"305ccbd7-0589-403e-a45b-d791dcfdee7d" # PanFritz
"305ccbd7-0589-403e-a45b-d791dcfdee7d", # PanFritz
"51f2ad3c-6cc8-40ea-aa2b-f25970316921" # Dico
]
@simplecommand("pyeval",
@@ -256,14 +256,26 @@ def on_modules_command(sender, command, label, args):
plugin_header(sender, "Modules")
msg(sender, ", ".join([(("&a" if mod in shared["modules"] else "&c") + mod) for mod in shared["load_modules"]]))
@hook.command("warn")
def on_warn_command(sender, command, label, args):
@simplecommand("warn",
usage = "",
description = "Warns everybody on the server that you will cause lag shortly",
amax = 0,
helpSubcmd = True)
def warn_command(sender, command, label, args):
broadcast(None, " &b= &2&lLag incoming! &r-%s" % sender.getDisplayName())
@hook.command("warnp")
def on_warnp_command(sender, command, label, args):
@simplecommand("warnp",
usage = "",
description = "Warns everybody on the server that you might cause lag shortly",
amax = 0,
helpSubcmd = True)
def warnp_command(sender, command, label, args):
broadcast(None, " &b= &2&lPossible lag incoming! &r-%s" % sender.getDisplayName())
""" Something I'm planning for schematics
@hook.event("player.PlayerCommandPreprocessEvent", "low")
def on_command(event):

View File

@@ -25,4 +25,5 @@ def on_join(event):
@hook.event("player.PlayerQuitEvent","highest")
def on_leave(event):
py_players.remove(get_py_player(event.getPlayer()))
py_players.remove(get_py_player(event.getPlayer()))

View File

@@ -98,7 +98,7 @@ def command(sender, cmd, label, args):
msg(sender, "&e-&a There are no people mining obsidian")
return True
for slave in slaves:
msg(sender, "&e-&a %s: %s blocks" % (slave.get_uuid(), slave.get_blocks()))
msg(sender, "&e-&a %s: %s blocks" % (server.getOfflinePlayer(juuid(slave.get_uuid())).getName(), slave.get_blocks()))
return True
elif args[0] == "add":
player = server.getOfflinePlayer(str(args[1]))
@@ -106,6 +106,7 @@ def command(sender, cmd, label, args):
player.teleport(server.getWorld(punish_world).getSpawnLocation())
Slave(False, player, int(args[2]))
save_slaves()
msg(player, "&e-&a You have been punished, mine %s blocks of obsidian to get out!" % args[2])
msg(sender, "&e-&a Player %s has been added into punishments for %s blocks of obsidian" % (player.getName(), args[2]))
else:
msg(sender, "&cYou can only punish online players")

View File

@@ -149,7 +149,7 @@ arg 0 size of backup
@hook.command("script_backup_database_end")
def print_backup_db_end(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&6 =&2 Databse backup completed.")
broadcast(None, "&6 =&2 Database backup completed.")
server.dispatchCommand(server.getConsoleSender(), "ac &abackup size: &2%sMB&a." % args[0])
else:
noperm(sender)

221
serversigns.py Normal file
View File

@@ -0,0 +1,221 @@
from helpers import *
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)
return (bLoc.getWorld().getName(), bLoc.getBlockX(), bLoc.getBlockY(), bLoc.getBlockZ())
def equals(loc1, loc2):
for i in range(4):
if loc1[i] != loc2[i]:
return False
return True
def getOwner(sign):
return retrieve_player(sign[0]).getName()
def isOwner(sign, player):
return sign and sign[0] == uid(player)
def canEdit(sign, player):
return player.hasPermission("utils.serversigns.admin") or isOwner(sign, player)
def getSign(locAt):
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'):
return "&c[Signs] &" + colour + msg
"""
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)
""
"""

159
signalstrength.py Normal file
View File

@@ -0,0 +1,159 @@
from helpers import *
import org.bukkit.inventory.ItemStack as ItemStack
import org.bukkit.Material as Material
from math import ceil
from basecommands import simplecommand, Validate, CommandException
""" Suggestion by Armadillo28, see thread: http://redstoner.com/forums/threads/2213?page=1#reply-14507 """
disallowed_item_types = (
Material.getMaterial(0),
Material.getMaterial(175),
Material.getMaterial(383),
)
default_args = open_json_file("signalstrengthdefaults", {})
def save_defaults():
save_json_file("signalstrengthdefaults", default_args)
def item_name(item_type, remove_underscores = True):
typ = str(item_type).lower()
return typ.replace("_", "") if remove_underscores else typ
def item_type_allowed(item_type):
return not item_type in disallowed_item_types
def required_item_count(strength, stack_size, slot_count):
if strength == 0:
item_count = 0
elif strength == 1:
item_count = 1
else:
item_count = int(ceil(slot_count * stack_size / 14.0 * (strength - 1)))
resulting_strength = 0 if item_count == 0 else int(1 + 14.0 * item_count / stack_size / slot_count)
#Clarification on these formulas at http://minecraft.gamepedia.com/Redstone_Comparator#Containers
return item_count if resulting_strength == strength else None
def get_data(player, args):
uuid = uid(player)
if uuid in default_args:
strength, item_type, item_data = default_args[uuid]
item_type = Material.getMaterial(item_type)
else:
strength = 1
item_type = Material.REDSTONE
item_data = 0
if len(args) > 0:
Validate.isTrue(args[0].isdigit() and 0 <= int(args[0]) <= 15, "&cThe signal strength has to be a value from 0 to 15")
strength = int(args[0])
if len(args) > 1:
if args[1].isdigit():
item_type = Material.getMaterial(int(args[1]))
else:
item_type = Material.matchMaterial(args[1])
Validate.notNone(item_type, "&cThat item type could not be found")
Validate.isTrue(item_type not in disallowed_item_types, "&cThat item type may not be used")
if len(args) > 2:
Validate.isTrue(args[2].isdigit() and 0 <= int(args[2]) <= 15, "&cThe data has to be a value from 0 to 15")
item_data = int(args[2])
return (strength, item_type, item_data)
def get_inventory(block):
try:
return block.getState().getInventory()
except AttributeError:
return None
def get_entire_container(container):
container_blocks = [container]
container_type = container.getType()
if container_type in (Material.CHEST, Material.TRAPPED_CHEST):
loc = container.getLocation()
x = loc.getBlockX()
y = loc.getBlockY()
z = loc.getBlockZ()
world = loc.getWorld()
container_blocks += [
block for block in (
world.getBlockAt(x + 1, y, z),
world.getBlockAt(x - 1, y, z),
world.getBlockAt(x, y, z + 1),
world.getBlockAt(x, y, z - 1),
) if block.getType() == container_type
]
return container_blocks
@simplecommand("signalstrength",
usage = "(default) [signalstrength] [item] [data]",
aliases = ["ss", "level"],
description = "Fills the targeted container with the correct amount of items to achieve the desired signal strength.",
amin = 0,
amax = 4,
helpSubcmd = True,
senderLimit = 0)
def on_signalstrength_command(sender, command, label, args):
if len(args) > 0 and args[0].lower() in ("default", "defaults", "setdefaults"):
strength, item_type, item_data = get_data(sender, args[1:])
uuid = uid(sender)
if strength == 1 and item_type == Material.REDSTONE and item_data == 0:
if uuid in default_args:
del default_args[uuid]
save_defaults()
else:
default_args[uuid] = (strength, str(item_type), item_data)
save_defaults()
return "&aSet your signal strength defaults to (%s, %s, %s)" % (strength, item_name(item_type, False), item_data)
Validate.isTrue(len(args) <= 3, "&cExpected at most 3 arguments")
target_block = sender.getTargetBlock(None, 5)
Validate.notNone(target_block, "&cThat command can only be used when a container is targeted")
inventory = get_inventory(target_block)
Validate.notNone(inventory, "&cThat command can only be used if a container is targeted")
strength, item_type, item_data = get_data(sender, args)
#--------Get the stack size and required amount of items to achieve the desired signal strength---------
stack_size = item_type.getMaxStackSize()
slot_count = inventory.getSize()
item_count = required_item_count(strength, stack_size, slot_count)
Validate.notNone(item_count, "&cThe desired signal strength could not be achieved with the requested item type")
#--------Add the other side of the chest if target is a double chest and check if player can build---------
container_blocks = get_entire_container(target_block)
for block in container_blocks:
Validate.isTrue(can_build(sender, block), "&cYou do not have permission to do that here")
#----------------Insert items-------------
full_stack_count, remaining = divmod(item_count, stack_size)
for block in container_blocks:
inv = block.getState().getInventory()
inv.clear()
for i in range(full_stack_count):
inv.setItem(i, ItemStack(item_type, stack_size, item_data))
if remaining > 0:
inv.setItem(full_stack_count, ItemStack(item_type, remaining, item_data))
return "&aComparators attached to that %s will now put out a signal strength of %s" % (item_name(target_block.getType()), strength)

8
tag.py
View File

@@ -34,11 +34,11 @@ def command(sender, command, label, args):
else:
msg(sender, "&a-&c Unknown subcommand! (add, check, del)")
else:
msg(sender, "&a&c Usage: /tag add/check")
msg(sender, "&a&c Usage: /tag add/check/del")
return True
def delete(sender, args):
player = server.getPlayer(args[0])
player = server.getOfflinePlayer(args[0])
uuid = uid(player)
try:
if data[uuid] == None:
@@ -54,7 +54,7 @@ def delete(sender, args):
msg(sender, "&a-&e Deleted note at %s" % args[1])
def add(sender, args):
player = server.getPlayer(args[0])
player = server.getOfflinePlayer(args[0])
uuid = uid(player)
try:
if data[uuid] == None:
@@ -66,7 +66,7 @@ def add(sender, args):
save_json_file("tag", data)
def check(sender, args):
player = server.getPlayer(args[0])
player = server.getOfflinePlayer(args[0])
uuid = uid(player)
try:
num = 0

121
vanish.py Normal file
View File

@@ -0,0 +1,121 @@
from helpers import *
from basecommands import simplecommand
from basecommands import Validate
vanished = []
def is_authorized(player):
return player.hasPermission("utils.vanish")
def is_vanished(player):
return uid(player) in vanished
#this can be used to silently set the vanished state of a player
def set_state(player, state):
if state == is_vanished(player):
return
if state:
enable_vanish(player)
else:
disable_vanish(player)
def enable_vanish(target):
vanished.append(uid(target))
for player in list(server.getOnlinePlayers()):
if not is_authorized(player):
player.hidePlayer(target)
def disable_vanish(target):
vanished.remove(uid(target))
for player in list(server.getOnlinePlayers()):
player.showPlayer(target)
@simplecommand("vanish",
aliases = ["v"],
usage = "[on/off]",
description = "Toggles vanish mode, hiding you and your online status \nfrom other players.",
senderLimit = 0,
amin = 0,
amax = 1,
helpNoargs = False,
helpSubcmd = True
)
def vanish_command(sender, command, label, args):
try:
current_state = is_vanished(sender)
new_state = not current_state
if len(args) == 1:
arg = args[0].lower()
if arg == "on":
new_state = True
elif arg == "off":
new_state = False
if current_state == new_state:
return "&cYou were %s vanished!" % ("already" if current_state else "not yet")
set_state(sender, new_state)
return "&a%s vanish mode!" % ("Enabled" if new_state else "Disabled")
except:
error(trace())
@hook.event("player.PlayerJoinEvent")
def on_player_join(event):
player = event.getPlayer()
if not is_authorized(player):
for uuid in vanished:
player.hidePlayer(retrieve_player(uuid))
elif is_vanished(player):
msg(player, "&cKeep in mind that you are still vanished! Use /vanish to disable.")
@hook.event("player.PlayerQuitEvent")
def on_player_quit(event):
player = event.getPlayer()
if not is_authorized(player):
for uuid in vanished:
player.showPlayer(retrieve_player(uuid))
@simplecommand("vanishother",
usage = "{player} [on/off]",
description = "Toggles vanish mode for someone, hiding them and their online status from other players.",
amin = 1,
amax = 2,
helpNoargs = True,
helpSubcmd = True)
def vanishother_command(sender, command, label, args):
target = server.getPlayer(args[0])
Validate.notNone(target, "&cThe specified player is not online")
current_state = is_vanished(target)
new_state = not current_state
if len(args) == 2:
arg = args[1].lower()
if arg == "on":
new_state = True
elif arg == "off":
new_state = False
if current_state == new_state:
return "&cThat player was already vanished!" if current_state else "&cThat player was not yet vanished!"
set_state(target, new_state)
enabled_str = "enabled" if new_state else "disabled"
if target != sender:
msg(target, "&aVanish mode %s by %s" % (enabled_str, sender.getDisplayName() if is_player(sender) else "&9CONSOLE"))
return "&aVanish mode %s%s" % (enabled_str, " for " + target.getDisplayName() if target != sender else "")