Merge branch 'dev'

This commit is contained in:
PanFritz
2015-01-09 21:38:04 +01:00
29 changed files with 1792 additions and 1593 deletions
+1
View File
@@ -0,0 +1 @@
If you want to contribute, please [read through the pages on the wiki](https://github.com/RedstonerServer/redstoner-utils/wiki).
+21
View File
@@ -0,0 +1,21 @@
# The MIT License (MIT)
Copyright (c) Redstoner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE
+3 -240
View File
@@ -2,245 +2,8 @@
Redstoner's custom plugins, written in python. Redstoner's custom plugins, written in python.
------
# Installation / Set-up ## Contributing
1-line-install-script for bash: If you want to contribute, please [read through the pages on the wiki](https://github.com/RedstonerServer/redstoner-utils/wiki).
`wget -O install.sh "http://pastie.org/pastes/9310905/download?key = 6byp4mrqmiui8yqeo3s6yw"; md5sum --check <<<"3499671c0832e561bc9c7d476d2167cb install.sh" && sh install.sh`
Detailed description:
0. Create a new directory called 'redstoner'
0. Download [the latest spigot](http://ci.md-5.net/job/Spigot/lastStableBuild/artifact/Spigot-Server/target/spigot.jar)
0. Run it once inside redstoner, then shut it down again
0. Create a new directory (inside redstoner) called 'lib'
0. Download [mysql-connector](https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.30.zip), extract 'mysql-connector-java-X.X.XX-bin.jar
' and save it as 'mysql-connector.jar' inside lib
0. Download [PyPluginLoader](http://bamboo.gserv.me/browse/PLUG-PYPL/latestSuccessful/artifact/JOB1/Version-agnostic-jar/PyPluginLoader.jar) (we're using [this fork](https://github.com/gdude2002/Python-Plugin-Loader)) into the plugins directory
0. inside plugins, clone this directory into 'redstoner-utils**.py.dir**':
`git clone git@bitbucket.org:redstonesheep/redstoner-utils.git redstoner-utils.py.dir`
0. Download [PEX](http://dev.bukkit.org/media/files/789/291/PermissionsEx.jar) into plugins
0. **if you want** to develop mysql things, set up a local MySQL server
# branches
* **dev**
Always use this branch to change code, please test before pushing. (If something goes wrong here, that's okay)
* **master**
Never commit into this branch directly! Only merge stable versions of *dev*:
```bash
git checkout master
git merge dev
```
# Deploying on the server
**Never** edit the files directly on the server!
The dev server uses the *dev* branch, the live server uses *master*.
**Do not use `git pull` on the server!** *(All files must be pulled/owned by the 'redstoner' user.)*
### Deploying on test server
* Push all changes
* Run `<server-dir>/git_pull_utils.sh`.
* Restart (You can try reloading here, but expect the unexpected)
### Deploying on production server
* Test all code carefully on the test server
***on your machine:***
* `git checkout master`
* `git pull`
* `git merge dev`
* `git push -u origin master`
* `git checkout dev`
***on the server:***
* `rs update_utils`
* Restart
# Modules / Files
If you add a new file, please update this list!
If you want the server to load a file (*module*) on startup, add it to the `modules` list in `main.py`.
* `files/`
> All config / storage files go here
* `plugin.yml`
> The plugin.yml file required for bukkut plugins
* `main.py`
> The only file loaded by PyPluginLoader, loads all other modules
> Contains a few methods that **need to be cleaned up**
* `helpers.py`
> Library that adds a bunch of re-usable methods which are used in nearly all other modules
* `adminchat.py`
> Adds chat for staff using `/ac <text` or `,<text>`
* `chatgroups.py`
> Adds group-chat with `/chatgroup` and `/cgt` to toggle normal chat into group mode
* `lagchunks.py`
> Plugin to locate laggy chunks. `/lc <n>` lists chunks with more than `n` entities
* `mysqlhack.py`
> A library that makes use of the so called ClassPathHack for jython to allow proper loading of `mysql-connector.jar` at runtime. import only, no methods.
* `plotter.py`
> Start of a custom plot-plugin like PlotMe, on hold because the PlotMe developer continued to develop PlotMe
* `reports.py`
> The `/report <text>` and `/rp` plugin
* `saylol.py`
> Remake of sheep's old SayLol plugin, originally written as a standalone plugin in Java
* `skullclick.py`
> Shows the owner of a skull when right-clicked
* `webtoken.py`
> Adds `/token`, reads and writes from the database to generate *pronouncable* (and thus memorable) registration-tokens for the website
* `spawnplayer.py`
> Code that was used once to create [this](http://www.reddit.com/r/Minecraft/comments/28le52/screenshot_of_all_players_that_joined_my_server/) awesome [screenshot](http://i.imgur.com/v4wg5kl.png)
* `tilehelper.py`
> A plugin that automatically tiles (stacks) blocks inside a selected region in configurable directions.
* `mentio.py`
> Adds `/listen`, highlights chat and plays a sound when your name was mentioned
* `cycler.py`
> Adds `/cycler`, swaps the hotbar with inventory when player changes slot from right->left or left->right
* `motd.py`
> Adds `/getmotd` & `/setmotd` to update the motd on the fly (no reboot).
* `abot.py`
> AnswerBot. Hides stupid questions from chat and tells the sender about `/faq` or the like
* `damnspam.py`
> Adds `/damnspam`, creates timeout for buttons/levers to mitigate button spam.
* `forcefield.py`
> Adds '/forcefield', creates forcefield for players who want it.
# Code styleguide & tips
## Indentation
Never use tabs!
Use 2 spaces to indent.
## Quotes
Always use double-quotes!
Only use single-quotes when the string contains double-quotes that would need to be escaped.
## Capitalization
Do not use camelCase for variable or function names! Use under_score naming.
camelCase is okay when used like `import foo.bar.camelCase as camelCase`.
## Aligning variable assignments
In case you have multiple variable assignments, align the equals sign:
```Python
# bad
foo = 1
foobar = 2
a = 3
# good
foo = 1
foobar = 2
a = 3
```
Pro Tip: Use the AlignTab plugin for Sublime Text!
## Horizontal spacing
Use at least one space left and one space right to equals signs, and one space right to colons.
## Vertical spacing
Leave two empty lines before function definitions. In case you need to use `@hook.something`, add the two lines before that, directly followed by the definition.
## Meaningful names
Give function and variable names meaningful names. If you want to shorten long names, that's fine, but leave a comment on assigment with the actual meaning.
## Readability
Don't create long lines with lots of function calls. Split into multiple lines instead.
Also avoid methods with lots of lines. Split into multiple methods instead.
```Python
# bad
foo = int(player_data[str(server.getPlayer(args[4]).getUniqueId())]["details"].["last_login"].strftime("%s"))
# good
player = server.getPlayer(args[4])
player_id = uid(player)
logintime = player_data[played_id]["last_login"]
epoch_time = int(logintime.strftime("%s"))
```
## Comments
Comments are good!
Please comment everything that's non-obious or makes it easier to understand
## Debugging
Debugging can be a bit special with jython/PyPluginLoader.
When something goes wrong, you probably see a weird traceback that's not telling you shit.
...unless you take a closer look.
You will not see a direct traceback of the python methods.
Instead, you'll probably see a bunch of java, bukkit and python things, because it tries to translate python into java, line per line.
Take a closer look at the method names, they might tell you what it's trying to do and where it's coming from.
Watch out for something like `org.python.pycode._pyx5.horribleCode$23(/path/to/badcode.py:214) ~[?:?]`
0. In this case, `_pyx5` is our module.
0. `horribleCode` is the method that was called
0. `/path/to/badcode.py` is the actual file of our module
0. `:214` is the line in which the error occured.
Please note that the line may not be accurate. You'll often get the start of a loop, or the end of a method - when the actual error was somewhere in there.
In many cases, this is enough to find your bug. If you still cannot find it,try to catch exceptions in your code, as follows:
## Catching exceptions
If you want to catch all exceptions (e.g. for debugging), do not `catch Exception`.
Since we're using jython, this will not catch Java exceptions.
This will give you some more deatails:
```python
from traceback import format_exc as trace
try:
#code
except: # everything
print(trace())
```
+40 -40
View File
@@ -5,59 +5,59 @@ answers = []
def load_answers(): def load_answers():
global answers global answers
answers = open_json_file("abot", []) answers = open_json_file("abot", [])
# compile answers # compile answers
for answer in answers: for answer in answers:
answer["regex"] = [reg_compile(reg.lower()) for reg in answer["regex"]] answer["regex"] = [reg_compile(reg.lower()) for reg in answer["regex"]]
def list_answers(sender): def list_answers(sender):
for answer in answers: for answer in answers:
msg(sender, "&e{") msg(sender, "&e{")
msg(sender, " &eregex:") msg(sender, " &eregex:")
for regex in answer["regex"]: for regex in answer["regex"]:
msg(sender, " " + regex.pattern, basecolor="a", usecolor = False) msg(sender, " " + regex.pattern, basecolor="a", usecolor = False)
msg(sender, " &epermission:") msg(sender, " &epermission:")
msg(sender, " " + str(answer["hide-perm"]), basecolor="a", usecolor = False) msg(sender, " " + str(answer["hide-perm"]), basecolor="a", usecolor = False)
msg(sender, " &emessage:") msg(sender, " &emessage:")
msg(sender, " " + "\n ".join(answer["message"].split("\n"))) msg(sender, " " + "\n ".join(answer["message"].split("\n")))
msg(sender, "&e}") msg(sender, "&e}")
@hook.command("abot") @hook.command("abot")
def on_abot_command(sender, args): def on_abot_command(sender, args):
plugin_header(sender, "AnswerBot") plugin_header(sender, "AnswerBot")
if sender.hasPermission("utils.abot.admin"): if sender.hasPermission("utils.abot.admin"):
if not args: if not args:
msg(sender, "&2/abot list &eList all answers and their regex") msg(sender, "&2/abot list &eList all answers and their regex")
msg(sender, "&2/abot reload &eReload the config file") msg(sender, "&2/abot reload &eReload the config file")
elif args[0] == "list": elif args[0] == "list":
list_answers(sender) list_answers(sender)
elif args[0] == "reload": elif args[0] == "reload":
load_answers() load_answers()
msg(sender, "&2Reloaded!") msg(sender, "&2Reloaded!")
else:
msg(sender)
else: else:
msg(sender) noperm(sender)
else: return True
noperm(sender)
return True
@hook.event("player.AsyncPlayerChatEvent", "low") @hook.event("player.AsyncPlayerChatEvent", "low")
def on_chat(event): def on_chat(event):
sender = event.getPlayer() sender = event.getPlayer()
message = event.getMessage().lower() message = event.getMessage().lower()
for answer in answers: for answer in answers:
for regex in answer["regex"]: for regex in answer["regex"]:
if regex.search(message): if regex.search(message):
if not answer["hide-perm"] or not sender.hasPermission(answer["hide-perm"]): if not answer["hide-perm"] or not sender.hasPermission(answer["hide-perm"]):
plugin_header(sender, "AnswerBot") plugin_header(sender, "AnswerBot")
msg(sender, answer["message"] + "\n ") msg(sender, answer["message"] + "\n ")
event.setCancelled(True) event.setCancelled(True)
info("(hidden) %s: '%s'" % (sender.getName(), message)) info("(hidden) %s: '%s'" % (sender.getName(), message))
break break
load_answers() load_answers()
+32 -32
View File
@@ -7,49 +7,49 @@ ac_toggle_list = []
ac_prefix = "&8[&cAC&8]" ac_prefix = "&8[&cAC&8]"
def adminchat(sender, msg): def adminchat(sender, msg):
name = "&7{unknown}" name = "&7{unknown}"
try: try:
name = sender.getDisplayName() name = sender.getDisplayName()
except AttributeError: except AttributeError:
name = sender.getName() name = sender.getName()
broadcast(ac_permission, "%s &9%s&8: &b%s" % (ac_prefix, name, msg)) broadcast(ac_permission, "%s &9%s&8: &b%s" % (ac_prefix, name, msg))
# ac toggle # ac toggle
@hook.command("act") @hook.command("act")
def on_act_command(sender, args): def on_act_command(sender, args):
if sender.hasPermission(ac_permission): if sender.hasPermission(ac_permission):
p = sender.getName() p = sender.getName()
if p in ac_toggle_list: if p in ac_toggle_list:
ac_toggle_list.remove(p) ac_toggle_list.remove(p)
msg(sender, "%s &aAC toggle: off" % ac_prefix) msg(sender, "%s &aAC toggle: off" % ac_prefix)
else:
ac_toggle_list.append(p)
msg(sender, "%s &aAC toggle: on" % ac_prefix)
else: else:
ac_toggle_list.append(p) noperm(sender)
msg(sender, "%s &aAC toggle: on" % ac_prefix) return True
else:
noperm(sender)
return True
@hook.command("ac") @hook.command("ac")
def on_ac_command(sender, args): def on_ac_command(sender, args):
if sender.hasPermission(ac_permission): if sender.hasPermission(ac_permission):
if not checkargs(sender, args, 1, -1): if not checkargs(sender, args, 1, -1):
return True return True
adminchat(sender, " ".join(args)) adminchat(sender, " ".join(args))
else: else:
noperm(sender) noperm(sender)
return True return True
@hook.event("player.AsyncPlayerChatEvent", "low") @hook.event("player.AsyncPlayerChatEvent", "low")
def on_chat(event): def on_chat(event):
sender = event.getPlayer() sender = event.getPlayer()
msg = event.getMessage() msg = event.getMessage()
if sender.hasPermission(ac_permission) and not event.isCancelled(): if sender.hasPermission(ac_permission) and not event.isCancelled():
if msg[:len(ac_key)] == ac_key: if msg[:len(ac_key)] == ac_key:
adminchat(sender, msg[1:]) adminchat(sender, msg[1:])
event.setCancelled(True) event.setCancelled(True)
elif sender.getName() in ac_toggle_list: elif sender.getName() in ac_toggle_list:
adminchat(sender, msg) adminchat(sender, msg)
event.setCancelled(True) event.setCancelled(True)
+137
View File
@@ -0,0 +1,137 @@
from helpers import *
badges = open_json_file("badges", {})
badges_available = {
"helpful" : "A very helpful player",
"expert_minecraft" : "An expert in Minecraft",
"expert_coder" : "A good coder",
"oldtimer" : "A long time player",
"good_builder" : "A very good builder",
"friendly" : "Many think that this player is friendly",
"very_active" : "A very active player",
"trustworthy" : "This player is very trustworthy",
}
badges_perm_add = "utils.badges.add"
badges_perm_del = "utils.badges.delete"
def save_badges():
save_json_file("badges", badges)
def get_badges(player):
sender_id = uid(player)
return badges.get(sender_id, [])
def show_badges(sender, player):
player_badges = get_badges(player)
if player_badges:
msg(sender, "&6Badges of " + player.getName())
for key in player_badges:
msg(sender, "&b> &3&o%s" % badges_available[key])
else:
msg(sender, "&eThis player has no badges yet")
def new_badge_event(player, badge):
msg(player, "")
msg(player, "&6Wow! You just received a badge!")
msg(player, "&b-> &3%s" % badges_available[badge])
msg(player, "&7Type /badge to see all your badges!")
msg(player, "")
player.playSound(player.getLocation(), "random.orb", 1, 1)
def del_badge_event(player, badge):
msg(player, "&cWe took your badge \"%s\"." % badges_available[badge])
def list_badges(sender):
if badges_available:
for key in badges_available.keys():
msg(sender, "&b> &3%s &7&o\"%s\"" % (key, badges_available[key]))
else:
msg(sender, "&cThere are currently no badges available")
def add_badge(sender, target, badge):
if badge in badges_available:
player_badges = get_badges(target)
if badge in player_badges:
msg(sender, "&cThis player got this badge already!")
return
player_badges.append(badge)
if player_badges:
badges[uid(target)] = player_badges
msg(sender, "&aYou just gave %s a new badge!" % target.getName())
new_badge_event(target, badge)
save_badges()
else:
msg(sender, "&cThere is no badge called %s. Check /badge list!" % badge)
def del_badge(sender, target, badge):
if badge in badges_available.keys():
player_badges = get_badges(target)
if badge in player_badges:
player_badges.remove(badge)
badges[uid(target)] = player_badges
msg(sender, "&aYou just took %s from %s!" % (badge, target.getName()))
save_badges()
del_badge_event(target, badge)
return
msg(sender, "&c%s doesn't have this badge!" % target.getName())
else:
msg(sender, "&cThere is no badge called %s. Check /badge list!" % badge)
@hook.command("badge", aliases=["badges", "rewards"])
def on_badge_command(sender, args):
argnum = int(len(args))
# No arguments
if argnum is 0:
show_badges(sender, sender)
# Length of arguments is 1
if argnum == 1:
# If only argument is "list"
if args[0].lower() == "list":
list_badges(sender)
return True
# If only argument is a player name
target = server.getPlayer(args[0])
if is_player(target):
show_badges(sender, target)
return True
else:
msg(sender, "&cThere is no player called %s online." % args[0])
return True
msg(sender, "&cUnknown syntax: /badge <playername> &o&c /badge list")
return True
# Length of arguments is 3
if argnum == 3:
cmd = args[0].lower()
target = server.getPlayer(args[1])
new_badge = args[2].lower()
if cmd == "add":
if not sender.hasPermission(badges_perm_add):
noperm(sender)
return True
add_badge(sender, target, new_badge)
return True
if cmd == "take" or cmd == "del":
if not sender.hasPermission(badges_perm_del):
noperm(sender)
return True
del_badge(sender, target, new_badge)
return True
msg(sender, "&cUnknown syntax: /badge <add|take> <playername> <badge>")
return True
+62
View File
@@ -0,0 +1,62 @@
from helpers import *
calc_users = open_json_file("calc", [])
math_operators = ["+", "-", "*", "/", "&", "|"]
ignore_operators = ["**", "&&", "||"] # ** may be too intensive, the others cause syntax errors
calc_perm = "utils.calc"
def calc(text):
"""
extracts a mathematical expression from `text`
returns (expression, result) or None
"""
expression = ""
should_calc = False
for char in text:
if char.isdigit() or (should_calc and char in [".", " "]):
expression += char
elif char in math_operators:
# calculation must include at least 1 operator
should_calc = True
expression += char
elif should_calc and char.isalpha():
# don't include any more text in the calculation
break
if should_calc and not any(op in expression for op in ignore_operators):
try:
result = str(eval(expression)) # pylint: disable = W0123
except: # pylint: disable = W0702
# we can run into all kinds of errors here
# most probably SyntaxError
return None
return (expression, result)
return None
@hook.event("player.AsyncPlayerChatEvent", "monitor")
def on_calc_chat(event):
sender = event.getPlayer()
message = event.getMessage()
if not event.isCancelled() and uid(sender) in calc_users and sender.hasPermission(calc_perm):
output = calc(message)
if output:
msg(sender, "&2=== Calc: &e" + output[0] + " &2= &c" + output[1])
@hook.command("calc", description="Toggles chat calculations")
def on_calc_command(sender, args):
plugin_header(sender, "Chat Calculator")
if not sender.hasPermission(calc_perm):
noperm(sender)
return True
if not checkargs(sender, args, 0, 1):
return True
if not is_player(sender):
msg(sender, "&cYou are not a player!" % sender)
return True
toggle(sender, calc_users, name = "Calc")
save_json_file("calc", calc_users)
return True
+64 -64
View File
@@ -10,83 +10,83 @@ cg_toggle_list = []
@hook.command("chatgroup") @hook.command("chatgroup")
def on_chatgroup_command(sender, args): def on_chatgroup_command(sender, args):
plugin_header(sender, "ChatGroups") plugin_header(sender, "ChatGroups")
sender_id = uid(sender) sender_id = uid(sender)
if len(args) == 1 and args[0] == "leave": if len(args) == 1 and args[0] == "leave":
if sender_id in groups.keys(): if sender_id in groups.keys():
groupchat(sender, "left the group", True) groupchat(sender, "left the group", True)
group = groups[sender_id] group = groups[sender_id]
del(groups[sender_id]) del(groups[sender_id])
save_groups() save_groups()
else:
msg(sender, "&aYou can't leave no group, derp!")
elif len(args) == 1 and args[0] == "info":
if sender_id in groups.keys():
group = groups[sender_id]
msg(sender, "&aCurrent chatgroup: %s" % group)
users = []
for uuid, ugroup in groups.iteritems():
if ugroup == group:
usr = server.getPlayer(juuid(uuid))
if usr:
users.append(usr.getDisplayName())
msg(sender, "&aUsers in this group:")
msg(sender, "&a%s" % ", ".join(users))
else:
msg(sender, "&aYou're in no chatgroup.")
elif len(args) == 2 and args[0] == "join":
groups[sender_id] = args[1]
groupchat(sender, "joined the group", True)
save_groups()
msg(sender, "&aYour chatgroup is set to '%s'" % args[1])
msg(sender, "&aUse chat like '&e%s<message>' to send messages to this group." % cg_key)
else: else:
msg(sender, "&aYou can't leave no group, derp!") msg(sender, "&e/chatgroup join <name>")
elif len(args) == 1 and args[0] == "info": msg(sender, "&e/chatgroup leave")
if sender_id in groups.keys(): msg(sender, "&e/chatgroup info")
group = groups[sender_id]
msg(sender, "&aCurrent chatgroup: %s" % group)
users = []
for uuid, ugroup in groups.iteritems():
if ugroup == group:
usr = server.getPlayer(juuid(uuid))
if usr:
users.append(usr.getDisplayName())
msg(sender, "&aUsers in this group:")
msg(sender, "&a%s" % ", ".join(users))
else:
msg(sender, "&aYou're in no chatgroup.")
elif len(args) == 2 and args[0] == "join":
groups[sender_id] = args[1]
groupchat(sender, "joined the group", True)
save_groups()
msg(sender, "&aYour chatgroup is set to '%s'" % args[1])
msg(sender, "&aUse chat like '&e%s<message>' to send messages to this group." % cg_key)
else:
msg(sender, "&e/chatgroup join <name>")
msg(sender, "&e/chatgroup leave")
msg(sender, "&e/chatgroup info")
@hook.command("cgt") @hook.command("cgt")
def on_cgt_command(sender, args): def on_cgt_command(sender, args):
p = uid(sender) p = uid(sender)
if p in cg_toggle_list: if p in cg_toggle_list:
cg_toggle_list.remove(p) cg_toggle_list.remove(p)
msg(sender, "&8[&bCG&8] &e&oCG toggle: off") msg(sender, "&8[&bCG&8] &e&oCG toggle: off")
else: else:
cg_toggle_list.append(p) cg_toggle_list.append(p)
msg(sender, "&8[&bCG&8] &e&oCG toggle: on") msg(sender, "&8[&bCG&8] &e&oCG toggle: on")
return True return True
def groupchat(sender, message, ann = False): def groupchat(sender, message, ann = False):
group = groups.get(uid(sender)) group = groups.get(uid(sender))
if group == None: if group == None:
msg(sender, "&cYou are not in a group!") msg(sender, "&cYou are not in a group!")
return return
name = sender.getDisplayName() name = sender.getDisplayName()
if ann: if ann:
mesg = "&8[&bCG&8] &e&o%s&e&o %s" % (name, message) mesg = "&8[&bCG&8] &e&o%s&e&o %s" % (name, message)
else: else:
mesg = "&8[&bCG&8] &f%s&f: &6%s" % (name, message) mesg = "&8[&bCG&8] &f%s&f: &6%s" % (name, message)
info("[ChatGroups] %s (%s): %s" % (sender.getDisplayName(), group, message)) info("[ChatGroups] %s (%s): %s" % (sender.getDisplayName(), group, message))
for receiver in server.getOnlinePlayers(): for receiver in server.getOnlinePlayers():
groups.get(uid(receiver)) == group and msg(receiver, mesg) groups.get(uid(receiver)) == group and msg(receiver, mesg)
def save_groups(): def save_groups():
save_json_file("chatgroups", groups) save_json_file("chatgroups", groups)
@hook.event("player.AsyncPlayerChatEvent", "normal") @hook.event("player.AsyncPlayerChatEvent", "normal")
def on_chat(event): def on_chat(event):
sender = event.getPlayer() sender = event.getPlayer()
msge = event.getMessage() msge = event.getMessage()
if not event.isCancelled(): if not event.isCancelled():
sender_id = uid(sender) sender_id = uid(sender)
if msge[:len(cg_key)] == cg_key and sender_id in groups.keys(): if msge[:len(cg_key)] == cg_key and sender_id in groups.keys():
groupchat(sender, msge[1:]) groupchat(sender, msge[1:])
event.setCancelled(True) event.setCancelled(True)
elif sender_id in cg_toggle_list: elif sender_id in cg_toggle_list:
groupchat(sender, msge) groupchat(sender, msge)
event.setCancelled(True) event.setCancelled(True)
+101
View File
@@ -0,0 +1,101 @@
import json
import urllib2
import datetime
import mysqlhack #pylint: disable = unused-import
from traceback import format_exc as print_traceback
from com.ziclix.python.sql import zxJDBC
from secrets import *
from helpers import *
# receive info based on the user's IP. information provided by ipinfo.io
def ip_info(player):
if player.isOnline():
return json.load(urllib2.urlopen("http://ipinfo.io%s/json" % str(player.getAddress().getAddress())))
else:
return {}
# receive first join date based on the player data (may not be accurate)
def get_first_join(player):
first_join = int(player.getFirstPlayed())
dt = datetime.datetime.fromtimestamp(first_join/1000.0)
return dt.strftime("%Y-%m-%d %H:%M")
# receive last seen date based on the player data
def get_last_seen(player):
last_seen = int(player.getLastPlayed())
dt = datetime.datetime.fromtimestamp(last_seen/1000.0)
return dt.strftime("%Y-%m-%d %H:%M")
# receive link and email from website
def get_website_data(player):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
uuid = str(uid(player)).replace("-", "")
curs.execute("SELECT DISTINCT `id`, `email` FROM users WHERE `uuid` = ? LIMIT 1", (uuid,))
results = curs.fetchall()
curs.close()
conn.close()
if len(results) == 1:
if len(results[0]) == 2:
return {
"link": "http://redstoner.com/users/%s" % results[0][0],
"email": results[0][1]
}
else:
return {}
else:
return {}
# receive country based on the user's IP
def get_country(data):
return str(data.get("country"))
def get_all_names(player):
uuid = str(uid(player)).replace("-", "")
names = json.load(urllib2.urlopen("https://api.mojang.com/user/profiles/%s/names" % uuid))
# [ {"name": "some_name"}, {"name": "other_name"} ]
return ", ".join([name["name"] for name in names])
# combines data
def get_all_data(sender, player):
data = ip_info(player)
msg(sender, "")
try:
msg(sender, "&7 -- Data provided by Redstoner")
msg(sender, "&6> UUID: &e%s" % str(uid(player)))
msg(sender, "&6> First joined: &7(y-m-d h:m:s) &e%s" % get_first_join(player))
msg(sender, "&6> Last seen: &7(y-m-d h:m:s) &e%s" % get_last_seen(player))
website = get_website_data(player)
msg(sender, "&6> Website account: &e%s" % website.get("link"))
msg(sender, "&6> email: &e%s" % website.get("email"))
msg(sender, "&7 -- Data provided by ipinfo.io")
msg(sender, "&6> Country: &e%s" % get_country(data))
msg(sender, "&7 -- Data provided by Mojang")
msg(sender, "&6> All ingame names used so far: &e%s" % get_all_names(player))
except:
# can throw exceptions such as timeouts when Mojang API is down
warn(print_traceback())
msg(sender, "&cSorry, something went wrong while fetching data")
@hook.command("check", description="Displays useful stuff about a user", usage="/check <player>")
def on_hook_command(sender, args):
if sender.hasPermission("utils.check"):
if not checkargs(sender, args, 1, 1):
return True
plugin_header(sender, "Check")
msg(sender, "&7Please notice that the data may not be fully accurate!")
player = server.getOfflinePlayer(args[0]) if len(args) > 0 else None
get_all_data(sender, player)
else:
msg(sender, "&4You don't have the required permissions to execute this command!")
return True
+45 -45
View File
@@ -5,46 +5,46 @@ no_cyclers = open_json_file("cycle", [])
@hook.command("cycle") @hook.command("cycle")
def on_cycler_command(sender, args): def on_cycler_command(sender, args):
plugin_header(sender, "Cycle") plugin_header(sender, "Cycle")
if not is_player(sender): if not is_player(sender):
msg(sender, "&conly players can do this") msg(sender, "&conly players can do this")
return True return True
if not len(args) == 1: if not len(args) == 1:
msg(sender, "&cUsage: /cycle <on|off>") msg(sender, "&cUsage: /cycle <on|off>")
return True return True
cmd = args[0].lower() cmd = args[0].lower()
pid = uid(sender) pid = uid(sender)
nop = pid in no_cyclers nop = pid in no_cyclers
if cmd == "on": if cmd == "on":
if nop: if nop:
no_cyclers.remove(pid) no_cyclers.remove(pid)
save_cyclers() save_cyclers()
msg(sender, "&aTurned &2on&a inventory cycling!") msg(sender, "&aTurned &2on&a inventory cycling!")
else:
msg(sender, "&aAlready turned on.")
elif cmd == "off":
if not nop:
no_cyclers.append(pid)
save_cyclers()
msg(sender, "&aTurned &coff&a inventory cycling!")
else:
msg(sender, "&aAlready turned off.")
else: else:
msg(sender, "&aAlready turned on.") msg(sender, "&cUsage: /cycle <on|off>")
elif cmd == "off": return True
if not nop:
no_cyclers.append(pid)
save_cyclers()
msg(sender, "&aTurned &coff&a inventory cycling!")
else:
msg(sender, "&aAlready turned off.")
else:
msg(sender, "&cUsage: /cycle <on|off>")
return True
@hook.event("player.PlayerItemHeldEvent", "normal") @hook.event("player.PlayerItemHeldEvent", "normal")
def on_slot_change(event): def on_slot_change(event):
player = event.getPlayer() player = event.getPlayer()
if is_creative(player) and uid(player) not in no_cyclers and not player.isSneaking(): if is_creative(player) and uid(player) not in no_cyclers and not player.isSneaking():
prev_slot = event.getPreviousSlot() prev_slot = event.getPreviousSlot()
new_slot = event.getNewSlot() new_slot = event.getNewSlot()
if (prev_slot == 0 and new_slot == 8): # left -> right if (prev_slot == 0 and new_slot == 8): # left -> right
do_cycle(player, True) do_cycle(player, True)
elif (prev_slot == 8 and new_slot == 0): # right -> left elif (prev_slot == 8 and new_slot == 0): # right -> left
do_cycle(player, False) do_cycle(player, False)
# ITEM SLOTS # # ITEM SLOTS #
#_____________________________ #_____________________________
@@ -55,16 +55,16 @@ def on_slot_change(event):
# | 0| 1| 2| 3| 4| 5| 6| 7| 8| # | 0| 1| 2| 3| 4| 5| 6| 7| 8|
def do_cycle(player, down): def do_cycle(player, down):
inv = player.getInventory() inv = player.getInventory()
items = inv.getContents() items = inv.getContents()
shift = -9 if down else 9 shift = -9 if down else 9
shift = shift % len(items) shift = shift % len(items)
for _ in range(4): for _ in range(4):
items = items[shift:] + items[:shift] # shift "around" items = items[shift:] + items[:shift] # shift "around"
uniq_items = sorted(set(list(items)[:9])) # get unique inventory uniq_items = sorted(set(list(items)[:9])) # get unique inventory
if uniq_items != [None]: # row not empty if uniq_items != [None]: # row not empty
break break
inv.setContents(items) inv.setContents(items)
def save_cyclers(): def save_cyclers():
save_json_file("cycle", no_cyclers) save_json_file("cycle", no_cyclers)
+118 -109
View File
@@ -10,136 +10,145 @@ removing_input = False
def save_inputs(): def save_inputs():
save_json_file("damnspam", inputs) save_json_file("damnspam", inputs)
def location_str(block): def location_str(block):
return ";".join([block.getWorld().getName(), str(block.getX()), str(block.getY()), str(block.getZ())]) return ";".join([block.getWorld().getName(), str(block.getX()), str(block.getY()), str(block.getZ())])
def add_input(creator, block, timeout_off, timeout_on): def add_input(creator, block, timeout_off, timeout_on):
inputs[location_str(block)] = { inputs[location_str(block)] = {
"creator" : uid(creator), "creator" : uid(creator),
"timeout_off" : timeout_off, "timeout_off" : timeout_off,
"timeout_on" : timeout_on, "timeout_on" : timeout_on,
"last_time" : 0 "last_time" : 0
} }
@hook.command("damnspam") @hook.command("damnspam")
def on_dammnspam_command(sender, args): def on_dammnspam_command(sender, args):
global changing_input global changing_input
plugin_header(sender, "DamnSpam") plugin_header(sender, "DamnSpam")
if len(args) in [1,2]: if not checkargs(sender, args, 1, 2):
msg(sender, "&c/damnspam <seconds> &e(Buttons/Levers)")
if not is_creative(sender): msg(sender, "&c/damnspam <seconds after off> <seconds after on> &e(Levers only)")
msg(sender, "&cYou can only do this in Creative mode.")
return True
# /damnspam <secs>
if len(args) == 1:
timeout_on = args[0]
try:
timeout_on = round(float(timeout_on), 2)
timeout_off = timeout_on
if not 0 <= timeout_on <= 60:
msg(sender, "&cThe timeout must be within 0-60.")
return True
except ValueError:
msg(sender, "&cThe timeout must be a number")
return True return True
# /damnspam <off> <on> if not is_creative(sender):
elif len(args) == 2: msg(sender, "&cYou can only do this in Creative mode.")
timeout_on = args[0] return True
timeout_off = args[1]
try: # /damnspam <secs>
timeout_on = round(float(timeout_on), 2) if len(args) == 1:
timeout_off = round(float(timeout_off), 2) timeout_on = args[0]
if not 0 <= timeout_on <= 60 or not 0 <= timeout_off <= 60: try:
msg(sender, "&cThe timeout must be within 0-60.") timeout_on = round(float(timeout_on), 2)
return True timeout_off = timeout_on
except ValueError: if 60 >= timeout_on <= -2 or timeout_on == 0:
msg(sender, "&cThe timeout must be a number") timeout_on = False
if timeout_on == False:
msg(sender, "&cThe timeout must be within 0-60 or -1.")
return True
except ValueError:
msg(sender, "&cThe timeout must be a number")
return True
# /damnspam <off> <on>
elif len(args) == 2:
timeout_on = args[0]
timeout_off = args[1]
try:
timeout_on = round(float(timeout_on), 2)
timeout_off = round(float(timeout_off), 2)
if 60 >= timeout_on <= -2 or timeout_on == 0:
timeout_on = False
if 60 >= timeout_off <= -2 or timeout_off == 0:
timeout_off = False
if timeout_on == False or timeout_off == False:
msg(sender, "&cThe timeout must be within 0-60 or -1.")
return True
except ValueError:
msg(sender, "&cThe timeout must be a number")
return True
# get the block we're looking at
target = sender.getTargetBlock(None, 10)
ttype = str(target.getType())
if ttype not in accepted_inputs:
msg(sender, "&cPlease look at a button or lever while executing this command!")
return True
if location_str(target) in inputs:
changing_input = True # this input already has a timeout
# test if player is allowed to build here
test_event = BlockBreakEvent(target, sender)
server.getPluginManager().callEvent(test_event)
changing_input = False
if test_event.isCancelled():
msg(sender, "&cYou are not allowed to modify this %s" % str(target.getType()).lower())
return True
# add block to inputs
add_input(sender, target, timeout_off, timeout_on)
save_inputs()
msg(sender, "&aSuccessfully set a timeout for this %s." % ttype.lower().replace("_", " "))
return True return True
# get the block we're looking at
target = sender.getTargetBlock(None, 10)
ttype = str(target.getType())
if ttype not in accepted_inputs:
msg(sender, "&cPlease look at a button or lever while executing this command!")
return True
if location_str(target) in inputs:
changing_input = True # this input already has a timeout
# test if player is allowed to build here
test_event = BlockBreakEvent(target, sender)
server.getPluginManager().callEvent(test_event)
changing_input = False
if test_event.isCancelled():
msg(sender, "&cYou are not allowed to modify this %s" % str(target.getType()).lower())
return True
# add block to inputs
add_input(sender, target, timeout_off, timeout_on)
save_inputs()
msg(sender, "&aSuccessfully set a timeout for this %s." % ttype.lower())
return True
else:
msg(sender, "&c/damnspam <seconds> &e(Buttons/Levers)")
msg(sender, "&c/damnspam <seconds after off> <seconds after on> &e(Levers only)")
@hook.event("block.BlockBreakEvent", "normal") @hook.event("block.BlockBreakEvent", "normal")
def on_block_break(event): def on_block_break(event):
global removing_input global removing_input
if removing_input: if removing_input:
return True
sender = event.getPlayer()
block = event.getBlock()
btype = str(block.getType()).lower()
if str(block.getType()) in accepted_inputs and not event.isCancelled():
pos_str = location_str(block)
if inputs.get(pos_str):
plugin_header(sender, "DamnSpam")
if sender.isSneaking():
# test if player is allowed to build here
removing_input = True
test_event = BlockBreakEvent(block, sender)
server.getPluginManager().callEvent(test_event)
removing_input = False
if test_event.isCancelled():
event.setCancelled(True)
msg(sender, "&cYou are not allowed to remove this %s" % btype)
return True
inputs.pop(pos_str) # remove
save_inputs()
msg(sender, "&eSuccessfully removed this %s!" % btype)
return True
elif not changing_input:
event.setCancelled(True)
msg(sender, "&cYou cannot destroy this %s!" % btype)
msg(sender, "&c&nSneak&c and break if you want to remove it.")
return True return True
sender = event.getPlayer()
block = event.getBlock()
btype = str(block.getType()).lower()
if str(block.getType()) in accepted_inputs and not event.isCancelled():
pos_str = location_str(block)
if inputs.get(pos_str):
plugin_header(sender, "DamnSpam")
if sender.isSneaking():
# test if player is allowed to build here
removing_input = True
test_event = BlockBreakEvent(block, sender)
server.getPluginManager().callEvent(test_event)
removing_input = False
if test_event.isCancelled():
event.setCancelled(True)
msg(sender, "&cYou are not allowed to remove this %s" % btype)
return True
inputs.pop(pos_str) # remove
save_inputs()
msg(sender, "&eSuccessfully removed this %s!" % btype)
return True
elif not changing_input:
event.setCancelled(True)
msg(sender, "&cYou cannot destroy this %s!" % btype)
msg(sender, "&c&nSneak&c and break if you want to remove it.")
return True
@hook.event("player.PlayerInteractEvent", "normal") @hook.event("player.PlayerInteractEvent", "normal")
def on_interact(event): def on_interact(event):
if (str(event.getAction()) == "RIGHT_CLICK_BLOCK") and not event.isCancelled(): if (str(event.getAction()) == "RIGHT_CLICK_BLOCK") and not event.isCancelled():
sender = event.getPlayer() sender = event.getPlayer()
block = event.getClickedBlock() block = event.getClickedBlock()
btype = str(block.getType()).lower() btype = str(block.getType()).lower()
powered = (block.getData() & 0x8) == 0x8 if btype == "lever" else False # data > 7, but this is how bukkit does it powered = (block.getData() & 0x8) == 0x8 if btype == "lever" else False # data > 7, but this is how bukkit does it
pos_str = location_str(block) pos_str = location_str(block)
data = inputs.get(pos_str) data = inputs.get(pos_str)
if data: if data:
checktime = data["timeout_on"] if powered else data["timeout_off"] checktime = data["timeout_on"] if powered else data["timeout_off"]
if data["last_time"] + checktime > now(): if checktime == -1:
event.setCancelled(True) event.setCancelled(True)
plugin_header(sender, "DamnSpam") plugin_header(sender, "DamnSpam")
msg(sender, "&cThis %s has a timeout of %ss." % (btype, checktime)) msg(sender, "&cThis %s is locked permanently." % (btype))
else: elif data["last_time"] + checktime > now():
inputs[pos_str]["last_time"] = round(now(), 2) event.setCancelled(True)
plugin_header(sender, "DamnSpam")
msg(sender, "&cThis %s has a timeout of %ss." % (btype, checktime))
else:
inputs[pos_str]["last_time"] = round(now(), 2)
+129 -129
View File
@@ -18,130 +18,130 @@ whitelists = {} # {ff_owner_id: [white, listed, ids]} (Adding file usage later,
@hook.command("forcefield") @hook.command("forcefield")
def on_forcefield_command(sender, args): def on_forcefield_command(sender, args):
if not is_player(sender) or not sender.hasPermission(ff_perm): if not is_player(sender) or not sender.hasPermission(ff_perm):
noperm(sender) noperm(sender)
return True return True
if not args or args[0].upper() in ["ON", "OFF"]: # Toggle if not args or args[0].upper() in ["ON", "OFF"]: # Toggle
forcefield_toggle(sender, args[:1]) forcefield_toggle(sender, args[:1])
return True return True
args[0] = args[0].upper() # If it gets to this point, there are argument(s). args[0] = args[0].upper() # If it gets to this point, there are argument(s).
if args[0] in ["WHITELIST", "WL", "WLIST"]: # Whitelist commands if args[0] in ["WHITELIST", "WL", "WLIST"]: # Whitelist commands
if not args[1:] or args[1].upper() == "LIST": if not args[1:] or args[1].upper() == "LIST":
thread.start_new_thread(whitelist_list, (sender,)) thread.start_new_thread(whitelist_list, (sender,))
return True return True
args[1] = args[1].upper() # If it gets too this point, there is a second argument. args[1] = args[1].upper() # If it gets too this point, there is a second argument.
if args[1] == "CLEAR": if args[1] == "CLEAR":
whitelist_clear(sender) whitelist_clear(sender)
elif args[1] in ["ADD", "+"]: elif args[1] in ["ADD", "+"]:
change_whitelist(sender, True, args[2:]) change_whitelist(sender, True, args[2:])
elif args[1] in ["REMOVE", "DELETE", "REM", "DEL", "-"]: elif args[1] in ["REMOVE", "DELETE", "REM", "DEL", "-"]:
change_whitelist(sender, False, args[2:]) change_whitelist(sender, False, args[2:])
else:
forcefield_header(sender, "&cInvalid syntax. Use &e/ff ? &cfor info.")
elif args[0] in ["HELP", "?"]: # /forcefield help
forcefield_help(sender)
else: else:
forcefield_header(sender, "&cInvalid syntax. Use &e/ff ? &cfor info.") forcefield_header(sender, "&cInvalid syntax. Use &e/ff ? &cfor info.")
return True
elif args[0] in ["HELP", "?"]: # /forcefield help
forcefield_help(sender)
else:
forcefield_header(sender, "&cInvalid syntax. Use &e/ff ? &cfor info.")
return True
def change_whitelist(sender, add, names): #Add names if add == True else Remove names. def change_whitelist(sender, add, names): #Add names if add == True else Remove names.
if names: if names:
sender_id = uid(sender) sender_id = uid(sender)
if sender_id not in whitelists: if sender_id not in whitelists:
whitelists[sender_id] = [] whitelists[sender_id] = []
for name in names: for name in names:
player = server.getPlayer(name) player = server.getPlayer(name)
if player: if player:
player_id = uid(player) player_id = uid(player)
pname = player.getName() pname = player.getName()
sname = stripcolors(sender.getDisplayName()) sname = stripcolors(sender.getDisplayName())
# add player to whitelist if not already added # add player to whitelist if not already added
if add and player_id not in whitelists[sender_id]: if add and player_id not in whitelists[sender_id]:
if sender != player: if sender != player:
whitelists[sender_id].append(player_id) whitelists[sender_id].append(player_id)
forcefield_header(sender, "&bAdded &f%s &bto your forcefield whitelist." % pname) forcefield_header(sender, "&bAdded &f%s &bto your forcefield whitelist." % pname)
forcefield_header(player, "&f%s &badded you to his forcefield whitelist." % sname) forcefield_header(player, "&f%s &badded you to his forcefield whitelist." % sname)
else: else:
forcefield_header(sender, "&cYou can't whitelist yourself.") forcefield_header(sender, "&cYou can't whitelist yourself.")
# remove player from whitelist if whitelisted # remove player from whitelist if whitelisted
elif not add and player_id in whitelists[sender_id]: elif not add and player_id in whitelists[sender_id]:
whitelists[sender_id].remove(player_id) whitelists[sender_id].remove(player_id)
forcefield_header(sender, "&cRemoved &f%s &cfrom your forcefield whitelist." % pname) forcefield_header(sender, "&cRemoved &f%s &cfrom your forcefield whitelist." % pname)
forcefield_header(player, "&f%s &cremoved you from his forcefield whitelist." % sname) forcefield_header(player, "&f%s &cremoved you from his forcefield whitelist." % sname)
# player was already / not added to whitelist # player was already / not added to whitelist
else: else:
var = "already" if add == True else "not" var = "already" if add == True else "not"
forcefield_header(sender, "&f%s &cwas %s in your forcefield whitelist!" % (pname, var)) forcefield_header(sender, "&f%s &cwas %s in your forcefield whitelist!" % (pname, var))
else: else:
forcefield_header(sender, "&cplayer &f%s &cwas not found (must be online)." % name) forcefield_header(sender, "&cplayer &f%s &cwas not found (must be online)." % name)
else: else:
forcefield_header(sender, "&cGive space-separated playernames.") forcefield_header(sender, "&cGive space-separated playernames.")
def whitelist_list(player): def whitelist_list(player):
try: try:
player_id = uid(player) player_id = uid(player)
count = 0 count = 0
forcefield_header(player, "&bForcefield whitelist:") forcefield_header(player, "&bForcefield whitelist:")
for user_id in whitelists.get(player_id, []): for user_id in whitelists.get(player_id, []):
count += 1 count += 1
pname = retrieve_player(user_id).getName() pname = retrieve_player(user_id).getName()
msg(player, "&b %s. &f%s" % (count, pname)) msg(player, "&b %s. &f%s" % (count, pname))
if count == 0: if count == 0:
msg(player, "&c Your whitelist has no entries.") msg(player, "&c Your whitelist has no entries.")
except: except:
warn("Unable to finish whitelist_list process") warn("Unable to finish whitelist_list process")
def whitelist_clear(player): def whitelist_clear(player):
player_id = uid(player) player_id = uid(player)
if whitelists.get(player_id): if whitelists.get(player_id):
whitelists.pop(player_id) whitelists.pop(player_id)
forcefield_header(player, "&bForcefield whitelist cleared.") forcefield_header(player, "&bForcefield whitelist cleared.")
else: else:
forcefield_header(player, "&cYou had no players whitelisted.") forcefield_header(player, "&cYou had no players whitelisted.")
def forcefield_help(player): def forcefield_help(player):
msg(player, " ") msg(player, " ")
forcefield_header(player, "&b&l/Forcefield help: Your forcefield is %s" % ("&2&lON" if uid(player) in ff_users else "&c&lOFF")) forcefield_header(player, "&b&l/Forcefield help: Your forcefield is %s" % ("&2&lON" if uid(player) in ff_users else "&c&lOFF"))
msg(player, "&b You can use the forcefield to keep players on distance.") msg(player, "&b You can use the forcefield to keep players on distance.")
msg(player, "&b Commands:") msg(player, "&b Commands:")
msg(player, "&b 1. &6/ff &ohelp &b aliases: &6?") msg(player, "&b 1. &6/ff &ohelp &b aliases: &6?")
msg(player, "&b 2. &6/ff &o(on off)") msg(player, "&b 2. &6/ff &o(on off)")
msg(player, "&b 3. &6/ff &owhitelist (list) &b aliases: &6wlist, wl") msg(player, "&b 3. &6/ff &owhitelist (list) &b aliases: &6wlist, wl")
msg(player, "&b 4. &6/ff wl &oclear") msg(player, "&b 4. &6/ff wl &oclear")
msg(player, "&b 5. &6/ff wl &oadd <players> &b aliases: &6+") msg(player, "&b 5. &6/ff wl &oadd <players> &b aliases: &6+")
msg(player, "&b 6. &6/ff wl &oremove <players> &b aliases: &6delete, rem, del, -") msg(player, "&b 6. &6/ff wl &oremove <players> &b aliases: &6delete, rem, del, -")
msg(player, " ") msg(player, " ")
def forcefield_toggle(player, arg): # arg is a list with max 1 string def forcefield_toggle(player, arg): # arg is a list with max 1 string
player_id = uid(player) player_id = uid(player)
enabled = player_id in ff_users enabled = player_id in ff_users
argoff = arg[0].upper() == "OFF" if arg else False argoff = arg[0].upper() == "OFF" if arg else False
if enabled and (not arg or argoff): # 3 possibilities for arg: [], ["OFF"], ["ON"]. This is the most efficient way. (Case insensitive) if enabled and (not arg or argoff): # 3 possibilities for arg: [], ["OFF"], ["ON"]. This is the most efficient way. (Case insensitive)
ff_users.remove(player_id) ff_users.remove(player_id)
forcefield_header(player, "&bForcefield toggle: &c&lOFF") forcefield_header(player, "&bForcefield toggle: &c&lOFF")
elif not enabled and not argoff: elif not enabled and not argoff:
ff_users.append(player_id) ff_users.append(player_id)
forcefield_header(player, "&bForcefield toggle: &2&lON") forcefield_header(player, "&bForcefield toggle: &2&lON")
else: else:
forcefield_header(player, "&cYour forcefield is already %s!" % arg[0].lower()) forcefield_header(player, "&cYour forcefield is already %s!" % arg[0].lower())
def forcefield_header(player, message): def forcefield_header(player, message):
msg(player, "%s %s" % (ff_prefix, message)) msg(player, "%s %s" % (ff_prefix, message))
#--------------------------------------------------------------------------------------------------------# #--------------------------------------------------------------------------------------------------------#
@@ -149,41 +149,41 @@ def forcefield_header(player, message):
@hook.event("player.PlayerMoveEvent") @hook.event("player.PlayerMoveEvent")
def on_move(event): def on_move(event):
if ff_users: if ff_users:
player = event.getPlayer() player = event.getPlayer()
if is_creative(player): if is_creative(player):
player_id = uid(player) player_id = uid(player)
# moving player has forcefield, nearby player should be moved away # moving player has forcefield, nearby player should be moved away
if player_id in ff_users: if player_id in ff_users:
for entity in player.getNearbyEntities(fd, fd, fd): for entity in player.getNearbyEntities(fd, fd, fd):
whitelisted = (uid(entity) in whitelists.get(player_id, [])) whitelisted = (uid(entity) in whitelists.get(player_id, []))
if is_player(entity) and not entity.hasPermission(pass_perm) and not whitelisted: if is_player(entity) and not entity.hasPermission(pass_perm) and not whitelisted:
move_away(player, entity) move_away(player, entity)
# nearby player has forcefield, moving player should be moved away # nearby player has forcefield, moving player should be moved away
if not player.hasPermission(pass_perm): if not player.hasPermission(pass_perm):
for entity in player.getNearbyEntities(fd, fd, fd): for entity in player.getNearbyEntities(fd, fd, fd):
entity_id = uid(entity) entity_id = uid(entity)
ff_enabled = (entity_id in ff_users) ff_enabled = (entity_id in ff_users)
whitelisted = (player_id in whitelists.get(entity_id, [])) whitelisted = (player_id in whitelists.get(entity_id, []))
if is_player(entity) and is_creative(entity) and ff_enabled and not whitelisted: if is_player(entity) and is_creative(entity) and ff_enabled and not whitelisted:
move_away(entity, player) move_away(entity, player)
def move_away(player, entity): def move_away(player, entity):
# Pushes entity away from player # Pushes entity away from player
player_loc = player.getLocation() player_loc = player.getLocation()
entity_loc = entity.getLocation() entity_loc = entity.getLocation()
dx = entity_loc.getX() - player_loc.getX() dx = entity_loc.getX() - player_loc.getX()
vx = sin(Xv * dx) vx = sin(Xv * dx)
dy = entity_loc.getY() - player_loc.getY() dy = entity_loc.getY() - player_loc.getY()
vy = sin(Xv * dy) vy = sin(Xv * dy)
dz = entity_loc.getZ() - player_loc.getZ() dz = entity_loc.getZ() - player_loc.getZ()
vz = sin(Xv * dz) vz = sin(Xv * dz)
entity.setVelocity(Vector(vx , vy, vz)) entity.setVelocity(Vector(vx , vy, vz))
#--------------------------------------------------------------------------------------------------------# #--------------------------------------------------------------------------------------------------------#
@@ -191,7 +191,7 @@ def move_away(player, entity):
@hook.event("player.PlayerQuitEvent") @hook.event("player.PlayerQuitEvent")
def on_quit(event): def on_quit(event):
player = event.getPlayer() player = event.getPlayer()
player_id = uid(player) player_id = uid(player)
if player_id in ff_users: if player_id in ff_users:
ff_users.remove(player_id) ff_users.remove(player_id)
+115 -115
View File
@@ -8,153 +8,153 @@ friend_join_sound = "random.orb"
@hook.event("player.PlayerJoinEvent", "high") # creates sound and sends a bold message on friend join @hook.event("player.PlayerJoinEvent", "high") # creates sound and sends a bold message on friend join
def fjm(event): # friend join message def fjm(event): # friend join message
player = event.getPlayer() player = event.getPlayer()
player_id = uid(player) player_id = uid(player)
for onlineplayer in list(server.getOnlinePlayers()): for onlineplayer in list(server.getOnlinePlayers()):
if player_id in friends.get(uid(onlineplayer), []): if player_id in friends.get(uid(onlineplayer), []):
msg(onlineplayer, "&a&l%s &ajoined!" % player.getName()) msg(onlineplayer, "&a&l%s &ajoined!" % player.getName())
onlineplayer.playSound(onlineplayer.getLocation(), friend_join_sound, 1, 0) onlineplayer.playSound(onlineplayer.getLocation(), friend_join_sound, 1, 0)
def save_friends(): # saves to friends file def save_friends(): # saves to friends file
save_json_file("friends", friends) save_json_file("friends", friends)
def friendmessage(player, message): # sends a message with a prefix def friendmessage(player, message): # sends a message with a prefix
msg(player, "&7[&aFriends&7] " + message) msg(player, "&7[&aFriends&7] " + message)
def ls(sender): def ls(sender):
try: try:
sender_friends = friends.get(uid(sender), False) sender_friends = friends.get(uid(sender), False)
if sender_friends: if sender_friends:
friends_string = "" friends_string = ""
for uuid in sender_friends: for uuid in sender_friends:
friends_string += (retrieve_player(uuid).getName() + ", ") friends_string += (retrieve_player(uuid).getName() + ", ")
friendmessage(sender, "&aYour friends list: " + friends_string[:len(friends_string)-2]) friendmessage(sender, "&aYour friends list: " + friends_string[:len(friends_string)-2])
else: else:
friendmessage(sender, "&cYour friends list is empty") friendmessage(sender, "&cYour friends list is empty")
except: except:
warn("Unable to finish friends' ls process") warn("Unable to finish friends' ls process")
def clear(sender): def clear(sender):
sender_id = uid(sender) sender_id = uid(sender)
if friends.get(sender_id, False): if friends.get(sender_id, False):
friends.pop(sender_id) friends.pop(sender_id)
friendmessage(sender, "&aFriends list cleared") friendmessage(sender, "&aFriends list cleared")
save_friends() save_friends()
else: else:
friendmessage(sender, "&cYour friends list is already empty") friendmessage(sender, "&cYour friends list is already empty")
def add(sender, names): def add(sender, names):
sender_id = uid(sender) sender_id = uid(sender)
added = [] added = []
notfound = [] notfound = []
friendalready = [] friendalready = []
if not sender_id in friends: if not sender_id in friends:
friends[sender_id] = [] friends[sender_id] = []
for name in names: for name in names:
player = server.getPlayer(name) player = server.getPlayer(name)
if player: if player:
player_id = uid(player) player_id = uid(player)
not_yourself = player != sender not_yourself = player != sender
if not player_id in friends[sender_id]: if not player_id in friends[sender_id]:
if not_yourself: if not_yourself:
friends[sender_id].append(player_id) friends[sender_id].append(player_id)
added.append(player.getName()) added.append(player.getName())
friendmessage(player.getPlayer(), "&a&o%s &aadded you to their friends list" % stripcolors(sender.getDisplayName())) friendmessage(player.getPlayer(), "&a&o%s &aadded you to their friends list" % stripcolors(sender.getDisplayName()))
else: else:
friendalready.append(player.getName()) friendalready.append(player.getName())
else: else:
notfound.append(name) notfound.append(name)
save_friends() save_friends()
if added: if added:
friendmessage(sender, "&a&o%s&a added." % ", ".join(added)) friendmessage(sender, "&a&o%s&a added." % ", ".join(added))
if notfound: if notfound:
friendmessage(sender, "&c&o%s&c not found. (must be online)" % ", ".join(notfound)) friendmessage(sender, "&c&o%s&c not found. (must be online)" % ", ".join(notfound))
if friendalready: if friendalready:
friendmessage(sender, "&c&o%s&c is/are already your friend." % ", ".join(friendalready)) friendmessage(sender, "&c&o%s&c is/are already your friend." % ", ".join(friendalready))
if not not_yourself: if not not_yourself:
friendmessage(sender, "&cYou can't add yourself to your friends list.") friendmessage(sender, "&cYou can't add yourself to your friends list.")
def rem(sender, names): def rem(sender, names):
sender_id = uid(sender) sender_id = uid(sender)
removed = [] removed = []
notfound = [] notfound = []
notafriend = [] notafriend = []
for name in names: for name in names:
player = server.Player(name) player = server.Player(name)
if player: if player:
player_id = uid(player) player_id = uid(player)
if player_id in friends.get(sender_id, []): if player_id in friends.get(sender_id, []):
friends[sender_id].remove(player_id) friends[sender_id].remove(player_id)
removed.append(player.getName()) removed.append(player.getName())
friendmessage(player.getPlayer(), "&c&o%s &cremoved you from their friends list" % stripcolors(sender.getDisplayName())) friendmessage(player.getPlayer(), "&c&o%s &cremoved you from their friends list" % stripcolors(sender.getDisplayName()))
else: else:
notafriend.append(player.getName()) notafriend.append(player.getName())
else: else:
notfound.append(name) notfound.append(name)
save_friends() save_friends()
if removed: if removed:
friendmessage(sender, "&a&o%s&a removed." % ", ".join(removed)) friendmessage(sender, "&a&o%s&a removed." % ", ".join(removed))
if notfound: if notfound:
friendmessage(sender, "&c&o%s&c not found. (must be online)" % ", ".join(notfound)) friendmessage(sender, "&c&o%s&c not found. (must be online)" % ", ".join(notfound))
if notafriend: if notafriend:
friendmessage(sender, "&c&o%s&c is/are not in your friends list." % ", ".join(notafriend)) friendmessage(sender, "&c&o%s&c is/are not in your friends list." % ", ".join(notafriend))
def fhelp(sender): def fhelp(sender):
friendmessage(sender, "&a&l/friends help") friendmessage(sender, "&a&l/friends help")
msg(sender, "&a1. /friends &oadd <names...> &6aliases: &o+") msg(sender, "&a1. /friends &oadd <names...> &6aliases: &o+")
msg(sender, "&a2. /friends &orem <names...> &6aliases: &oremove, delete, del, -") msg(sender, "&a2. /friends &orem <names...> &6aliases: &oremove, delete, del, -")
msg(sender, "&a3. /friends &oclear &6aliases: &o/") msg(sender, "&a3. /friends &oclear &6aliases: &o/")
msg(sender, "&a4. /friends &olist &6aliases: &olst, *") msg(sender, "&a4. /friends &olist &6aliases: &olst, *")
msg(sender, "&a5. /friends &ohelp &6aliases: &o?") msg(sender, "&a5. /friends &ohelp &6aliases: &o?")
@hook.command("friends") @hook.command("friends")
def on_friend_command(sender, args): def on_friend_command(sender, args):
if not is_player(sender): if not is_player(sender):
friendmessage(sender, "&c&lYou can't have friends!") friendmessage(sender, "&c&lYou can't have friends!")
return True
cmd = args[0] if args else None
fargs = args[1:]
# /friends list
if cmd in ["list", "lst", "*"]:
thread.start_new_thread(ls, (sender,))
# /friends clear
elif cmd in ["clear", "/"]:
clear(sender)
# /friends add <names>
elif cmd in ["add", "+"]:
if fargs:
add(sender, fargs)
else:
fhelp(sender)
# /friends remove <names>
elif cmd in ["remove", "rem", "delete", "del", "-"]:
if fargs:
rem(sender, fargs)
else:
fhelp(sender)
else:
fhelp(sender)
return True return True
cmd = args[0] if args else None
fargs = args[1:]
# /friends list
if cmd in ["list", "lst", "*"]:
thread.start_new_thread(ls, (sender,))
# /friends clear
elif cmd in ["clear", "/"]:
clear(sender)
# /friends add <names>
elif cmd in ["add", "+"]:
if fargs:
add(sender, fargs)
else:
fhelp(sender)
# /friends remove <names>
elif cmd in ["remove", "rem", "delete", "del", "-"]:
if fargs:
rem(sender, fargs)
else:
fhelp(sender)
else:
fhelp(sender)
return True
+138 -145
View File
@@ -15,205 +15,198 @@ server = bukkit.Bukkit.getServer()
def info(text): def info(text):
server.getLogger().info("[RedstonerUtils] %s" % text) """
Log info to console
"""
server.getLogger().info("[RedstonerUtils] %s" % text)
def warn(text): def warn(text):
server.getLogger().warning("[RedstonerUtils] %s" % text) """
Log warning to console
"""
server.getLogger().warning("[RedstonerUtils] %s" % text)
def error(text): def error(text):
server.getLogger().severe("[RedstonerUtils] %s" % text) """
Log error to console
"""
server.getLogger().severe("[RedstonerUtils] %s" % text)
def msg(player, text, usecolor = True, basecolor = None): def msg(player, text, usecolor = True, basecolor = None):
""" """
send a message to player send a message to player
the player may be None or offline, which this method just ignores the player may be None or offline, which this method just ignores
unless usecolor is False, &-codes are translated to real color codes unless usecolor is False, &-codes are translated to real color codes
for that case, basecolor can be useful. basecolor accepts a single character as color code for that case, basecolor can be useful. basecolor accepts a single character as color code
""" """
if player and (player == server.getConsoleSender() or player.getPlayer()): # getPlayer() returns None when offline if player and (player == server.getConsoleSender() or player.getPlayer()): # getPlayer() returns None when offline
if basecolor: if basecolor:
if usecolor: if usecolor:
text = colorify(text) text = colorify(text)
player.sendMessage(colorify("&%s" % basecolor) + text) player.sendMessage(colorify("&%s" % basecolor) + text)
else: else:
player.sendMessage(colorify(text) if usecolor else text) player.sendMessage(colorify(text) if usecolor else text)
def broadcast(perm, text): def broadcast(perm, text):
""" """
better than bukkit's broadcast. better than bukkit's broadcast.
bukkit only works with permissibles that are subscribed to perm bukkit only works with permissibles that are subscribed to perm
""" """
text = colorify(text) text = colorify(text)
for recipient in list(server.getOnlinePlayers()) + [server.getConsoleSender()]: for recipient in list(server.getOnlinePlayers()) + [server.getConsoleSender()]:
if not perm or recipient.hasPermission(perm): if not perm or recipient.hasPermission(perm):
msg(recipient, text) msg(recipient, text)
def colorify(text): def colorify(text):
""" """
replace &-codes with real color codes replace &-codes with real color codes
""" """
return sub("&(?=[?\\da-fk-or])", u"\u00A7", "%s" % text) return sub("&(?=[?\\da-fk-or])", u"\u00A7", "%s" % text)
def stripcolors(text): def stripcolors(text):
""" """
strips all (real) color codes from text strips all (real) color codes from text
""" """
return sub(u"\u00A7[\\da-fk-or]", "", "%s" % text) return sub(u"\u00A7[\\da-fk-or]", "", "%s" % text)
def safetp(player, world, x, y, z, yaw = 0, pitch = 0): def safetp(player, world, x, y, z, yaw = 0, pitch = 0):
""" """
teleports the player to the given Location teleports the player to the given Location
if the player would spawn inside blocks, the location is escalated until the location is safe if the player would spawn inside blocks, the location is escalated until the location is safe
""" """
tpblock = Location(world, x, y, z).getBlock() tpblock = Location(world, x, y, z).getBlock()
if (tpblock.isEmpty() and tpblock.getRelative(bblock.BlockFace.UP).isEmpty()) or y > 255: if (tpblock.isEmpty() and tpblock.getRelative(bblock.BlockFace.UP).isEmpty()) or y > 255:
player.teleport(Location(world, x+0.5, y, z+0.5, yaw, pitch), TeleportCause.COMMAND) player.teleport(Location(world, x+0.5, y, z+0.5, yaw, pitch), TeleportCause.COMMAND)
else: else:
safetp(player, world, x, y+1, z, yaw, pitch) safetp(player, world, x, y+1, z, yaw, pitch)
def plugin_header(recipient = None, name="Redstoner Utils"): def plugin_header(recipient = None, name="Redstoner Utils"):
""" """
sends the recipient a "Plugin Header", in the format of: --=[ PluginName ]=-- sends the recipient a "Plugin Header", in the format of: --=[ PluginName ]=--
""" """
head = "\n&2--=[ %s ]=--" % name head = "\n&2--=[ %s ]=--" % name
msg(recipient, head) msg(recipient, head)
return head return head
def noperm(player): def noperm(player):
msg(player, "&cno permission") """
Send the default permission failure message to the player
"""
msg(player, "&cno permission")
def runas(player, cmd): def runas(player, cmd):
""" """
run a command as player run a command as player
the cmd should no be prefixed with a / the cmd should no be prefixed with a /
""" """
server.dispatchCommand(player, cmd) server.dispatchCommand(player, cmd)
def is_player(obj): def is_player(obj):
""" """
return True when ob is a bukkit Player return True when ob is a bukkit Player
""" """
return (isinstance(obj, Player)) return (isinstance(obj, Player))
def checkargs(sender, args, amin, amax): def checkargs(sender, args, amin, amax):
""" """
check if a command has a valid amount of args, otherwise notify the sender check if a command has a valid amount of args, otherwise notify the sender
amin is the minimum amount of args amin is the minimum amount of args
amax is the maximum amount of args amax is the maximum amount of args
if amax is < 0, infinite args will be accepted if amax is < 0, infinite args will be accepted
return True if args has a valid length, False otherwise return True if args has a valid length, False otherwise
""" """
if not (len(args) >= amin and (amax < 0 or len(args) <= amax)): if not (len(args) >= amin and (amax < 0 or len(args) <= amax)):
if amin == amax: if amin == amax:
msg(sender, "&cNeeds " + str(amin) + " arguments!") msg(sender, "&cNeeds " + str(amin) + " arguments!")
return False return False
elif amax < 0: elif amax < 0:
msg(sender, "&cNeeds at least " + str(amin) + " arguments!") msg(sender, "&cNeeds at least " + str(amin) + " arguments!")
return False return False
else: else:
msg(sender, "&cNeeds " + str(amin) + " to " + str(amax) + " arguments!") msg(sender, "&cNeeds " + str(amin) + " to " + str(amax) + " arguments!")
return False return False
return True return True
def warp(player, args, warpname):
if not checkargs(player, args, 0, 1):
return False # You can check if it worked
runas(player, "warp %s" % warpname)
return True
def is_creative(player): def is_creative(player):
""" """
returns True if the player is in Creative mode returns True if the player is in Creative mode
""" """
return str(player.getGameMode()) == "CREATIVE" return str(player.getGameMode()) == "CREATIVE"
def uid(player): def uid(player):
""" """
returns the player's UUID returns the player's UUID
""" """
return str(player.getUniqueId()) return str(player.getUniqueId())
def retrieve_player(uuid_str): def retrieve_player(uuid_str):
""" """
gets an offline player by UUID string gets an offline player by UUID string
the uuid MUST contain dashes the uuid MUST contain dashes
""" """
return server.getOfflinePlayer(juuid(uuid_str)) return server.getOfflinePlayer(juuid(uuid_str))
def known_player(player): def known_player(player):
""" """
to be used on OfflinePlayer (which can be online!) to be used on OfflinePlayer (which can be online!)
returns True if the player has been on the server returns True if the player has been on the server
this is different to HasPlayedBefore(), which will return False on first join this is different to HasPlayedBefore(), which will return False on first join
""" """
return player.getFirstPlayed() != 0 return player.hasPlayedBefore()
def open_json_file(filename, default): def open_json_file(filename, default):
""" """
opens the given json file and returns an object or returns None on error opens the given json file and returns an object or returns None on error
filename is the path + name of the file. filename is the path + name of the file.
""" """
data = None data = None
try: try:
with open("plugins/redstoner-utils.py.dir/files/%s.json" % filename) as obj: with open("plugins/redstoner-utils.py.dir/files/%s.json" % filename) as obj:
data = json_loads(obj.read()) data = json_loads(obj.read())
except Exception, e: except Exception, e:
error("Failed to read from %s: %s" % (filename, e)) error("Failed to read from %s: %s" % (filename, e))
return (default if data is None else data) return (default if data is None else data)
def save_json_file(filename, obj): def save_json_file(filename, obj):
""" """
saves the given object as json into filename saves the given object as json into filename
filename is the path + name of the file. filename is the path + name of the file.
""" """
try: try:
with open("plugins/redstoner-utils.py.dir/files/%s.json" % filename, "w") as f: with open("plugins/redstoner-utils.py.dir/files/%s.json" % filename, "w") as f:
f.write(json_dumps(obj)) f.write(json_dumps(obj))
except Exception, e: except Exception, e:
error("Failed to write to %s: %s" % (filename, e)) error("Failed to write to %s: %s" % (filename, e))
def toggle(player, ls, add = None, on = "&aToggle now on!", off = "&cToggle now off!", already = "&cToggle was already %s"): def toggle(player, ls, name = "Toggle", add = None):
""" """
Toggle presence of a player's UUID in a list (ls) Toggles presence of a player's UUID in a list
'add' controls if a player should be added(True) or removed(False) If add is given, True explicitely adds it whereas False removes it
if 'add' is None, ls will simply be toggled for that player. """
when 'add' is given, but won't change anything, %s in 'already' is replaced with "ON" or "OFF" pid = uid(player)
""" if pid in ls or add == False:
ls.remove(pid)
pid = uid(player) msg(player, "&a%s turned off!" % name)
enabled = pid in ls elif add != False:
ls.append(pid)
# Do some checks and remove pid. msg(player, "&a%s turned on!" % name)
if enabled and add == False:
ls.remove(pid)
msg(player, on)
# Do some checks and append pid.
elif not enabled and add == True:
ls.append(pid)
msg(player, off)
# Already on/off (optional)
else:
msg(player, already % (" ON" if add else " OFF"))
+27
View File
@@ -0,0 +1,27 @@
import thread
from helpers import *
from adminchat import *
imout_toggle_list = []
@hook.command("imout")
def on_imout_command(sender, args):
if sender.hasPermission("utils.imout"):
name = sender.getName()
symbol = "&a&l+"
if name in imout_toggle_list:
msg(sender, "&eWelcome back! You are no longer hidden")
msg(sender, "&6We disabled /act for you!")
if name in imout_toggle_list:
imout_toggle_list.remove(name)
if name in ac_toggle_list:
ac_toggle_list.remove(name)
else:
symbol = "&c&l-"
msg(sender, "&eYou just left... Or didn't you?")
imout_toggle_list.append(name)
if name not in ac_toggle_list:
msg(sender, "&6We enabled /act for you!")
ac_toggle_list.append(name)
broadcast(None, "%s &7%s" % (symbol, name))
+38 -38
View File
@@ -6,55 +6,55 @@ lagchunks = []
def print_help(sender): def print_help(sender):
msg(sender, " &b/lagchunks <amount> &eList chunks where #entities >= <amount>") msg(sender, " &b/lagchunks <amount> &eList chunks where #entities >= <amount>")
msg(sender, " &b/lagchunks list &eShow list again") msg(sender, " &b/lagchunks list &eShow list again")
msg(sender, " &b/lagchunks tp <num> &eTeleport to chunk <num> from list") msg(sender, " &b/lagchunks tp <num> &eTeleport to chunk <num> from list")
def scan_chunks(amount): def scan_chunks(amount):
global lagchunks global lagchunks
chunks = [] chunks = []
for world in bukkit.Bukkit.getServer().getWorlds(): for world in bukkit.Bukkit.getServer().getWorlds():
for chunk in world.getLoadedChunks(): for chunk in world.getLoadedChunks():
if len(chunk.getEntities()) >= amount: if len(chunk.getEntities()) >= amount:
ents = chunk.getEntities() ents = chunk.getEntities()
# [0]world [1]X [2]Y [3]Z [4]amount # [0]world [1]X [2]Y [3]Z [4]amount
chunks.append([chunk.getWorld(), int(ents[-1].getLocation().getX()), int(ents[0].getLocation().getY()), int(ents[0].getLocation().getZ()), len(ents)]) chunks.append([chunk.getWorld(), int(ents[-1].getLocation().getX()), int(ents[0].getLocation().getY()), int(ents[0].getLocation().getZ()), len(ents)])
chunks.sort(key = lambda entry: entry[4], reverse = True) chunks.sort(key = lambda entry: entry[4], reverse = True)
lagchunks = chunks lagchunks = chunks
def list_chunks(sender): def list_chunks(sender):
for id, chunk in enumerate(lagchunks): for id, chunk in enumerate(lagchunks):
msg(sender, "&b%s&a: (&b%s&a) %s&7, &a%s &7(%s)" % (id, chunk[4], chunk[1], chunk[3], chunk[0].getName())) msg(sender, "&b%s&a: (&b%s&a) %s&7, &a%s &7(%s)" % (id, chunk[4], chunk[1], chunk[3], chunk[0].getName()))
msg(sender, "&2------------------") msg(sender, "&2------------------")
def tp_chunk(sender, id): def tp_chunk(sender, id):
chunk = lagchunks[id] chunk = lagchunks[id]
safetp(sender, chunk[0], chunk[1], chunk[2], chunk[3]) safetp(sender, chunk[0], chunk[1], chunk[2], chunk[3])
msg(sender, "&aTeleported to &b%s&a, &b%s&a in &7%s&a with &b%s&a entities nearby." % (chunk[1], chunk[3], chunk[0].getName(), chunk[4])) msg(sender, "&aTeleported to &b%s&a, &b%s&a in &7%s&a with &b%s&a entities nearby." % (chunk[1], chunk[3], chunk[0].getName(), chunk[4]))
@hook.command("lagchunks") @hook.command("lagchunks")
def on_lagchunks_command(sender, args): def on_lagchunks_command(sender, args):
if sender.hasPermission("utils.lagchunks"): if sender.hasPermission("utils.lagchunks"):
plugin_header(sender, "Lagchunks") plugin_header(sender, "Lagchunks")
global lagchunks global lagchunks
if len(args) == 1 and args[0].isdigit() and int(args[0]) > 0: if len(args) == 1 and args[0].isdigit() and int(args[0]) > 0:
amount = args[0] amount = args[0]
msg(sender, "&aChunks with at least &b%s &aentities:" % amount, ) msg(sender, "&aChunks with at least &b%s &aentities:" % amount, )
scan_chunks(int(amount)) scan_chunks(int(amount))
list_chunks(sender) list_chunks(sender)
elif len(args) == 1 and args[0].lower() == "list": elif len(args) == 1 and args[0].lower() == "list":
list_chunks(sender) list_chunks(sender)
elif len(args) == 2 and args[0].lower() == "tp" and args[1].isdigit() and int(args[1]) <= len(lagchunks)-1: elif len(args) == 2 and args[0].lower() == "tp" and args[1].isdigit() and int(args[1]) <= len(lagchunks)-1:
if isinstance(sender, Player): if isinstance(sender, Player):
tp_chunk(sender, int(args[1])) tp_chunk(sender, int(args[1]))
else: else:
msg(sender, "&cOnly players can do this!") msg(sender, "&cOnly players can do this!")
else:
print_help(sender)
else: else:
print_help(sender) noperm(sender)
else: return True
noperm(sender)
return True
+50 -26
View File
@@ -9,48 +9,72 @@ from traceback import format_exc as print_traceback
sys.path += ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/pymodules/python2.7', '/usr/lib/pyshared/python2.7'] sys.path += ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/pymodules/python2.7', '/usr/lib/pyshared/python2.7']
try: try:
from helpers import * # Library that adds a bunch of re-usable methods which are used in nearly all other modules
from helpers import *
except: except:
print("[RedstonerUtils] ERROR: Failed to import helpers:") print("[RedstonerUtils] ERROR: Failed to import helpers:")
print(print_traceback()) print(print_traceback())
@hook.enable @hook.enable
def on_enable(): def on_enable():
info("RedstonerUtils enabled!") info("RedstonerUtils enabled!")
@hook.disable @hook.disable
def on_disable(): def on_disable():
shared["modules"]["reports"].stop_reporting() shared["modules"]["reports"].stop_reporting()
info("RedstonerUtils disabled!") info("RedstonerUtils disabled!")
info("Loading RedstonerUtils...") info("Loading RedstonerUtils...")
# Import all modules, in this order # Import all modules, in this order
shared["load_modules"] = [ shared["load_modules"] = [
"misc", # Collection of tiny utilities
"adminchat", "misc",
"lagchunks", # Adds chat for staff using /ac <text or ,<text>
"reports", "adminchat",
"chatgroups", # Adds /badge, allows to give players achievements
"webtoken", "badges",
"saylol", # Adds /calc, toggles automatic solving of Math expressions in chat
"skullclick", "calc",
"mentio", # Plugin to locate laggy chunks. /lc <n> lists chunks with more than n entities
"cycle", "lagchunks",
"motd", # Adds /report and /rp, Stores reports with time and location
"abot", "reports",
"forcefield", # Adds group-chat with /chatgroup and /cgt to toggle normal chat into group mode
"damnspam" "chatgroups",
# Adds /token, reads and writes from the database to generate pronouncable (and thus memorable) registration-tokens for the website
"webtoken",
# Adds /lol, broadcasts random funyy messages. A bit like the splash text in the menu
"saylol",
# Shows the owner of a skull when right-clicked
"skullclick",
# Adds /listen, highlights chat and plays a sound when your name was mentioned
"mentio",
# Adds /cycler, swaps the hotbar with inventory when player changes slot from right->left or left->right
"cycle",
# Adds /getmotd & /setmotd to update the motd on the fly (no reboot)
"motd",
# AnswerBot. Hides stupid questions from chat and tells the sender about /faq or the like
"abot",
# Adds '/forcefield', creates forcefield for players who want it.
"forcefield",
# Adds /damnspam, creates timeout for buttons/levers to mitigate button spam.
"damnspam",
# Adds /check, useful to lookup details about a player
"check",
# Adds /imout, displays fake leave/join messages
"imout"
# NOTICE: If you add something here, please add a small descriptive comment above!
] ]
shared["modules"] = {} shared["modules"] = {}
for module in shared["load_modules"]: for module in shared["load_modules"]:
try: try:
shared["modules"][module] = __import__(module) shared["modules"][module] = __import__(module)
info("Module %s loaded." % module) info("Module %s loaded." % module)
except: except:
error("Failed to import module %s:" % module) error("Failed to import module %s:" % module)
error(print_traceback()) error(print_traceback())
+102 -102
View File
@@ -10,140 +10,140 @@ colors_reg = reg_compile(u"\u00A7[\\da-fk-or]") # finds color codes
def saveMentions(): def saveMentions():
save_json_file("mentio", mentions) save_json_file("mentio", mentions)
@hook.event("player.AsyncPlayerChatEvent", "high") @hook.event("player.AsyncPlayerChatEvent", "high")
def onChat(event): def onChat(event):
if not event.isCancelled(): if not event.isCancelled():
sender = event.getPlayer() sender = event.getPlayer()
words = event.getMessage().split(" ") words = event.getMessage().split(" ")
recipients = event.getRecipients() # set of <Player>, may be a lazy or unmodifiable collection recipients = event.getRecipients() # set of <Player>, may be a lazy or unmodifiable collection
for recipient in list(recipients): for recipient in list(recipients):
recuid = uid(recipient) recuid = uid(recipient)
if recuid in mentions: if recuid in mentions:
keywords = mentions[uid(recipient)] keywords = mentions[uid(recipient)]
else: else:
# player # player
keywords = [recipient.getName().lower(), stripcolors(recipient.getDisplayName()).lower()] keywords = [recipient.getName().lower(), stripcolors(recipient.getDisplayName()).lower()]
rec_words = words[:] # copy rec_words = words[:] # copy
for index, word in enumerate(rec_words): for index, word in enumerate(rec_words):
isMentioned = False isMentioned = False
for keyword in keywords: for keyword in keywords:
if keyword in word.lower(): # is the keyword mentioned if keyword in word.lower(): # is the keyword mentioned
isMentioned = True isMentioned = True
if isMentioned: if isMentioned:
# join all color codes used upto this word # join all color codes used upto this word
colors = "".join(colors_reg.findall("".join(words[:index+1]))) colors = "".join(colors_reg.findall("".join(words[:index+1])))
# highlight the word containing mention, then apply all previous color codes # highlight the word containing mention, then apply all previous color codes
rec_words[index] = colorify("&r&a&o") + stripcolors(word) + colorify("&r") + colors rec_words[index] = colorify("&r&a&o") + stripcolors(word) + colorify("&r") + colors
# No need to # No need to
break break
# player was mentioned # player was mentioned
if rec_words != words: if rec_words != words:
try: try:
recipients.remove(recipient) # don't send original message recipients.remove(recipient) # don't send original message
except: except:
# list might not be mutable, ignoring. Receiver will get the message twice # list might not be mutable, ignoring. Receiver will get the message twice
pass pass
message = " ".join([sender.getDisplayName(), arrow] + rec_words) message = " ".join([sender.getDisplayName(), arrow] + rec_words)
msg(recipient, message, usecolor = False) msg(recipient, message, usecolor = False)
recipient.playSound(recipient.getLocation(), "mob.chicken.plop", 1, 2) recipient.playSound(recipient.getLocation(), "mob.chicken.plop", 1, 2)
def get_keywords(player): def get_keywords(player):
sender_id = uid(player) sender_id = uid(player)
if sender_id in mentions.keys(): if sender_id in mentions.keys():
keywords = mentions[sender_id] keywords = mentions[sender_id]
else: else:
keywords = [] keywords = []
return keywords return keywords
def add_keyword(sender, args): def add_keyword(sender, args):
keywords = get_keywords(sender) keywords = get_keywords(sender)
new_word = stripcolors(args[1].lower()) new_word = stripcolors(args[1].lower())
if len(keywords) >= max_amount: if len(keywords) >= max_amount:
msg(sender, "&cYou are already listening for %s words! Try &6/mentio del <word>" % max_amount) msg(sender, "&cYou are already listening for %s words! Try &6/mentio del <word>" % max_amount)
return True
if len(new_word) > 20:
msg(sender, "&cThis word is longer than 20 characters. Pick a shorter one!")
return True
if new_word in keywords:
msg(sender, "&cYou are already listening for this word! Try &6/mentio list")
return True
keywords.append(new_word)
if keywords:
mentions[uid(sender)] = keywords
msg(sender, "&aYou are now listening for '&2%s'!" % new_word)
saveMentions()
return True return True
if len(new_word) > 20:
msg(sender, "&cThis word is longer than 20 characters. Pick a shorter one!")
return True
if new_word in keywords:
msg(sender, "&cYou are already listening for this word! Try &6/mentio list")
return True
keywords.append(new_word)
if keywords:
mentions[uid(sender)] = keywords
msg(sender, "&aYou are now listening for '&2%s'!" % new_word)
saveMentions()
return True
def del_keyword(sender, args): def del_keyword(sender, args):
keywords = get_keywords(sender) keywords = get_keywords(sender)
del_word = stripcolors(args[1].lower()) del_word = stripcolors(args[1].lower())
if not keywords: if not keywords:
msg(sender, "&cYou are currently listening for no words! Try &6/mentio add <word>") msg(sender, "&cYou are currently listening for no words! Try &6/mentio add <word>")
return return
if del_word in keywords: if del_word in keywords:
keywords.remove(del_word) keywords.remove(del_word)
sender_id = uid(sender) sender_id = uid(sender)
if keywords: if keywords:
mentions[sender_id] = keywords mentions[sender_id] = keywords
elif sender_id in mentions: elif sender_id in mentions:
del mentions[sender_id] del mentions[sender_id]
saveMentions() saveMentions()
msg(sender, "&aYou are no longer listening for '&2%s&e'!" % del_word) msg(sender, "&aYou are no longer listening for '&2%s&e'!" % del_word)
else: else:
msg(sender, "&cWe can't remove something that doesn't exist! Try &6/mentio list") msg(sender, "&cWe can't remove something that doesn't exist! Try &6/mentio list")
def show_help(player): def show_help(player):
msg(player, "&a/mentio add <word>") msg(player, "&a/mentio add <word>")
msg(player, "&a/mentio del <word>") msg(player, "&a/mentio del <word>")
msg(player, "&a/mentio list") msg(player, "&a/mentio list")
@hook.command("mentio") @hook.command("mentio")
def onListenCommand(sender, args): def onListenCommand(sender, args):
plugin_header(sender, "Mentio") plugin_header(sender, "Mentio")
argnum = len(args) argnum = len(args)
if argnum: if argnum:
cmd = args[0].lower() cmd = args[0].lower()
# /mentio add <word> # /mentio add <word>
if argnum == 2 and cmd == "add": if argnum == 2 and cmd == "add":
add_keyword(sender, args) add_keyword(sender, args)
# /mentio del <word> # /mentio del <word>
elif argnum == 2 and cmd == "del": elif argnum == 2 and cmd == "del":
del_keyword(sender, args) del_keyword(sender, args)
# /mentio list # /mentio list
elif argnum == 1 and cmd == "list": elif argnum == 1 and cmd == "list":
msg(sender, "&aWords you're listening for:") msg(sender, "&aWords you're listening for:")
keywords = get_keywords(sender) keywords = get_keywords(sender)
for word in keywords: for word in keywords:
msg(sender, "&c- &3%s" % word) msg(sender, "&c- &3%s" % word)
if not keywords: if not keywords:
msg(sender, "&cYou are currently listening for no words! Try &6/mentio add <word>") msg(sender, "&cYou are currently listening for no words! Try &6/mentio add <word>")
else:
show_help(sender)
else: else:
show_help(sender) show_help(sender)
else: return True
show_help(sender)
return True
+152 -110
View File
@@ -5,152 +5,194 @@ from sys import exc_info
import thread import thread
import org.bukkit.inventory.ItemStack as ItemStack import org.bukkit.inventory.ItemStack as ItemStack
#
# Welcome new players
#
@hook.event("player.PlayerJoinEvent", "monitor") @hook.event("player.PlayerJoinEvent", "monitor")
def on_join(event): def on_join(event):
player = event.getPlayer() """
Welcome new players
"""
player = event.getPlayer()
# send welcome broadcast # send welcome broadcast
if not player.hasPlayedBefore(): if not player.hasPlayedBefore():
broadcast("utils.greet_new", "") broadcast("utils.greet_new", "")
broadcast("utils.greet_new", "&a&lPlease welcome &f" + player.getDisplayName() + " &a&lto Redstoner!") broadcast("utils.greet_new", "&a&lPlease welcome &f" + player.getDisplayName() + " &a&lto Redstoner!")
broadcast("utils.greet_new", "") broadcast("utils.greet_new", "")
# clear out some eventual crap before # clear out some eventual crap before
msg(player, " \n \n \n \n \n \n \n \n \n \n \n \n ") msg(player, " \n \n \n \n \n \n \n \n \n \n \n \n ")
msg(player, " &4Welcome to the Redstoner Server!") msg(player, " &4Welcome to the Redstoner Server!")
msg(player, " &6Before you ask us things, take a quick") msg(player, " &6Before you ask us things, take a quick")
msg(player, " &6look at the &a&l/FAQ &6command.") msg(player, " &6look at &a&nredstoner.com/info")
msg(player, " \n&6thank you and happy playing ;)") msg(player, " \n&6thank you and happy playing ;)")
msg(player, " \n \n") msg(player, " \n \n")
# teleport to spawn when spawning inside portal # teleport to spawn when spawning inside portal
loginloc = player.getLocation().getBlock().getType() loginloc = player.getLocation().getBlock().getType()
headloc = player.getEyeLocation().getBlock().getType() headloc = player.getEyeLocation().getBlock().getType()
if str(loginloc) == "PORTAL" or str(headloc) == "PORTAL": if str(loginloc) == "PORTAL" or str(headloc) == "PORTAL":
msg(player, "&4Looks like you spawned in a portal... Let me help you out") msg(player, "&4Looks like you spawned in a portal... Let me help you out")
msg(player, "&6You can use /back if you &nreally&6 want to go back") msg(player, "&6You can use /back if you &nreally&6 want to go back")
player.teleport(player.getWorld().getSpawnLocation()) player.teleport(player.getWorld().getSpawnLocation())
#
# /sudo - execute command/chat *as* a player/console
#
@hook.command("sudo") @hook.command("sudo")
def on_sudo_command(sender, args): def on_sudo_command(sender, args):
if sender.hasPermission("utils.sudo"): """
plugin_header(sender, "Sudo") /sudo
if not checkargs(sender, args, 2, -1): execute command/chat *as* a player/console
return True """
target = args[0] if sender.hasPermission("utils.sudo"):
plugin_header(sender, "Sudo")
if not checkargs(sender, args, 2, -1):
return True
target = args[0]
cmd = " ".join(args[1:]) cmd = " ".join(args[1:])
msg(sender, "Running '&e%s&r' as &3%s" % (cmd, target)) msg(sender, "Running '&e%s&r' as &3%s" % (cmd, target))
if cmd[0] == "/": if cmd[0] == "/":
cmd = cmd[1:] cmd = cmd[1:]
if target.lower() == "server" or target.lower() == "console": if target.lower() == "server" or target.lower() == "console":
runas(server.getConsoleSender(), cmd) runas(server.getConsoleSender(), cmd)
elif server.getPlayer(target): elif server.getPlayer(target):
runas(server.getPlayer(target), cmd) runas(server.getPlayer(target), cmd)
else: else:
msg(sender, "&cPlayer %s not found!" % target) msg(sender, "&cPlayer %s not found!" % target)
else:
if target.lower() == "server" or target.lower() == "console":
runas(server.getConsoleSender(), "say %s" % cmd)
elif server.getPlayer(target):
server.getPlayer(target).chat(cmd)
else:
msg(sender, "&cPlayer %s not found!" % target)
else: else:
if target.lower() == "server" or target.lower() == "console": noperm(sender)
runas(server.getConsoleSender(), "say %s" % cmd) return True
elif server.getPlayer(target):
server.getPlayer(target).chat(cmd)
else:
msg(sender, "&cPlayer %s not found!" % target)
else:
noperm(sender)
return True
# #@hook.command("gm")
# Clicking redstone_sheep with shears will drop redstone + wool and makes a moo sound #def on_gm_command(sender, args):
# # """
# /gm - custom gamemode command with extra perms for greater control
# """
# if not is_player(sender):
# msg(sender, "&cDerp! Can't run that from console!")
# return True
# if not checkargs(sender, args, 1, 2):
# return True
# mode = args[0]
# target = args[1]
# if target and not sender.hasPermission("utils.gm.other"):
# msg(sender, "&cYou cannot change the gamemode of another player!")
# else:
# target = sender
# if mode < 0 or mode > 3:
# msg(sender, "&cThat gamemode does not exist!")
# elif sender.hasPermission("utils.gm." % mode):
# runas(server.getConsoleSender(), "gamemode " % mode % " " % target)
# else:
# msg(sender, "&cYou cannot access that gamemode!")
# return True
last_shear = 0.0 last_shear = 0.0
@hook.event("player.PlayerInteractEntityEvent") @hook.event("player.PlayerInteractEntityEvent")
def on_player_entity_interact(event): def on_player_entity_interact(event):
global last_shear """
if not event.isCancelled(): Clicking redstone_sheep with shears will drop redstone + wool
shear_time = now() also makes a moo sound for the shearer
if last_shear + 0.4 < shear_time: """
last_shear = shear_time global last_shear
sender = event.getPlayer() if not event.isCancelled():
entity = event.getRightClicked() shear_time = now()
if is_player(entity) and uid(entity) == "ae795aa8-6327-408e-92ab-25c8a59f3ba1" and str(sender.getItemInHand().getType()) == "SHEARS" and is_creative(sender): if last_shear + 0.4 < shear_time:
for _ in range(5): last_shear = shear_time
entity.getWorld().dropItemNaturally(entity.getLocation(), ItemStack(bukkit.Material.getMaterial("REDSTONE"))) sender = event.getPlayer()
entity.getWorld().dropItemNaturally(entity.getLocation(), ItemStack(bukkit.Material.getMaterial("WOOL"))) entity = event.getRightClicked()
sender.playSound(entity.getLocation(), "mob.cow.say", 1, 1) if is_player(entity) and uid(entity) == "ae795aa8-6327-408e-92ab-25c8a59f3ba1" and str(sender.getItemInHand().getType()) == "SHEARS" and is_creative(sender):
for _ in range(5):
entity.getWorld().dropItemNaturally(entity.getLocation(), ItemStack(bukkit.Material.getMaterial("REDSTONE")))
entity.getWorld().dropItemNaturally(entity.getLocation(), ItemStack(bukkit.Material.getMaterial("WOOL")))
sender.playSound(entity.getLocation(), "mob.cow.say", 1, 1)
#
# /pluginversions - print all plugins + versions; useful when updating plugins
#
@hook.command("pluginversions") @hook.command("pluginversions")
def on_pluginversions_command(sender, args): def on_pluginversions_command(sender, args):
plugin_header(sender, "Plugin versions") """
plugins = list(server.getPluginManager().getPlugins()) /pluginversions
plugins.sort(key = lambda pl: pl.getDescription().getName()) print all plugins + versions; useful when updating plugins
msg(sender, "&3Listing all " + str(len(plugins)) + " plugins and their version:") """
for plugin in plugins: plugin_header(sender, "Plugin versions")
msg(sender, "&6" + plugin.getDescription().getName() + "&r: &e" + plugin.getDescription().getVersion()) plugins = list(server.getPluginManager().getPlugins())
return True plugins.sort(key = lambda pl: pl.getDescription().getName())
msg(sender, "&3Listing all " + str(len(plugins)) + " plugins and their version:")
for plugin in plugins:
msg(sender, "&6" + plugin.getDescription().getName() + "&r: &e" + plugin.getDescription().getVersion())
return True
#
# /echo - essentials echo sucks and prints mail alerts sometimes
#
@hook.command("echo") @hook.command("echo")
def on_echo_command(sender, args): def on_echo_command(sender, args):
msg(sender, " ".join(args).replace("\\n", "\n")) """
/echo
essentials echo sucks and prints mail alerts sometimes
"""
msg(sender, " ".join(args).replace("\\n", "\n"))
#
# /pyeval - run python ingame
#
# has to be in main.py so we can access the modules
def eval_thread(sender, code): def eval_thread(sender, code):
try: """
result = eval(code) /pyeval
msg(sender, ">>> %s: %s" % (colorify("&3") + type(result).__name__, colorify("&a") + unicode(result) + "\n "), usecolor = False) run python ingame
except: """
e = exc_info()[1]
try: try:
eclass = e.__class__ result = eval(code)
except AttributeError: msg(sender, ">>> %s: %s" % (colorify("&3") + type(result).__name__, colorify("&a") + unicode(result) + "\n "), usecolor = False)
eclass = type(e) except:
msg(sender, ">>> %s: %s" % (eclass.__name__, e) + "\n ", False, "c") e = exc_info()[1]
thread.exit() try:
eclass = e.__class__
except AttributeError:
eclass = type(e)
msg(sender, ">>> %s: %s" % (eclass.__name__, e) + "\n ", False, "c")
thread.exit()
@hook.command("pyeval") @hook.command("pyeval")
def on_pyeval_command(sender, args): def on_pyeval_command(sender, args):
if sender.hasPermission("utils.pyeval"): """
if not checkargs(sender, args, 1, -1): /pyeval
return True run python code ingame
msg(sender, "%s" % " ".join(args), False, "e") """
thread.start_new_thread(eval_thread, (sender, " ".join(args))) if sender.hasPermission("utils.pyeval"):
else: if not checkargs(sender, args, 1, -1):
noperm(sender) return True
return True msg(sender, "%s" % " ".join(args), False, "e")
thread.start_new_thread(eval_thread, (sender, " ".join(args)))
else:
noperm(sender)
return True
@hook.command("modules") @hook.command("modules")
def on_modules_command(sender, args): def on_modules_command(sender, args):
plugin_header(sender, "Modules") """
for mod in shared["load_modules"]: /modules
color = "a" if mod in shared["modules"] else "c" list all modules, unloaded modules in red
msg(sender, "&" + color + mod) """
plugin_header(sender, "Modules")
for mod in shared["load_modules"]:
color = "a" if mod in shared["modules"] else "c"
msg(sender, "&" + color + mod)
@hook.event("player.PlayerTeleportEvent")
def on_player_teleport(event):
"""
Disable spectator teleportation
"""
player = event.getPlayer()
if not event.isCancelled() and str(event.getCause()) == "SPECTATE" and not player.hasPermission("utils.tp.spectate"):
event.setCancelled(True)
msg(event.getPlayer(), "&cSpectator teleportation is disabled")
+16 -16
View File
@@ -6,30 +6,30 @@ motd = default_motd
@hook.command("getmotd") @hook.command("getmotd")
def on_getmotd_command(sender, args): def on_getmotd_command(sender, args):
plugin_header(sender, "MOTD") plugin_header(sender, "MOTD")
msg(sender, motd, usecolor = False) msg(sender, motd, usecolor = False)
@hook.command("setmotd") @hook.command("setmotd")
def on_setmotd_command(sender, args): def on_setmotd_command(sender, args):
global motd global motd
if sender.hasPermission("utils.setmotd"): if sender.hasPermission("utils.setmotd"):
if not checkargs(sender, args, 1, -1): if not checkargs(sender, args, 1, -1):
return True return True
motd = colorify(" ".join(args).replace("\\n", "\n")) motd = colorify(" ".join(args).replace("\\n", "\n"))
if motd == "--reset": if motd == "--reset":
motd = default_motd motd = default_motd
broadcast(None, plugin_header(name="MOTD")) broadcast(None, plugin_header(name="MOTD"))
broadcast(None, "&aNew MOTD:&r\n%s" % motd) broadcast(None, "&aNew MOTD:&r\n%s" % motd)
broadcast(None, " ") broadcast(None, " ")
else: else:
noperm(sender) noperm(sender)
return True return True
@hook.event("server.ServerListPingEvent") @hook.event("server.ServerListPingEvent")
def on_server_ping(event): def on_server_ping(event):
event.setMotd(motd) event.setMotd(motd)
+5
View File
@@ -1,4 +1,9 @@
#pylint: disable = F0401 #pylint: disable = F0401
"""
A library that makes use of the so called ClassPathHack for jython
to allow proper loading of mysql-connector.jar at runtime.
Import only, no methods.
"""
import java.lang.reflect.Method import java.lang.reflect.Method
import java.io.File import java.io.File
import java.net.URL import java.net.URL
+9 -7
View File
@@ -1,7 +1,9 @@
#!/usr/bin/python #!/usr/bin/python
# this was going to be a PlotMe-like plugin "plotter" """
# but it seems like PlotMe is still beeing developed, so we don't need our own. *Very basic* start of a custom plot-plugin like PlotMe
on hold because the PlotMe developer continued to develop PlotMe
"""
import sys import sys
@@ -10,15 +12,15 @@ z_plot_size = 3
padding = 1 padding = 1
def base_coords(x, z): def base_coords(x, z):
pid = plot_id(x, z) pid = plot_id(x, z)
return [pid[0] * (x_plot_size + padding), pid[1] * (z_plot_size + padding)] return [pid[0] * (x_plot_size + padding), pid[1] * (z_plot_size + padding)]
def bounds(x, z): def bounds(x, z):
base = base_coords(x, z) base = base_coords(x, z)
return [base, [base[0] + x_plot_size, base[1] + z_plot_size]] return [base, [base[0] + x_plot_size, base[1] + z_plot_size]]
def plot_id(x, z): def plot_id(x, z):
return [x // (x_plot_size + padding), z // (z_plot_size + padding)] return [x // (x_plot_size + padding), z // (z_plot_size + padding)]
x = int(sys.argv[1]) x = int(sys.argv[1])
+93 -93
View File
@@ -12,128 +12,128 @@ rp_permission = "utils.rp"
def print_help(sender): def print_help(sender):
msg(sender, " &2/report <text> &eReport something") msg(sender, " &2/report <text> &eReport something")
msg(sender, " &2/rp list &eList unresolved reports (id, player, text)") msg(sender, " &2/rp list &eList unresolved reports (id, player, text)")
msg(sender, " &2/rp tp <id> &eTeleport to report's location & show details") msg(sender, " &2/rp tp <id> &eTeleport to report's location & show details")
msg(sender, " &2/rp del <id> &eResolve a report") msg(sender, " &2/rp del <id> &eResolve a report")
def print_list(sender): def print_list(sender):
try: # new thread, anything can happen. try: # new thread, anything can happen.
msg(sender, "&a" + str(len(reports)) + " reports:") msg(sender, "&a" + str(len(reports)) + " reports:")
for i, report in enumerate(reports): for i, report in enumerate(reports):
name = retrieve_player(report["uuid"]).getName() name = retrieve_player(report["uuid"]).getName()
msg(sender, "&8[&e%s &c%s&8] &3%s&f: &a%s" % (i, report["time"], name, report["msg"])) msg(sender, "&8[&e%s &c%s&8] &3%s&f: &a%s" % (i, report["time"], name, report["msg"]))
except: except:
warn("Failed to complete report's print_list() thread") warn("Failed to complete report's print_list() thread")
def tp_report(sender, rep_id): def tp_report(sender, rep_id):
if rep_id >= len(reports) or rep_id < 0: if rep_id >= len(reports) or rep_id < 0:
msg(sender, "&cReport &3#" + str(rep_id) + "&c does not exist!") msg(sender, "&cReport &3#" + str(rep_id) + "&c does not exist!")
return True return True
else: else:
report = reports[rep_id] report = reports[rep_id]
safetp(sender, server.getWorld(report["world"]), report["x"], report["y"], report["z"], report["yaw"], report["pitch"]) safetp(sender, server.getWorld(report["world"]), report["x"], report["y"], report["z"], report["yaw"], report["pitch"])
msg(sender, "&aTeleported to report #%s" % rep_id ) msg(sender, "&aTeleported to report #%s" % rep_id )
def delete_report(sender, rep_id): def delete_report(sender, rep_id):
if len(reports) > rep_id >= 0: if len(reports) > rep_id >= 0:
report = reports[rep_id] report = reports[rep_id]
reports.pop(rep_id) reports.pop(rep_id)
save_reports() save_reports()
msg(sender, "&aReport #%s deleted." % rep_id) msg(sender, "&aReport #%s deleted." % rep_id)
reporter = server.getOfflinePlayer(juuid(report["uuid"])) reporter = server.getOfflinePlayer(juuid(report["uuid"]))
plugin_header(reporter, "Report") plugin_header(reporter, "Report")
msg(reporter, "&aReport '&e%s&a' was resolved by %s." % (report["msg"], sender.getName())) msg(reporter, "&aReport '&e%s&a' was resolved by %s." % (report["msg"], sender.getName()))
else: else:
msg(sender, "&cThat report does not exist!") msg(sender, "&cThat report does not exist!")
def save_reports(): def save_reports():
save_json_file("reports", reports) save_json_file("reports", reports)
@hook.command("rp") @hook.command("rp")
def on_rp_command(sender, args): def on_rp_command(sender, args):
if sender.hasPermission(rp_permission): if sender.hasPermission(rp_permission):
plugin_header(sender, "Reports") plugin_header(sender, "Reports")
if len(args) > 0: if len(args) > 0:
if args[0] == "list": if args[0] == "list":
# needs to run in seperate thread because of getOfflinePlayer # needs to run in seperate thread because of getOfflinePlayer
thread.start_new_thread(print_list, (sender,)) thread.start_new_thread(print_list, (sender,))
else: else:
if not checkargs(sender, args, 2, 2): if not checkargs(sender, args, 2, 2):
return True return True
try: try:
repid = int(args[1]) repid = int(args[1])
except ValueError: except ValueError:
msg(sender, "&cDoesn't look like &3" + args[1] + "&c is a valid number!") msg(sender, "&cDoesn't look like &3" + args[1] + "&c is a valid number!")
print_help(sender) print_help(sender)
return True return True
if args[0] == "tp": if args[0] == "tp":
if not is_player(sender): if not is_player(sender):
msg(sender, "&conly players can do this") msg(sender, "&conly players can do this")
return True return True
tp_report(sender, repid) tp_report(sender, repid)
elif args[0] == "del": elif args[0] == "del":
delete_report(sender, repid) delete_report(sender, repid)
else:
print_help(sender)
else: else:
print_help(sender) print_help(sender)
else: else:
print_help(sender) noperm(sender)
else: return True
noperm(sender)
return True
@hook.command("report") @hook.command("report")
def on_report_command(sender, args): def on_report_command(sender, args):
plugin_header(sender, "Report") plugin_header(sender, "Report")
if not is_player(sender): if not is_player(sender):
msg(sender, "&conly players can do this") msg(sender, "&conly players can do this")
return True
if not checkargs(sender, args, 1, -1):
return True
text = " ".join(args)
loc = sender.getLocation()
reporter = sender.name
reporter_id = uid(sender)
report = {
"uuid": reporter_id,
"msg": text,
"x": int(loc.x),
"y": int(loc.y),
"z": int(loc.z),
"yaw": int(loc.yaw),
"pitch": int(loc.pitch),
"world": loc.getWorld().name,
"time": time.strftime(time_format)
}
reports.append(report)
save_reports()
broadcast(rp_permission, "&aReport #" + str(len(reports) -1) + ": " + reporter + "&f: " + text)
msg(sender, "&aReported \"&e" + text + "&a\"")
return True return True
if not checkargs(sender, args, 1, -1):
return True
text = " ".join(args)
loc = sender.getLocation()
reporter = sender.name
reporter_id = uid(sender)
report = {
"uuid": reporter_id,
"msg": text,
"x": int(loc.x),
"y": int(loc.y),
"z": int(loc.z),
"yaw": int(loc.yaw),
"pitch": int(loc.pitch),
"world": loc.getWorld().name,
"time": time.strftime(time_format)
}
reports.append(report)
save_reports()
broadcast(rp_permission, "&aReport #" + str(len(reports) -1) + ": " + reporter + "&f: " + text)
msg(sender, "&aReported \"&e" + text + "&a\"")
return True
def reports_reminder(): # needs 2 args for unknown reason def reports_reminder(): # needs 2 args for unknown reason
while True: while True:
for i in range(0, check_delay*2): for i in range(0, check_delay*2):
time.sleep(0.5) # check every 0.5 seconds if we should kill the thread time.sleep(0.5) # check every 0.5 seconds if we should kill the thread
if not check_reports: if not check_reports:
info("Reports reminder thread killed.") info("Reports reminder thread killed.")
thread.exit() thread.exit()
if len(reports) > 0: if len(reports) > 0:
broadcast(rp_permission, "&2--=[ Reports ]=--") broadcast(rp_permission, "&2--=[ Reports ]=--")
broadcast(rp_permission, "&aThere are %s pending reports!" % len(reports)) broadcast(rp_permission, "&aThere are %s pending reports!" % len(reports))
def stop_reporting(): def stop_reporting():
global check_reports global check_reports
info("Ending reports reminder thread") info("Ending reports reminder thread")
check_reports = False check_reports = False
thread.start_new_thread(reports_reminder, ()) thread.start_new_thread(reports_reminder, ())
+73 -73
View File
@@ -9,95 +9,95 @@ last_msg = 0
def save_lols(): def save_lols():
save_json_file("lol", lols) save_json_file("lol", lols)
def add_lol(txt): def add_lol(txt):
lols.append(txt) lols.append(txt)
save_lols() save_lols()
def del_lol(lid): def del_lol(lid):
lols.pop(lid) lols.pop(lid)
save_lols() save_lols()
def print_lol(sender, lid): def print_lol(sender, lid):
global last_msg global last_msg
if time() - last_msg > timeout: if time() - last_msg > timeout:
if len(lols) > lid: if len(lols) > lid:
dispname = sender.getDisplayName() if is_player(sender) else sender.getName() dispname = sender.getDisplayName() if is_player(sender) else sender.getName()
broadcast(None, "&8[&blol&8] &7%s&8: &e%s" % (dispname, lols[lid])) broadcast(None, "&8[&blol&8] &7%s&8: &e%s" % (dispname, lols[lid]))
last_msg = time() last_msg = time()
else:
msg(sender, "&cInvalid id")
else: else:
msg(sender, "&cInvalid id") msg(sender, "&cYou can use SayLol again in &a%s seconds!" % int(timeout + 1 - (time() - last_msg)))
else:
msg(sender, "&cYou can use SayLol again in &a%s seconds!" % int(timeout + 1 - (time() - last_msg)))
def search_lols(sender, keyword): def search_lols(sender, keyword):
if not keyword: if not keyword:
msg(sender, "&cPlease provide a keyword to search for!") msg(sender, "&cPlease provide a keyword to search for!")
return return
keyword = keyword.lower() keyword = keyword.lower()
msg(sender, "&aLols containing '&6%s&a':" % keyword) msg(sender, "&aLols containing '&6%s&a':" % keyword)
for i, lol in enumerate(lols): for i, lol in enumerate(lols):
if keyword in lol.lower(): if keyword in lol.lower():
msg(sender, "&a%s: &e%s" % (str(i).rjust(3), lol)) msg(sender, "&a%s: &e%s" % (str(i).rjust(3), lol))
msg(sender, "") # empty line showing end of list msg(sender, "") # empty line showing end of list
@hook.command("lol") @hook.command("lol")
def on_lol_command(sender, args): def on_lol_command(sender, args):
plugin_header(sender, "SayLol") plugin_header(sender, "SayLol")
cmd = args[0] if len(args) > 0 else None
if len(args) == 0:
if sender.hasPermission("utils.lol"):
print_lol(sender, randrange(len(lols)))
else:
noperm(sender)
elif cmd == "id":
if sender.hasPermission("utils.lol.id"):
try:
i = int(args[1])
print_lol(sender, i)
except ValueError:
msg(sender, "&cInvalid number '&e%s&c'" % args[1])
else:
noperm(sender)
elif cmd == "list":
for i in range(len(lols)):
msg(sender, "&a%s: &e%s" % (str(i).rjust(3), lols[i]))
elif cmd == "search":
if sender.hasPermission("utils.lol.search"):
search_lols(sender, " ".join(args[1:]))
else:
noperm(sender)
elif cmd == "add":
if sender.hasPermission("utils.lol.modify"):
add_lol(" ".join(args[1:]))
msg(sender, "&aNew lol message added!")
else:
noperm(sender)
elif cmd == "del":
if sender.hasPermission("utils.lol.modify"):
try:
i = int(args[1])
del_lol(i)
msg(sender, "&aLol message &e#%s&a deleted!" % i)
except ValueError:
msg(sender, "&cInvalid number '&e%s&c'" % args[1])
cmd = args[0] if len(args) > 0 else None
if len(args) == 0:
if sender.hasPermission("utils.lol"):
print_lol(sender, randrange(len(lols)))
else: else:
noperm(sender) msg(sender, "&a/lol &eSay random message")
msg(sender, "&a/lol list &eList all messages")
elif cmd == "id": msg(sender, "&a/lol id <id> &eSay specific message")
if sender.hasPermission("utils.lol.id"): msg(sender, "&a/lol add <text> &eAdd message")
try: msg(sender, "&a/lol del <id> &eDelete message")
i = int(args[1]) return True
print_lol(sender, i)
except ValueError:
msg(sender, "&cInvalid number '&e%s&c'" % args[1])
else:
noperm(sender)
elif cmd == "list":
for i in range(len(lols)):
msg(sender, "&a%s: &e%s" % (str(i).rjust(3), lols[i]))
elif cmd == "search":
if sender.hasPermission("utils.lol.search"):
search_lols(sender, " ".join(args[1:]))
else:
noperm(sender)
elif cmd == "add":
if sender.hasPermission("utils.lol.modify"):
add_lol(" ".join(args[1:]))
msg(sender, "&aNew lol message added!")
else:
noperm(sender)
elif cmd == "del":
if sender.hasPermission("utils.lol.modify"):
try:
i = int(args[1])
del_lol(i)
msg(sender, "&aLol message &e#%s&a deleted!" % i)
except ValueError:
msg(sender, "&cInvalid number '&e%s&c'" % args[1])
else:
msg(sender, "&a/lol &eSay random message")
msg(sender, "&a/lol list &eList all messages")
msg(sender, "&a/lol id <id> &eSay specific message")
msg(sender, "&a/lol add <text> &eAdd message")
msg(sender, "&a/lol del <id> &eDelete message")
return True
+3
View File
@@ -0,0 +1,3 @@
mysql_database = "jdbc:mysql://localhost/database"
mysql_user = "username"
mysql_pass = "secret"
+10 -10
View File
@@ -4,13 +4,13 @@ from helpers import msg
@hook.event("player.PlayerInteractEvent", "monitor") @hook.event("player.PlayerInteractEvent", "monitor")
def on_block_interact(event): def on_block_interact(event):
if (str(event.getAction()) == "RIGHT_CLICK_BLOCK"): if (str(event.getAction()) == "RIGHT_CLICK_BLOCK"):
sender = event.getPlayer() sender = event.getPlayer()
block = event.getClickedBlock().getState() block = event.getClickedBlock().getState()
if (isinstance(block, bukkit.block.Skull) and not event.isCancelled()): if (isinstance(block, bukkit.block.Skull) and not event.isCancelled()):
owner = block.getOwner() owner = block.getOwner()
if (owner): if (owner):
msg(sender, "&eThat's %s." % owner) msg(sender, "&eThat's %s." % owner)
else: else:
msg(sender, "&cThis skull has no name (Steve)") msg(sender, "&cThis skull has no name (Steve)")
event.setCancelled(True) event.setCancelled(True)
+42 -36
View File
@@ -1,3 +1,9 @@
"""
Code that was used once to create this awesome screenshot
- https://i.imgur.com/v4wg5kl.png
- https://i.imgur.com/tIZ3jmC.png
- https://www.reddit.com/r/Minecraft/comments/28le52/screenshot_of_all_players_that_joined_my_server/
"""
import net.minecraft.server.v1_7_R1.EntityPlayer as EntityPlayer import net.minecraft.server.v1_7_R1.EntityPlayer as EntityPlayer
import net.minecraft.server.v1_7_R1.PacketPlayOutNamedEntitySpawn as PacketPlayOutNamedEntitySpawn import net.minecraft.server.v1_7_R1.PacketPlayOutNamedEntitySpawn as PacketPlayOutNamedEntitySpawn
import net.minecraft.server.v1_7_R1.PlayerInteractManager as PlayerInteractManager import net.minecraft.server.v1_7_R1.PlayerInteractManager as PlayerInteractManager
@@ -18,45 +24,45 @@ upmul = 0.95 # multiplicate with goup each row
def spawn(dispname, sender, x, y, z): def spawn(dispname, sender, x, y, z):
""" """
Sends the actual player to sender Sends the actual player to sender
""" """
server = bukkit.getServer().getServer() server = bukkit.getServer().getServer()
world = server.getWorldServer(0) # main world world = server.getWorldServer(0) # main world
profile = GameProfile(dispname, dispname) # set player details profile = GameProfile(dispname, dispname) # set player details
manager = PlayerInteractManager(world) manager = PlayerInteractManager(world)
entity = EntityPlayer(server, world, profile, manager) # create Player's entity entity = EntityPlayer(server, world, profile, manager) # create Player's entity
entity.setPosition(x, y, z) entity.setPosition(x, y, z)
packet = PacketPlayOutNamedEntitySpawn(entity) # create packet for entity spawn packet = PacketPlayOutNamedEntitySpawn(entity) # create packet for entity spawn
sender.getHandle().playerConnection.sendPacket(packet) # send packet sender.getHandle().playerConnection.sendPacket(packet) # send packet
@hook.command("spawnplayer") @hook.command("spawnplayer")
def on_spawnplayer_command(sender, args): def on_spawnplayer_command(sender, args):
global amount, row, ground, goup global amount, row, ground, goup
# X and Z position # X and Z position
xpos = sender.getLocation().add(-float(row-1 * shift + (amount * margin) / 2), 0, 0).getX() xpos = sender.getLocation().add(-float(row-1 * shift + (amount * margin) / 2), 0, 0).getX()
row = sender.getLocation().add(0, 0, -row).getZ() row = sender.getLocation().add(0, 0, -row).getZ()
count = 0 count = 0
stop = False stop = False
while not stop: while not stop:
for i in range(amount): for i in range(amount):
player = players[count] player = players[count]
x = int(xpos + i*margin) x = int(xpos + i*margin)
spawn(player, sender, x, ground, row) spawn(player, sender, x, ground, row)
print(player, x, ground, row) print(player, x, ground, row)
count += 1 count += 1
if count >= len(players): if count >= len(players):
stop = True stop = True
print "breaking" print "breaking"
break break
print("next row") print("next row")
row -= 1 # next row (-z) row -= 1 # next row (-z)
xpos -= shift # shift left xpos -= shift # shift left
amount += int(shift*margin*2) # add players left and right amount += int(shift*margin*2) # add players left and right
if abs(row) % int(goup) == 0: if abs(row) % int(goup) == 0:
goup *= upmul goup *= upmul
ground += 1 ground += 1
print "Going up by 1: %s" % ground print "Going up by 1: %s" % ground
+97 -94
View File
@@ -1,4 +1,7 @@
#pylint: disable = F0401 #pylint: disable = F0401
"""
A plugin that automatically tiles (stacks) blocks inside a selected region in configurable directions.
"""
import org.bukkit.event.block.BlockPlaceEvent as BlockPlaceEvent import org.bukkit.event.block.BlockPlaceEvent as BlockPlaceEvent
import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
import org.bukkit.event.player.PlayerInteractEvent as PlayerInteractEvent import org.bukkit.event.player.PlayerInteractEvent as PlayerInteractEvent
@@ -9,13 +12,13 @@ from helpers import *
tilehelpers = open_json_file("tilehelpers", []) tilehelpers = open_json_file("tilehelpers", [])
dirmap = { dirmap = {
# [x, y, z] # [x, y, z]
"n": [0, 0, -1], "n": [0, 0, -1],
"e": [+1, 0, 0], "e": [+1, 0, 0],
"s": [0, 0, +1], "s": [0, 0, +1],
"w": [-1, 0, 0], "w": [-1, 0, 0],
"u": [0, +1, 0], "u": [0, +1, 0],
"d": [0, -1, 0] "d": [0, -1, 0]
} }
# FIXME: disallow multiple regions by single person. # FIXME: disallow multiple regions by single person.
@@ -24,111 +27,111 @@ dirmap = {
@hook.event("block.BlockPlaceEvent", "low") @hook.event("block.BlockPlaceEvent", "low")
def on_place_block(event): def on_place_block(event):
if not event.isCancelled(): if not event.isCancelled():
player = event.getPlayer() player = event.getPlayer()
block = event.getBlockPlaced() block = event.getBlockPlaced()
for th in tilehelpers: for th in tilehelpers:
area = th.get("area") area = th.get("area")
if th.get("owner") == uid(player) and str(block.getWorld().getUID()) == th.get("world") and block.getX() in range(area[0][0], area[0][1]+1) and block.getY() in range(area[1][0], area[1][1]+1) and block.getZ() in range(area[2][0], area[2][1]+1) and event.canBuild(): if th.get("owner") == uid(player) and str(block.getWorld().getUID()) == th.get("world") and block.getX() in range(area[0][0], area[0][1]+1) and block.getY() in range(area[1][0], area[1][1]+1) and block.getZ() in range(area[2][0], area[2][1]+1) and event.canBuild():
# stack block in directions # stack block in directions
for direction in th.get("directions"): for direction in th.get("directions"):
directions = dirmap[direction] directions = dirmap[direction]
size = [ size = [
1 + abs(area[0][1] - area[0][0]), 1 + abs(area[0][1] - area[0][0]),
1 + abs(area[1][1] - area[1][0]), 1 + abs(area[1][1] - area[1][0]),
1 + abs(area[2][1] - area[2][0]) 1 + abs(area[2][1] - area[2][0])
] ]
against = event.getBlockAgainst() against = event.getBlockAgainst()
newblock = block.getWorld().getBlockAt( newblock = block.getWorld().getBlockAt(
block.getX() + size[0] * directions[0], block.getX() + size[0] * directions[0],
block.getY() + size[1] * directions[1], block.getY() + size[1] * directions[1],
block.getZ() + size[2] * directions[2] block.getZ() + size[2] * directions[2]
) )
newagainst = against.getWorld().getBlockAt( newagainst = against.getWorld().getBlockAt(
against.getX() + size[0] * directions[0], against.getX() + size[0] * directions[0],
against.getY() + size[1] * directions[1], against.getY() + size[1] * directions[1],
against.getZ() + size[2] * directions[2] against.getZ() + size[2] * directions[2]
) )
newstate = newblock.getState() newstate = newblock.getState()
newstate.setType(block.getType()) newstate.setType(block.getType())
newstate.setData(block.getState().getData()) newstate.setData(block.getState().getData())
event = BlockPlaceEvent(newstate.getBlock(), newblock.getState(), newagainst, event.getItemInHand(), player, event.canBuild()) event = BlockPlaceEvent(newstate.getBlock(), newblock.getState(), newagainst, event.getItemInHand(), player, event.canBuild())
server.getPluginManager().callEvent(event) server.getPluginManager().callEvent(event)
if not event.isCancelled(): if not event.isCancelled():
newblock.setType(block.getType()) newblock.setType(block.getType())
newblock.setData(block.getData()) newblock.setData(block.getData())
@hook.event("block.BlockBreakEvent", "low") @hook.event("block.BlockBreakEvent", "low")
def on_break_block(event): def on_break_block(event):
if not event.isCancelled(): if not event.isCancelled():
player = event.getPlayer() player = event.getPlayer()
block = event.getBlock() block = event.getBlock()
for th in tilehelpers: for th in tilehelpers:
area = th.get("area") area = th.get("area")
if th.get("owner") == uid(player) and str(block.getWorld().getUID()) == th.get("world") and block.getX() in range(area[0][0], area[0][1]+1) and block.getY() in range(area[1][0], area[1][1]+1) and block.getZ() in range(area[2][0], area[2][1]+1): if th.get("owner") == uid(player) and str(block.getWorld().getUID()) == th.get("world") and block.getX() in range(area[0][0], area[0][1]+1) and block.getY() in range(area[1][0], area[1][1]+1) and block.getZ() in range(area[2][0], area[2][1]+1):
# stack block in directions # stack block in directions
for direction in th.get("directions"): for direction in th.get("directions"):
directions = dirmap[direction] directions = dirmap[direction]
size = [ size = [
1 + abs(area[0][1] - area[0][0]), 1 + abs(area[0][1] - area[0][0]),
1 + abs(area[1][1] - area[1][0]), 1 + abs(area[1][1] - area[1][0]),
1 + abs(area[2][1] - area[2][0]) 1 + abs(area[2][1] - area[2][0])
] ]
newblock = block.getWorld().getBlockAt( newblock = block.getWorld().getBlockAt(
block.getX() + size[0] * directions[0], block.getX() + size[0] * directions[0],
block.getY() + size[1] * directions[1], block.getY() + size[1] * directions[1],
block.getZ() + size[2] * directions[2] block.getZ() + size[2] * directions[2]
) )
event = BlockBreakEvent(newblock, player) event = BlockBreakEvent(newblock, player)
server.getPluginManager().callEvent(event) server.getPluginManager().callEvent(event)
if not event.isCancelled(): if not event.isCancelled():
newblock.setTypeId(0) newblock.setTypeId(0)
@hook.event("player.PlayerInteractEvent", "low") @hook.event("player.PlayerInteractEvent", "low")
def on_block_interact(event): def on_block_interact(event):
action = event.getAction() action = event.getAction()
if not event.isCancelled() and str(action) == "RIGHT_CLICK_BLOCK": if not event.isCancelled() and str(action) == "RIGHT_CLICK_BLOCK":
player = event.getPlayer() player = event.getPlayer()
block = event.getClickedBlock() block = event.getClickedBlock()
for th in tilehelpers: for th in tilehelpers:
area = th.get("area") area = th.get("area")
if th.get("owner") == uid(player) and str(block.getWorld().getUID()) == th.get("world") and block.getX() in range(area[0][0], area[0][1]+1) and block.getY() in range(area[1][0], area[1][1]+1) and block.getZ() in range(area[2][0], area[2][1]+1): if th.get("owner") == uid(player) and str(block.getWorld().getUID()) == th.get("world") and block.getX() in range(area[0][0], area[0][1]+1) and block.getY() in range(area[1][0], area[1][1]+1) and block.getZ() in range(area[2][0], area[2][1]+1):
# stack block in directions # stack block in directions
for direction in th.get("directions"): for direction in th.get("directions"):
directions = dirmap[direction] directions = dirmap[direction]
size = [ size = [
1 + abs(area[0][1] - area[0][0]), 1 + abs(area[0][1] - area[0][0]),
1 + abs(area[1][1] - area[1][0]), 1 + abs(area[1][1] - area[1][0]),
1 + abs(area[2][1] - area[2][0]) 1 + abs(area[2][1] - area[2][0])
] ]
newblock = block.getWorld().getBlockAt( newblock = block.getWorld().getBlockAt(
block.getX() + size[0] * directions[0], block.getX() + size[0] * directions[0],
block.getY() + size[1] * directions[1], block.getY() + size[1] * directions[1],
block.getZ() + size[2] * directions[2] block.getZ() + size[2] * directions[2]
) )
event = PlayerInteractEvent(event.getPlayer(), action, event.getItem(), newblock, event.getBlockFace()) event = PlayerInteractEvent(event.getPlayer(), action, event.getItem(), newblock, event.getBlockFace())
server.getPluginManager().callEvent(event) server.getPluginManager().callEvent(event)
if not event.isCancelled(): if not event.isCancelled():
# FIXME: do not use bukkit API calls outside main thread # FIXME: do not use bukkit API calls outside main thread
thread.start_new_thread(update_block, (block, newblock)) thread.start_new_thread(update_block, (block, newblock))
def update_block(block, newblock): def update_block(block, newblock):
try: # we're in a thread, the universe may hace collapsed in another thread try: # we're in a thread, the universe may hace collapsed in another thread
sleep(0.2) sleep(0.2)
newblock.setType(block.getType()) newblock.setType(block.getType())
newblock.setData(block.getData()) newblock.setData(block.getData())
except Exception, e: except Exception, e:
error("Failed to update %s block in %s at %s,%s,%s: '%s'" % (str(block.getType()), block.getWorld().getName(), block.getX(), block.getY(), block.getZ(), e)) error("Failed to update %s block in %s at %s,%s,%s: '%s'" % (str(block.getType()), block.getWorld().getName(), block.getX(), block.getY(), block.getZ(), e))
+67 -67
View File
@@ -18,96 +18,96 @@ from random import randrange
def mysql_query(query, args, fetch = True): def mysql_query(query, args, fetch = True):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver") conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor() curs = conn.cursor()
curs.execute(query, args) curs.execute(query, args)
if fetch: if fetch:
results = curs.fetchall() results = curs.fetchall()
else: else:
results = conn.commit() results = conn.commit()
curs.close() curs.close()
conn.close() conn.close()
return results return results
def generate_token(length): def generate_token(length):
cons = 'bcdfghjklmnpqrstvwxyz' cons = 'bcdfghjklmnpqrstvwxyz'
vows = 'aeiou' vows = 'aeiou'
token = '' token = ''
start = randrange(2) start = randrange(2)
for i in range(0, length): for i in range(0, length):
if i % 2 == start: if i % 2 == start:
token += cons[randrange(21)] token += cons[randrange(21)]
else: else:
token += vows[randrange(5)] token += vows[randrange(5)]
return token return token
def get_token(uuid): def get_token(uuid):
results = mysql_query("SELECT DISTINCT `token`, `email` FROM register_tokens WHERE `uuid` = ? LIMIT 1", (uuid,)) results = mysql_query("SELECT DISTINCT `token`, `email` FROM register_tokens WHERE `uuid` = ? LIMIT 1", (uuid,))
return results[0] if len(results) == 1 else None return results[0] if len(results) == 1 else None
def token_command(sender): def token_command(sender):
plugin_header(sender, "Website Token") plugin_header(sender, "Website Token")
if is_player(sender): if is_player(sender):
try: try:
token = get_token(sender.getUniqueId().toString().replace("-", "")) token = get_token(sender.getUniqueId().toString().replace("-", ""))
if token: if token:
msg(sender, "&aEmail: &e%s" % token[1]) msg(sender, "&aEmail: &e%s" % token[1])
msg(sender, "&aToken: &e%s" % token[0]) msg(sender, "&aToken: &e%s" % token[0])
msg(sender, "&cIMPORTANT: never share the token with anyone!") msg(sender, "&cIMPORTANT: never share the token with anyone!")
msg(sender, "&cIt could be used to claim your website account!") msg(sender, "&cIt could be used to claim your website account!")
else: else:
msg(sender, "&cYou don't have a token yet! Use &e/gettoken <email>&c.") msg(sender, "&cYou don't have a token yet! Use &e/gettoken <email>&c.")
except Exception, e: except Exception, e:
error(e) error(e)
msg(sender, "&cError getting your token, please contact an admin!") msg(sender, "&cError getting your token, please contact an admin!")
else: else:
msg(sender, "&cThis is only for players..") msg(sender, "&cThis is only for players..")
def tokengen_command(sender, args): def tokengen_command(sender, args):
plugin_header(sender, "Website Token") plugin_header(sender, "Website Token")
if is_player(sender): if is_player(sender):
if len(args) < 1: if len(args) < 1:
msg(sender, "&cPlease use &e/gettoken <email adress>") msg(sender, "&cPlease use &e/gettoken <email adress>")
else:
# email may contain spaces
mail = " ".join(args)
# email regex, needs something followed by an @ followed by domain or IP
if match("^.+@(.+\\..{2,}|\\[[0-9a-fA-F:.]+\\])$", mail) != None:
token = generate_token(6)
uuid = sender.getUniqueId().toString().replace("-", "")
try:
mysql_query("DELETE FROM register_tokens WHERE `uuid` = ?", (uuid,), False)
mysql_query("INSERT INTO register_tokens (`uuid`, `token`, `email`) VALUES (?, ?, ?)", (uuid, token, mail), False)
msg(sender, "&aToken generated!")
msg(sender, "&aEmail: &e%s" % mail)
msg(sender, "&aToken: &e%s" % token)
msg(sender, "&cIMPORTANT: never share the token with anyone!")
msg(sender, "&cIt could be used to claim your website account!")
except Exception, e:
error(e)
msg(sender, "&cError getting your token, please contact an admin!")
else:
msg(sender, "&c'&6%s&c' doesn't look like a valid email adress!" % mail)
else: else:
# email may contain spaces msg(sender, "&cThis is only for players..")
mail = " ".join(args)
# email regex, needs something followed by an @ followed by domain or IP
if match("^.+@(.+\\..{2,}|\\[[0-9a-fA-F:.]+\\])$", mail) != None:
token = generate_token(6)
uuid = sender.getUniqueId().toString().replace("-", "")
try:
mysql_query("DELETE FROM register_tokens WHERE `uuid` = ?", (uuid,), False)
mysql_query("INSERT INTO register_tokens (`uuid`, `token`, `email`) VALUES (?, ?, ?)", (uuid, token, mail), False)
msg(sender, "&aToken generated!")
msg(sender, "&aEmail: &e%s" % mail)
msg(sender, "&aToken: &e%s" % token)
msg(sender, "&cIMPORTANT: never share the token with anyone!")
msg(sender, "&cIt could be used to claim your website account!")
except Exception, e:
error(e)
msg(sender, "&cError getting your token, please contact an admin!")
else:
msg(sender, "&c'&6%s&c' doesn't look like a valid email adress!" % mail)
else:
msg(sender, "&cThis is only for players..")
@hook.command("token") @hook.command("token")
def on_token_command(sender, args): def on_token_command(sender, args):
thread.start_new_thread(token_command, (sender,)) thread.start_new_thread(token_command, (sender,))
return True return True
@hook.command("gettoken") @hook.command("gettoken")
def on_gettoken_command(sender, args): def on_gettoken_command(sender, args):
thread.start_new_thread(tokengen_command, (sender, args)) thread.start_new_thread(tokengen_command, (sender, args))
return True return True