Merge branch 'dev'
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -3,6 +3,5 @@
|
|||||||
*sublime*
|
*sublime*
|
||||||
|
|
||||||
# these are player/ingame specific
|
# these are player/ingame specific
|
||||||
files/chatgroups.json
|
files/
|
||||||
files/lol.json
|
files/*
|
||||||
files/reports.json
|
|
||||||
96
README.md
96
README.md
@@ -5,14 +5,19 @@ Redstoner's custom plugins, written in python.
|
|||||||
|
|
||||||
# Installation / Set-up
|
# Installation / Set-up
|
||||||
|
|
||||||
|
1-line-install-script for bash:
|
||||||
|
`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. Create a new directory called 'redstoner'
|
||||||
0. Download [the latest bukkit](http://dl.bukkit.org/downloads/craftbukkit/get/latest-dev/craftbukkit.jar)
|
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. Run it once inside redstoner, then shut it down again
|
||||||
0. Create a new directory (inside redstoner) called 'lib'
|
0. Create a new directory (inside redstoner) called 'lib'
|
||||||
0. Download [jython](http://search.maven.org/remotecontent?filepath=org/python/jython-standalone/2.5.3/jython-standalone-2.5.3.jar) and save it as 'jython.jar' inside lib
|
0. Download [jython](http://search.maven.org/remotecontent?filepath=org/python/jython-standalone/2.5.3/jython-standalone-2.5.3.jar) and save it as 'jython.jar' inside 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
|
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
|
' and save it as 'mysql-connector.jar' inside lib
|
||||||
0. Download [PyPluginLoader](http://gserv.me/static/PyPluginLoader-0.3.5.jar) into the plugins directory
|
0. Download [PyPluginLoader](http://gserv.me/static/PyPluginLoader-0.3.5.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**':
|
0. inside plugins, clone this directory into 'redstoner-utils**.py.dir**':
|
||||||
`git clone git@bitbucket.org:redstonesheep/redstoner-utils.git 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. Download [PEX](http://dev.bukkit.org/media/files/789/291/PermissionsEx.jar) into plugins
|
||||||
@@ -25,18 +30,32 @@ Redstoner's custom plugins, written in python.
|
|||||||
Always use this branch to change code, please test before pushing. (If something goes wrong here, that's okay)
|
Always use this branch to change code, please test before pushing. (If something goes wrong here, that's okay)
|
||||||
|
|
||||||
* **master**
|
* **master**
|
||||||
Never commit into this branch directly! Only merge stable versions of *dev*
|
Never commit into this branch directly! Only merge stable versions of *dev*:
|
||||||
|
```bash
|
||||||
|
git checkout master
|
||||||
|
git merge dev
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
# Deploying
|
# Deploying on the server
|
||||||
|
|
||||||
There ain't much to do. The dev server uses the *dev* branch, the live server uses *master*. Just pull and restart the server.
|
**Never** edit the files directly on the server!
|
||||||
|
The dev server uses the *dev* branch, the live server uses *master*.
|
||||||
|
|
||||||
Be **very careful** with the live server! Make sure you're in the master branch and the code is working before pulling/restarting!
|
Please use the script `<server-dir>/git_pull_utils.sh`.
|
||||||
|
**Do not use `git pull` on the server!**
|
||||||
|
All files must be owned and pulled by the *redstoner* user.
|
||||||
|
|
||||||
|
Be **very careful** with the live server! Make sure you're in the *master* branch and the code is working before pulling/restarting!
|
||||||
|
|
||||||
|
|
||||||
# Modules / Files
|
# 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/`
|
* `files/`
|
||||||
|
|
||||||
> All config / storage files go here
|
> All config / storage files go here
|
||||||
@@ -88,4 +107,67 @@ Be **very careful** with the live server! Make sure you're in the master branch
|
|||||||
|
|
||||||
* `webtoken.py`
|
* `webtoken.py`
|
||||||
|
|
||||||
> Adds `/token`, reads and writes from the database to generate *pronouncable* (and thus memorable) registration-tokens for the website.
|
> 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
|
||||||
|
|
||||||
|
|
||||||
|
# Code styleguide & tips
|
||||||
|
|
||||||
|
## Indentation
|
||||||
|
Never use tabs!
|
||||||
|
Use 2 spaces to indent.
|
||||||
|
|
||||||
|
## 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 or end of a loop, method, or the like - 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:
|
||||||
|
```python
|
||||||
|
try:
|
||||||
|
# code
|
||||||
|
except Exception, e:
|
||||||
|
print(e)
|
||||||
|
```
|
||||||
|
Since we're using jython, this will not catch Java exceptions.
|
||||||
|
This will give you some more deatails:
|
||||||
|
```python
|
||||||
|
import traceback
|
||||||
|
try:
|
||||||
|
#code
|
||||||
|
except: # everything
|
||||||
|
print(traceback.format_exc())
|
||||||
|
```
|
||||||
@@ -42,7 +42,7 @@ def onAcCommand(sender, args):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@hook.event("player.PlayerChatEvent", "normal")
|
@hook.event("player.AsyncPlayerChatEvent", "low")
|
||||||
def onChat(event):
|
def onChat(event):
|
||||||
sender = event.getPlayer()
|
sender = event.getPlayer()
|
||||||
msg = event.getMessage()
|
msg = event.getMessage()
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ try:
|
|||||||
except Exception, e:
|
except Exception, e:
|
||||||
error("Failed to load chatgroups: %s" % e)
|
error("Failed to load chatgroups: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
@hook.command("chatgroup")
|
@hook.command("chatgroup")
|
||||||
def onChatgroupCommand(sender, args):
|
def onChatgroupCommand(sender, args):
|
||||||
try:
|
try:
|
||||||
@@ -49,6 +50,7 @@ def onChatgroupCommand(sender, args):
|
|||||||
except Exception, e:
|
except Exception, e:
|
||||||
error(e)
|
error(e)
|
||||||
|
|
||||||
|
|
||||||
@hook.command("cgt")
|
@hook.command("cgt")
|
||||||
def onCgtCommand(sender, args):
|
def onCgtCommand(sender, args):
|
||||||
p = sender.getName()
|
p = sender.getName()
|
||||||
@@ -76,6 +78,7 @@ def groupchat(sender, message, ann=False):
|
|||||||
#except Exception, e:
|
#except Exception, e:
|
||||||
# error(e)
|
# error(e)
|
||||||
|
|
||||||
|
|
||||||
def saveGroups():
|
def saveGroups():
|
||||||
try:
|
try:
|
||||||
chatgroups_file = open(chatgroups_filename, "w")
|
chatgroups_file = open(chatgroups_filename, "w")
|
||||||
@@ -84,7 +87,8 @@ def saveGroups():
|
|||||||
except Exception, e:
|
except Exception, e:
|
||||||
error("Failed to write reports: " + str(e))
|
error("Failed to write reports: " + str(e))
|
||||||
|
|
||||||
@hook.event("player.PlayerChatEvent", "normal")
|
|
||||||
|
@hook.event("player.AsyncPlayerChatEvent", "normal")
|
||||||
def onChat(event):
|
def onChat(event):
|
||||||
sender = event.getPlayer()
|
sender = event.getPlayer()
|
||||||
msge = event.getMessage()
|
msge = event.getMessage()
|
||||||
|
|||||||
9
main.py
9
main.py
@@ -11,8 +11,9 @@ sys.path += ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/l
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from helpers import *
|
from helpers import *
|
||||||
except Exception, e:
|
except:
|
||||||
print("[RedstonerUtils] ERROR: Failed to import helpers: %s" % e)
|
print("[RedstonerUtils] ERROR: Failed to import helpers:")
|
||||||
|
print(print_traceback())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -36,8 +37,8 @@ for module in modules:
|
|||||||
try:
|
try:
|
||||||
mod[module] = __import__(module)
|
mod[module] = __import__(module)
|
||||||
log("Module %s loaded." % module)
|
log("Module %s loaded." % module)
|
||||||
except Exception, e:
|
except:
|
||||||
error("Failed to import module %s: '%s'" % (module, e))
|
error("Failed to import module %s:" % module)
|
||||||
error(print_traceback())
|
error(print_traceback())
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
11
mentio.py
11
mentio.py
@@ -7,7 +7,7 @@ arrow = colorify(u"&r&7\u2192&r")
|
|||||||
regex = reg_compile(u"\u00A7[\\da-fk-or]")
|
regex = reg_compile(u"\u00A7[\\da-fk-or]")
|
||||||
|
|
||||||
|
|
||||||
@hook.event("player.AsyncPlayerChatEvent", "normal")
|
@hook.event("player.AsyncPlayerChatEvent", "high")
|
||||||
def onChat(event):
|
def onChat(event):
|
||||||
try:
|
try:
|
||||||
if not event.isCancelled():
|
if not event.isCancelled():
|
||||||
@@ -15,7 +15,7 @@ def onChat(event):
|
|||||||
words = event.getMessage().split(" ")
|
words = event.getMessage().split(" ")
|
||||||
recipients = event.getRecipients()
|
recipients = event.getRecipients()
|
||||||
|
|
||||||
for recipient in recipients:
|
for recipient in list(recipients):
|
||||||
rec_words = words[:] # copy
|
rec_words = words[:] # copy
|
||||||
for i in range(len(rec_words)):
|
for i in range(len(rec_words)):
|
||||||
word = rec_words[i]
|
word = rec_words[i]
|
||||||
@@ -25,13 +25,14 @@ def onChat(event):
|
|||||||
|
|
||||||
# player was mentioned
|
# player was mentioned
|
||||||
if rec_words != words:
|
if rec_words != words:
|
||||||
try: # list might not be mutable
|
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
|
||||||
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, 0)
|
recipient.playSound(recipient.getLocation(), "mob.chicken.plop", 1, 0)
|
||||||
except Exception, e:
|
except:
|
||||||
error("Failed to handle PlayerChatEvent: %s" % e)
|
error("Failed to handle PlayerChatEvent:")
|
||||||
error(print_traceback())
|
error(print_traceback())
|
||||||
21
misc.py
21
misc.py
@@ -1,5 +1,6 @@
|
|||||||
|
#pylint: disable=F0401
|
||||||
from helpers import *
|
from helpers import *
|
||||||
|
import org.bukkit.inventory.ItemStack as ItemStack
|
||||||
|
|
||||||
#
|
#
|
||||||
# Welcome new players
|
# Welcome new players
|
||||||
@@ -75,12 +76,20 @@ def onSudoCommand(sender, args):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Clicking redstone_sheep with shears will drop redstone + wool and makes a moo sound
|
||||||
|
#
|
||||||
|
|
||||||
|
@hook.event("player.PlayerInteractEntityEvent")
|
||||||
|
def onPlayerInteractEntity(event):
|
||||||
|
if not event.isCancelled():
|
||||||
|
sender = event.getPlayer()
|
||||||
|
entity = event.getRightClicked()
|
||||||
|
if isPlayer(entity) and str(entity.getUniqueId()) == "ae795aa8-6327-408e-92ab-25c8a59f3ba1" and str(sender.getItemInHand().getType()) == "SHEARS" and str(sender.getGameMode() == "CREATIVE"):
|
||||||
|
for i 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)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ def token_command(sender):
|
|||||||
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, "&cIt could be used to claim your website account!")
|
||||||
else:
|
else:
|
||||||
msg(sender, "&cYou don't have a token yet! Use &e/tokengen <email>&c.")
|
msg(sender, "&cYou don't have a token yet! Use &e/tokengen <email>&c.")
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
@@ -94,7 +96,7 @@ def onTokenCommand(sender, args):
|
|||||||
thread.start_new_thread(token_command, (sender,))
|
thread.start_new_thread(token_command, (sender,))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@hook.command("tokengen")
|
@hook.command("gettoken")
|
||||||
def onTokengenCommand(sender, args):
|
def onTokengenCommand(sender, args):
|
||||||
thread.start_new_thread(tokengen_command, (sender, args))
|
thread.start_new_thread(tokengen_command, (sender, args))
|
||||||
return True
|
return True
|
||||||
|
|||||||
Reference in New Issue
Block a user