249 Commits

Author SHA1 Message Date
Dico
fd368a8aac Patch buggy movement blocking when logging in
Added a separate event handler for PlayerMoveEvent which instead of cancelling the event, sets the new position to the old one.
This should fix the buggy, flashy screen you get when you move your cursor while not yet logged in.
2016-06-23 05:21:24 +02:00
Dico
bfcb22f650 Merge pull request #46 from psrcek/patch-1
Fix for bug, where you can shift click and toggle levers
2016-06-21 22:35:53 +02:00
psrcek
1602ad2185 Fix for bug, where you can shift click and toggle levers 2016-06-21 21:46:48 +02:00
Dico200
cebdb90d60 Fix cycle for 1.10 (will break in 1.8 now..) 2016-06-12 20:02:06 +02:00
Dico200
6320d78a37 Mysql update tweak 2016-06-12 18:13:42 +02:00
Dico
47a0a92225 Merge pull request #45 from psrcek/dev
Fixed typo
2016-06-12 18:09:40 +02:00
Dico200
a6ea05a459 made /check display email not confirmed warning 2016-06-12 18:04:17 +02:00
psrcek
f5c51645d2 Fixed typo 2016-06-12 13:34:33 +02:00
Dico200
8e2ff33dbb Serversigns permissions fix, adapted help page to user permissions, implemented help pages 2016-06-05 17:46:35 +02:00
Dico200
2c94c40c77 Remove /clear from commands whitelist for the time being 2016-06-05 13:51:12 +02:00
Dico200
2f943e8b12 Add /clear to serversigns command whitelist 2016-06-03 20:29:25 +02:00
Dico200
0aa18e9945 Merge branch 'dev' of github.com:RedstonerServer/redstoner-utils into dev 2016-06-01 00:44:37 +02:00
Dico200
13606638b7 Fix calc 2016-05-31 18:03:46 +02:00
PixelSergey
57603725d2 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2016-05-31 17:54:16 +03:00
PixelSergey
f0f32abbfa Final fix to lol list pageing
Can someone tell me whether it's paging or pageing or both?
2016-05-31 17:52:56 +03:00
Dico200
83e7505565 Remove debug I forgot to remove in prior commit 2016-05-31 16:41:13 +02:00
Dico200
f0ada788bf Made serversigns force its commands into the command map (to replace the java plugin ServerSigns its commands) 2016-05-31 16:39:54 +02:00
PixelSergey
5d00af8ced Fix checking for page 0 in saylol.py listing
I hope I'm not making this too messy
2016-05-31 17:34:49 +03:00
PixelSergey
1e34a9b39b Fix saylol.py for dico
By the way, dico, some of your line notes on the previous commit were completely wrong
Once again, this has been tested
I didn't clean up the code, I think it's good enough. And it works perfectly.
2016-05-31 17:09:42 +03:00
PixelSergey
6f4357fad7 Add lol list pageing.
Tested, works perf.
2016-05-31 15:39:34 +03:00
Dico200
fe2d6eb701 Forgot to set this timeout back up after testing... Derp 2016-05-31 01:00:15 +02:00
Dico200
ae706e8e12 Clean up imbusy. Improve replying to busy people. All working perfectly, tested thoroughly. 2016-05-31 00:13:51 +02:00
Dico200
edf5fa6d32 Fix /busy status 2016-05-30 22:59:09 +02:00
Dico200
5d3530242e Another tiny tweak to @debug 2016-05-30 22:58:27 +02:00
Dico200
c7d872c93b Fix @debug decorator not returning results 2016-05-30 22:55:06 +02:00
Dico200
e46bea31c8 Cleaned up chatalias, notable changes: Fixed remotes list and remove, improved prior alias checks for multi-aliasing, fixed color chat permission implementations, grouped the file properly, removed unreasonable complications, changed header from Alias to Chatalias, fixed a mistake where 2 threads are created per player for online players during server reload, moved a lot of repeated code to remote() base function 2016-05-30 21:42:30 +02:00
Dico200
6539c34a82 Removed unneeded try/except clause 2016-05-30 15:47:24 +02:00
Dico200
d00301ccc3 Updated damnspam, made block breaking check attached levers and buttons, denied clicking now mentions timeout left, tweaked command slightly to perceive setting the timeout to 0 as removing it. 2016-05-30 15:45:05 +02:00
Dico200
4e4acc6b3d Remove sync.py file 2016-05-30 05:26:07 +02:00
Dico200
9d1956dc2a Merge branch 'dev' 2016-05-30 04:52:26 +02:00
Dico200
e08666995c Friends fix 2016-05-30 04:52:10 +02:00
Dico200
765fa76cb7 Merge branch 'dev' 2016-05-30 04:15:24 +02:00
Dico200
1da9aa2578 Friends hotfix... Did I really write this code? 2016-05-30 04:15:06 +02:00
Dico200
20b33588e7 Merge branch 'dev' 2016-05-30 04:07:18 +02:00
Dico200
d66e8f3294 Imbusy hotfix... 2016-05-30 04:07:09 +02:00
Dico200
1fb6e08d42 Serversigns hotfix 2016-05-30 03:53:33 +02:00
Dico200
ba78151e49 Merge branch 'dev' 2016-05-30 01:11:42 +02:00
Dico200
c78d0f651b Hotfix for chatalias 2016-05-30 01:11:34 +02:00
Dico200
fa03a68963 Merge branch 'dev' 2016-05-30 00:08:45 +02:00
Dico200
fe32e7a49c Cleaned up some of helpers.py 2016-05-30 00:05:49 +02:00
Dico200
361da9e049 Chatalias: Fixed all the things (permission AMOUNT, permission LENGTH, and more), incremented version number 2016-05-29 23:49:45 +02:00
Dico200
33d8fd2f08 Removed Pan from pythoners, added Pep, added essentials:esudo to sudo_blacklist 2016-05-29 22:18:42 +02:00
Dico200
a0a7d43a38 Tweak comment above imbusy, removed credits, removed a useless comment with an old line of code 2016-05-29 21:29:36 +02:00
Dico200
8e4f30a017 Changed command blacklist to a whitelist. Added /svs commands to show whitelisted commands. Added a few more command aliases. Added maximum line count and maximum line size. 2016-05-29 21:08:28 +02:00
Dico200
5a757b7fb1 Removed @hook.enable decs from modules, added them to the on_enable() method of main.py. 2016-05-29 20:56:29 +02:00
Dico200
e35fadc353 Added/fixed torch breaker setting. Added a few missing saveSettings() calls. Fixed /set <setting> on turning it off and vice-versa for boolean settings that are enabled by default. A few more tweaks. 2016-05-29 20:55:10 +02:00
Dico
860c844d6c Merge pull request #43 from RedstonerServer/chatalias-chained-aliases-patch
Prevent chained aliases in chatalias
2016-05-28 23:06:32 +02:00
Dico200
c3189639f0 Fixes and stuff 2016-05-28 23:05:43 +02:00
Pepich
c534d9316a Moved OnModuleLoad to bottom of file 2016-05-28 22:40:08 +02:00
Pepich
7da3fd5b71 That's an "s", not an "S" ._. 2016-05-28 22:35:28 +02:00
Pepich
a19f0b5bdc Added support for /rl; Made comments more precise 2016-05-28 22:33:38 +02:00
Dico200
28ac05ce0a Tweak imbusy permission nodes 2016-05-28 22:22:51 +02:00
Dico200
e60e124324 Merge branch 'dev' of github.com:RedstonerServer/redstoner-utils into dev 2016-05-28 22:22:12 +02:00
Dico
cab575937d Merge pull request #42 from RedstonerServer/imbusy-reply-patch
Solidify imbusy blocking pms, tpas, etc.
2016-05-28 22:22:01 +02:00
Dico200
7a905643eb Enabled friends module, added friends check in imbusy, fixed small mistakes 2016-05-28 22:18:27 +02:00
Dico200
3859ad8e40 Fix error on player quit for player.py 2016-05-28 21:43:59 +02:00
Dico200
89e3982a29 Implement some of pizza's changes from imbusy branch 2016-05-26 04:37:47 +02:00
Dico200
28afa1ddcf Changed debug output, tweaked [busy] broadcast prefix 2016-05-25 18:54:32 +02:00
Dico200
8629b39ce1 Make /busy a toggle, move help page to /busy help. Changed a few messages 2016-05-25 18:41:42 +02:00
Dico200
00e38efd14 Added catcher for /mail send 2016-05-25 18:32:20 +02:00
Dico200
a532c6b42c Changed broadcast message, removed two debugs 2016-05-25 18:18:27 +02:00
Dico200
1fdf97f77a Add missing _ ... lol 2016-05-25 16:46:49 +02:00
Dico200
16e78a2677 Add missing ) to chatalias 2016-05-25 16:44:09 +02:00
Dico
2d6725df73 Prevent chained aliases in chatalias
Prevents 1 -> 23 along with 2 -> 3 and similar stuff
2016-05-25 16:40:31 +02:00
Dico200
d88baa4899 What is this.. sorry 2016-05-25 16:37:58 +02:00
Dico200
29f846c8f9 Undo prior changes in favor of pull request 2016-05-25 16:31:32 +02:00
Dico200
a2a43ed464 Replace camelCase with _ stuff 2016-05-25 16:13:36 +02:00
Dico
5592e16200 Solidify imbusy blocking pms, tpas, etc.
I used reflection to get the Map<String, Command> object from the SimpleCommandMap instance stored in the implementation of PluginManager.
I replaced all Command instances in there that handle /msg, /tpa, /tpahere and /reply, minus /minecraft:tell, with a wrapper that checks if the target is busy.
Tested adequately, but some more would be nice.
2016-05-25 15:49:11 +02:00
Dico200
9a1006e711 Imbusy command: status <player> tweaked, cleaned up return statements 2016-05-25 03:05:59 +02:00
Dico200
29e7ce174b Imbusy command: Replace plugin_header calls with a single one at the start 2016-05-25 03:02:01 +02:00
Dico200
8165d5977b Small change to imbusy messages 2016-05-25 03:00:35 +02:00
Dico200
fca3cf250c Imbusy: Fixed typos and some *flaws* which I will disregard here @curs3d 2016-05-25 02:52:24 +02:00
Dico200
7fdaee155a Fix yo shitty chatgroups code 2016-05-25 02:46:53 +02:00
Dico200
4e6bd44c38 Undoing these small changes from last commit... 2016-05-25 02:40:50 +02:00
Dico200
a555676076 Prevent complete multi-replacement in chatalias. Doesn't prevent 1 -> 2 and 23 -> 5 to make for 13 -> 5, but does prevent a -> 20 and 2 -> 3. Tested. 2016-05-25 02:39:05 +02:00
Dico
cb1a333a56 Merge pull request #41 from RedstonerServer/chatalias
Fixed player subcommand, removed debug outputs
2016-05-25 01:38:10 +02:00
Dico
07039b3d16 Fix command given for next help page in chatalias.py 2016-05-25 01:37:01 +02:00
Pepich
48251e1e52 Cleanup, adding debug outputs back, removing empty try/catch phrases 2016-04-12 14:52:16 +02:00
Pepich
fa1d5e900d Fixed player subcommand, removed debug outputs 2016-04-11 16:59:42 +02:00
jomo
622971c41c Merge pull request #40 from RedstonerServer/tweaks
Fixed indentation error ll 39-41 (damnspam)
2016-04-11 15:35:43 +02:00
Pepich
46f1564af0 Fixed indentation error ll 39-41 2016-04-11 15:18:59 +02:00
Pepich
d81d17b5f2 Merge pull request #39 from psrcek/dev
removed some unnecesary code
2016-03-26 22:08:34 +01:00
psrcek
c870561f7d removed some unnecesary code
The below if statement is always true and the value of timeout_on isn't used before a return statement.
                timeout_on = False
                if timeout_on == False:
2016-03-26 21:56:10 +01:00
Dico200
286f8751b5 Fix tab -.- lol why did it load locally? 2016-03-12 01:02:48 +01:00
Dico200
fad1ae0f90 Fixed a return message in blockplacemods.py 2016-03-12 01:00:07 +01:00
PixelSergey
621f4ca23b Added a debug decorator, use @debug to nicely print function errors 2016-03-08 20:32:56 +02:00
jomo
f2dfc6c473 Merge pull request #37 from RedstonerServer/tweaks
Minor tweaks
2016-02-15 17:48:22 +01:00
BuildTools
0aad531f9e Added more aliases 2016-02-15 17:38:19 +01:00
BuildTools
412ed59225 Added aliases and proper command description 2016-02-15 17:33:14 +01:00
BuildTools
9160c85d09 Added automatic disabling of cgt when leaving a chatgroup 2016-02-15 17:32:50 +01:00
jomo
a98a8a8657 Merge pull request #35 from RedstonerServer/tabnames
Fixed naming error in rank trainingmod
2016-02-15 16:51:55 +01:00
BuildTools
34ed3a1023 Fixed naming error in rank trainingmod 2016-02-15 16:50:21 +01:00
jomo
ddc4a9b457 Merge pull request #34 from RedstonerServer/tabnames
Adding tabnames, updating main
2016-02-15 01:34:56 +01:00
jomo
6a4d1447ec rename tabnames to nametags
I think it's a more descriptive name
2016-02-15 01:27:13 +01:00
jomo
5a0477fdbf clean up tabnames
doesn't throw exceptions when group can't be found, will print warning instead
2016-02-14 23:52:50 +01:00
BuildTools
91afa684cd removed unnessecary imports, code cleanup 2016-02-14 22:33:44 +01:00
BuildTools
70f2001e7b initial commit, adding the tabnames module 2016-02-14 22:25:02 +01:00
BuildTools
f03f34777b Added tabnames module, disabled iptracker due to instability 2016-02-14 22:24:11 +01:00
PixelSergey
799584df46 Unbusies on logout 2016-02-07 13:15:51 +02:00
BuildTools
3a2d1193ca iptracker v1.1.0 updating to helpers v2.0.0 functions; fixing bugs in data management and command execution 2016-01-09 16:43:19 +01:00
BuildTools
cbc77de826 Helpers v2.0.0, added versioning, added array_to_list and get_permission_content, renamed isIP to is_ip 2016-01-09 16:42:26 +01:00
BuildTools
883b02acd5 Initial commit of chatalias.py v2 2016-01-09 16:40:57 +01:00
PanFritz
4cf08dcd6d Merge pull request #30 from psrcek/dev
Fixed capitalization
2015-12-27 00:21:42 +01:00
psrcek
fa81ace66e Fixed capitalization 2015-12-26 23:57:34 +01:00
Dico200
528269afd6 Added comment with permission nodes to blockplacemods 2015-12-09 22:33:48 +01:00
Dico200
2c8bfff01f Add sudo_blacklist to blocked_cmds in serversigns 2015-11-30 02:31:28 +01:00
Dico200
2690da5666 This should keep players from interacting with comparators where they cannot build 2015-11-30 02:19:07 +01:00
Dico200
1969584312 Revert "Merge branch 'wrapper' of https://github.com/RedstonerServer/redstoner-utils into wrapper"
This reverts commit 4d5861fd36, reversing
changes made to 9d0e4c99ba.
2015-11-25 15:49:52 +01:00
Dico200
0172cf2feb Revert "wrapper_command WIP"
This reverts commit 522a7a99a1.
2015-11-25 15:24:34 +01:00
Dico200
522a7a99a1 wrapper_command WIP 2015-11-25 01:15:44 +01:00
Dico200
4d5861fd36 Merge branch 'wrapper' of https://github.com/RedstonerServer/redstoner-utils into wrapper 2015-11-23 23:29:06 +01:00
BuildTools
781714bc74 Test 2015-11-23 22:28:11 +01:00
BuildTools
0b836485ee Merge branch 'wrapper' of github.com:RedstonerServer/redstoner-utils into wrapper
First commit of working wrapper
2015-11-23 22:22:21 +01:00
BuildTools
70b4db5318 added wrappers, temp disabled all modules 2015-11-23 22:17:40 +01:00
PanFritz
9d0e4c99ba Removed "ls" in for loop 2015-11-23 01:55:45 +01:00
PixelSergey
e57f721db3 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-11-22 19:56:55 +02:00
PixelSergey
2808c5838b Fixed a bug in chatalias. Still safe :D 2015-11-22 19:56:11 +02:00
Dico200
ab42a0cb65 Sorry for the spam 2015-11-22 18:01:27 +01:00
Dico200
274ce42fc8 Block break fix infinity 2015-11-22 17:52:54 +01:00
Dico200
030b32f86a More tweaks 2015-11-22 17:50:26 +01:00
Dico200
2a68613e77 Block break tweaks 2015-11-22 17:38:21 +01:00
Dico200
d1d62d71d2 Derp 2! block break fix 6 lel 2015-11-22 17:30:09 +01:00
Dico200
ff365a832d Derp! block break fix 5 2015-11-22 17:28:56 +01:00
Dico200
39b38ff093 Block break fix 4 2015-11-22 17:25:56 +01:00
Dico200
019b3c6b57 Block break fix 3 2015-11-22 17:20:54 +01:00
Dico200
d83345d8f2 Block break fix 2 2015-11-22 17:18:03 +01:00
Dico200
f941f05f1d Block break fix 1 2015-11-22 17:16:06 +01:00
Dico200
5717f58527 Disabled chatalias so I can see errors 2015-11-22 17:12:35 +01:00
Dico200
da9255558c Testing for sign breaking problems, added trace 2015-11-22 17:10:16 +01:00
Dico200
d3ba9eac73 More fixes, pretty much finished 2015-11-22 17:06:55 +01:00
Dico200
8613c9221e Fix for /svs remove <id>, Added some to blocked_cmds, /svs help still WIP 2015-11-22 15:52:41 +01:00
Dico200
23b3bffcf6 Major serversigns overhaul, it mostly works now. A little bit of testing and command help is left 2015-11-22 14:51:47 +01:00
PixelSergey
1b59c79fd7 Fixed chatalias, no bugs and now SAFE! \o/ 2015-11-21 12:08:45 +02:00
Dico
93c9bab421 Chatgroups optimization
The message is now colorified just once, not for every recipient. I'll test all this at home <3
2015-11-04 12:01:38 +01:00
Dico
4a4cdc839b Add /chatgroup tpahere to chatgroups help message 2015-11-04 11:53:09 +01:00
Dico
eb491bcd9e Update chatgroups, add /cg tpahere, add some cool code
I added a function do_for_chatgroup which takes a groupname, a function, and additional arguments after a receiver.
2015-11-04 11:52:27 +01:00
Dico
7282bf63f6 Removed unneeded permission check from signalstrength.py... again xD 2015-11-03 19:16:35 +01:00
Dico200
aa86881f5e Fix survival use of /signalstrength, other interesting changes 2015-11-03 19:05:15 +01:00
Nemes
93ca9e0456 Removed secondary permission, sorry my derp 2015-11-03 16:57:19 +01:00
Pepich
c84dce9d34 Added colorsupport, fixed perms and limits into file, added length limitations, made file PEP8 conform 2015-11-02 00:02:44 +01:00
Dico200
eb201196e1 Small change <3 2015-11-01 22:03:21 +01:00
Dico200
1f1c090651 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-11-01 21:59:21 +01:00
Dico200
5f77eddf5c This module should work now. Can someone test it? 2015-11-01 21:59:05 +01:00
NEMESIS13cz
612b86c50b Merge branch 'dev' 2015-11-01 14:20:25 +01:00
NEMESIS13cz
670203522b Added permission for signalstrength 2015-11-01 14:09:13 +01:00
NEMESIS13cz
cb8efcc767 fixed errors on login event 2015-11-01 14:09:01 +01:00
NEMESIS13cz
438a2f7027 Added permissions for warn and warnp 2015-11-01 14:08:48 +01:00
NEMESIS13cz
7775e37a65 Merge branch 'dev' 2015-11-01 13:42:11 +01:00
NEMESIS13cz
626ec7f187 lowercase please 2015-10-31 19:31:46 +01:00
NEMESIS13cz
dfa48d7da5 This seems to fix everything 2015-10-31 19:31:32 +01:00
NEMESIS13cz
3f677467fc Fixed conflicts with chatalias 2015-10-31 19:24:33 +01:00
Curs3d
97e2b80392 Ate pugs. Fixed bugs. 2015-10-31 20:08:29 +02:00
PixelSergey
398533860b Fixed ugly stacktraces. And the associated bugs. 2015-10-31 19:59:55 +02:00
PixelSergey
0ff5e6eaa1 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-10-31 19:36:05 +02:00
PixelSergey
fe8461872f Fixed ugly stacktraces. And the associated bugs. 2015-10-31 19:16:44 +02:00
PixelSergey
9b47599d06 Fixed ugly stacktraces. And the associated bugs. 2015-10-31 19:10:22 +02:00
Dico200
085360c331 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-10-31 15:53:25 +01:00
Dico200
9c3d969695 Fixed signalstrength error and minor change 2015-10-31 15:52:03 +01:00
NEMESIS13cz
278f0b411c Made iptracker async 2015-10-30 17:16:31 +01:00
NEMESIS13cz
629a938b3e Changed database stuff 2015-10-30 17:06:59 +01:00
NEMESIS13cz
35fd76c7a8 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-10-30 16:48:05 +01:00
NEMESIS13cz
743d42f719 added iptracker to main.py 2015-10-30 16:47:51 +01:00
NEMESIS13cz
c66fb40df5 changed limit to 1000 2015-10-30 16:44:07 +01:00
NEMESIS13cz
4ed319f15d Fixed offline players and no notification for the punished player 2015-10-30 16:37:47 +01:00
Pepich
086eade43f fixed colorify method 2015-10-30 16:36:47 +01:00
NEMESIS13cz
45a9b260d9 Now works with offline players 2015-10-30 16:31:23 +01:00
Sergey
b369ea7557 Removed random crap
How did it get there?!
2015-10-28 18:49:52 +02:00
NEMESIS13cz
3d34f15c41 Changed to ignore lower/upper case 2015-10-27 17:05:55 +01:00
PixelSergey
e036716a62 Remembered to edit main.py :) 2015-10-20 19:45:53 +03:00
PixelSergey
fb7871bb3b Added I'M BUSY! plugin 2015-10-20 19:42:14 +03:00
Dico200
b4f5a68e4e small addition to basecommands documentation 2015-10-20 18:10:56 +02:00
Dico200
ce4fa316d9 Added the signalstrength.py file. 2015-10-20 18:05:40 +02:00
Dico200
9119c3d150 Moved /signalstrength to its own file, added default configurability, added basecommands documentation, added can_build() to helpers 2015-10-20 18:03:05 +02:00
Dico200
2db8142b35 Small update to /signalstrength 2015-10-20 02:58:42 +02:00
Dico200
5e593e0f5c Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-10-20 01:02:16 +02:00
Dico200
0676c535ad Finished signal strength command 2015-10-20 01:01:53 +02:00
Pepich
fbbbad1853 added console support and fixed a small cosmetic bug 2015-10-18 16:06:09 +02:00
Pepich
70662bdd0b Added support for an infinite amount of mentio keywords 2015-10-18 15:37:17 +02:00
Pepich
d2204d9706 Initial iptracker commit allowing username - IP lookups and vice versa 2015-10-18 15:36:50 +02:00
Pepich
9a93cd3203 Added two functions for the iptracker 2015-10-18 15:36:08 +02:00
Sergey
2811f74888 Fixed missing return statement 2015-10-18 01:33:03 +03:00
PixelSergey
b8ab9a2fc7 Added permission check, fixed negative setting 2015-10-16 23:32:19 +03:00
PixelSergey
28da124088 Changed names to UUID, fixed empty dicts 2015-10-16 22:54:44 +03:00
PixelSergey
b9293d7be2 Updated event variable 2015-10-16 17:37:52 +03:00
PixelSergey
ed27cdf561 Added the chat aliasing plugin 2015-10-16 17:20:17 +03:00
NEMESIS13cz
f5df50e353 Added Dico to pythoners 2015-10-14 21:14:40 +02:00
Dico200
a637954ef7 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-10-11 23:28:18 +02:00
Dico200
e85f716dc5 /signalstrength progress 2015-10-11 23:27:20 +02:00
Dico200
05a74b416b /signalstrength progress 2015-10-11 23:25:12 +02:00
NEMESIS13cz
9c2934a374 Fixed spelling mistake 2015-10-11 15:33:31 +02:00
NEMESIS13cz
069cc8aec1 Removed a vanishfix.py call as we are no longer using it 2015-09-29 21:53:45 +02:00
PanFritz
b4c4857761 Attempt to make a sync decorator 2015-09-20 01:47:36 +02:00
Dico200
920738bd65 Another fix -.- these single characters...
It's been too long since I committed properly
2015-09-19 02:25:58 +02:00
Dico200
12ea31cd02 fix in misc.py - ofc I forget to save 2015-09-19 02:24:39 +02:00
Dico200
4404674c29 Disabled vanishfix, preparing merge
I replaced /warn and /warnp commands with @simplecommand hook. they
happened to be missing the 'if' from the permission checks and this
takes care of some other things as well.

I added a module called vanish which will replace essentials vanish
which happens to be really buggy as you know.

I added a serversigns module but it is not added to main.py and thus it
will not cause problems!
2015-09-19 02:22:21 +02:00
Dico200
393d7f791d Small fix to make sure staff can always see other staff in vanish mode 2015-09-19 01:26:26 +02:00
Dico200
d5c9e2fae1 Added vanish module, a simple replacement for the essentials version
I tried to use underscores where ever I could ^^
2015-09-19 01:00:51 +02:00
Dico200
9bf7d626da Serversigns Replacement, accessible for everyone.
Untested. 🉑
2015-09-15 16:45:22 +02:00
NEMESIS13cz
ebfb4b4140 Added a permission to /warn and /warnp 2015-09-13 23:27:11 +02:00
NEMESIS13cz
4947c7edd2 Fixed missing return 2015-09-13 03:37:40 +02:00
NEMESIS13cz
d4ed851ac0 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-09-13 02:53:05 +02:00
NEMESIS13cz
6e4f34e9d8 Fixed error tracing 2015-09-13 02:51:50 +02:00
PanFritz
33fab330e6 Changed color for messages 2015-09-13 02:13:10 +02:00
PanFritz
61202f2482 Merge branch 'dev' of github.com:RedstonerServer/redstoner-utils into dev 2015-09-13 01:44:08 +02:00
PanFritz
de2b097484 Changed login event to highest, added a message to the command interrupt 2015-09-13 01:43:41 +02:00
NEMESIS13cz
b3ff447d05 Added sudo aliases to the sudo blacklist 2015-09-13 01:34:02 +02:00
PanFritz
d4bb481b24 Now cancles all commands besides /login whilst not logged in 2015-09-13 01:32:13 +02:00
PanFritz
a1973b6666 Fixed syntax error 2015-09-13 00:56:52 +02:00
NEMESIS13cz
fff55eb016 Fixed spelling error (thanks keyboard) 2015-09-12 21:10:17 +02:00
NEMESIS13cz
a7ed59cfbf Added a lag warning broadcast command 2015-09-12 21:06:49 +02:00
PanFritz
256bcadf8d Disabled servercontrol for now 2015-09-11 11:48:42 +02:00
PanFritz
1cc8126a9f Added args and kwargs 2015-09-11 11:44:46 +02:00
PanFritz
d751654ff8 Acctualy, its simpler to just do it all in a thread. 2015-09-11 11:43:57 +02:00
PanFritz
ebb893289c Converted to use async_query 2015-09-11 11:39:06 +02:00
NEMESIS13cz
449c501544 Added evil obsidian mining punishments plugins thing >:D 2015-09-06 15:20:53 +02:00
NEMESIS13cz
65b74511d0 Added punishments.py to module list 2015-09-06 15:20:10 +02:00
NEMESIS13cz
579b906b2a Added vanishfix.py into modules + call its enabled method 2015-09-06 01:40:13 +02:00
NEMESIS13cz
823dd37341 Added a temporary fix for the knows /vanish bug 2015-09-06 01:39:53 +02:00
NEMESIS13cz
aa3f76e897 Added note deletion in tag 2015-09-04 20:51:28 +02:00
jomo
75a78dfef0 Fix #25
which -s is not available on all platforms
2015-09-01 23:59:43 +02:00
PanFritz
945cc977a7 Imported db password and user from secrets, added target_args 2015-09-01 00:42:19 +02:00
PanFritz
f711f5e46c Added async_query since we need to remake all of our db interaction to be in a seperate thread 2015-08-31 03:25:37 +02:00
NEMESIS13cz
465b235042 Added a simple per-player notes module 2015-08-30 20:25:10 +02:00
NEMESIS13cz
b9e71b80ad Added scriptutils and tag into main.py 2015-08-30 20:24:49 +02:00
PanFritz
65f20ae9ca First working prototype of servercontrol to redstoner 2015-08-28 05:53:36 +02:00
NEMESIS13cz
37de65d130 Added /stop to the sudo blacklist 2015-08-27 18:09:02 +02:00
NEMESIS13cz
cbdfd4af23 Added a /sudo blacklist as a final security update 2015-08-25 18:33:43 +02:00
PanFritz
0ea6183c03 Merge branch 'dev' of github.com:RedstonerServer/redstoner-utils into dev
Conflicts:
	loginsecurity.py
	player.py
2015-08-18 00:24:26 +02:00
NEMESIS13cz
782f127b23 Changed timeout in loginsecurity to 60 seconds 2015-08-17 14:44:02 +02:00
PanFritz
6574179872 Multiple bug fixes, loginsecurity fully functioning 2015-08-17 04:54:02 +02:00
PanFritz
2ae64488ad Fixed indentation problems 2015-08-17 04:13:28 +02:00
PanFritz
bacdebca34 Fixed missing argument 2015-08-17 04:10:35 +02:00
PanFritz
039d79fa0c remade loginsecurity to use py_player 2015-08-17 04:06:34 +02:00
NEMESIS13cz
2310c9143a More security fixes 2015-08-14 02:19:14 +02:00
NEMESIS13cz
fcda622259 Fixed spelling error 2015-08-14 00:57:43 +02:00
NEMESIS13cz
e400f9999a Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-08-13 15:01:37 +02:00
NEMESIS13cz
d76b0aaf37 Changed event priority to low 2015-08-13 14:56:56 +02:00
jomo
45008c0443 remove trailing whitespace, replace tabs with 4x space 2015-08-13 00:30:54 +02:00
jomo
34eed808dc Merge branch 'dev' of github.com:RedstonerServer/redstoner-utils into dev 2015-08-13 00:22:21 +02:00
jomo
fe56d1e2f4 check requirements before trying to setup 2015-08-13 00:22:13 +02:00
jomo
6d7bd233da install python dependencies on setup 2015-08-13 00:18:06 +02:00
jomo
ae02f14c4b duplicate sample files on setup 2015-08-13 00:11:35 +02:00
jomo
9e3cd6828e disable some plugins by default 2015-08-13 00:05:36 +02:00
NEMESIS13cz
c137ef93c6 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-08-12 22:41:58 +02:00
NEMESIS13cz
f1ae0c4189 Created script utilities 2015-08-12 22:40:59 +02:00
jomo
6aa7cf40aa use ssh for cloning, fix level-type 2015-08-12 22:02:19 +02:00
NEMESIS13cz
66ab0c1468 Fixed order of operations 2015-08-12 20:34:20 +02:00
NEMESIS13cz
11cbd08480 Changed /pyeval to only work for certain people 2015-08-12 20:22:41 +02:00
jomo
c05e56d307 add setup.sh 2015-08-12 01:50:02 +02:00
34 changed files with 3113 additions and 321 deletions

View File

@@ -50,12 +50,12 @@ def get_key(uuid):
key = ac_keys.get(uuid)
return key if key != None else ac_defaultkey
@simplecommand("adminchatkey",
aliases = ["ackey"],
senderLimit = 0,
helpNoargs = True,
helpSubcmd = True,
description = "Sets a key character for adminchat",
@simplecommand("adminchatkey",
aliases = ["ackey"],
senderLimit = 0,
helpNoargs = True,
helpSubcmd = True,
description = "Sets a key character for adminchat",
usage = "<key>")
def adminchatkey_command(sender, command, label, args):
key = " ".join(args)

View File

@@ -92,7 +92,7 @@ def adminnotes_command(sender, command, label, args):
show_an_help(sender)
return
if not args[1].isdigit():
msg(sender, "&cThe ID has to be numeric (check /an if you're unsure)")
msg(sender, "&cThe ID has to be numeric (check /an if you're unsure)")
return
note_id = int(args[1])-1
if note_id >= len(notes):

View File

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

View File

@@ -9,7 +9,18 @@ import org.bukkit.inventory.ItemStack as ItemStack
import org.bukkit.Material as Material
import org.bukkit.event.block.Action as Action
import org.bukkit.block.BlockFace as BlockFace
import org.bukkit.scheduler.BukkitRunnable as Runnable
import org.bukkit.scheduler.BukkitRunnable as BukkitRunnable
"""
# Permissions:
# - utils.toggle: for use of the command
# - utils.toggle.cauldron
# - utils.toggle.slab
# - utils.toggle.furnace
# - utils.toggle.piston
# - utils.toggle.dropper
# - utils.toggle.hopper
"""
settingInformation = dict( #[setting type, identifying description, detailed description, aliases, (optional) max slot id], setting types: 0 = toggle, default on. 1 = Set your setting to held itemstack, 2 = toggle, default off
cauldron = [0,
@@ -24,14 +35,14 @@ settingInformation = dict( #[setting type, identifying description, detailed des
],
furnace = [1,
"automatically filling furnaces upon placement",
"Sets your preferred default furnace contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle dropper clear to clear all slots.",
"Sets your preferred default furnace contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle furnace clear to clear all slots.",
["cooker", "fillf"], 2
],
#torch = [0,
# "removal of torches you place on redstone blocks",
# "Toggles whether redstone torches which you place on redstone blocks will be deleted after a short amount of delay.",
# ["redstonetorch", "tor"]
#],
torch = [0,
"removal of torches you place on redstone blocks",
"Toggles whether redstone torches which you place on redstone blocks will be deleted after a short amount of delay.",
["redstonetorch", "tor"]
],
piston = [2,
"rotating pistons, droppers and hoppers to face the block you place them against",
"Toggles whether pistons or sticky pistons which you place will be rotated to face the block which you placed them against.",
@@ -44,18 +55,18 @@ settingInformation = dict( #[setting type, identifying description, detailed des
],
hopper = [1,
"automatically filling hoppers upon placement",
"Sets your preferred default hopper contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle dropper clear to clear all slots.",
"Sets your preferred default hopper contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle hopper clear to clear all slots.",
["itemtransporter", "fillh"], 4
]
)
defaults = {
0: list,
0: list,
1: dict,
2: list
}
faces = {
piston_faces = {
BlockFace.DOWN : 0,
BlockFace.UP : 1,
BlockFace.NORTH : 2,
@@ -64,6 +75,14 @@ faces = {
BlockFace.EAST : 5
}
torch_faces = {
1: BlockFace.WEST,
2: BlockFace.EAST,
3: BlockFace.NORTH,
4: BlockFace.SOUTH,
5: BlockFace.DOWN
}
playerSettings = open_json_file("blockplacemods", {})
for setting, details in settingInformation.iteritems():
@@ -87,8 +106,8 @@ def getSettingDetails(arg):
raise CommandException(" &cThat setting could not be found.\n For command help, use &o/toggle &cor &o/set")
@simplecommand("toggle",
aliases = ["setting", "set", "config"],
usage = "<setting> [value|info]",
aliases = ["setting", "set", "config"],
usage = "<setting> [value|info]",
description = "Toggles or sets your preferences for our redstone \nutilities. The following settings are available:\n" + ", ".join([x for x in settingInformation]),
senderLimit = 0,
helpNoargs = True,
@@ -117,14 +136,14 @@ def toggle_command(sender, command, label, args):
elif arg2 in ("toggle", "switch"):
new = not enabled
elif arg2 in ("on", "enable"):
new = not default
new = True
elif arg2 in ("off", "disable"):
new = default
new = False
else:
return " &cArgument '%s' was not recognized. \n Use &o/toggle %s info &cfor more information" % (arg2, setting)
if enabled == new:
if enabled is new:
return " &cAlready %s: &a%s" % ("enabled" if enabled else "disabled", details[1])
if new == default:
if new is default:
values.remove(uuid)
else:
values.append(uuid)
@@ -139,31 +158,34 @@ def toggle_command(sender, command, label, args):
if arg2 == "clear":
if enabled:
del values[uuid]
return " &aDisabled " + details[1]
saveSettings()
return " &aDisabled " + details[1]
return " &cAlready disabled: " + details[1]
if arg2 == "details":
if arg2 == "info":
return " &aSetting %s:\n &9%s \n&6Accepted arguments: [<slot>|clear|details]" % (setting, details[2])
slot = int(arg2) if arg2.isdigit() else 0
slot = int(arg2) if arg2.isdigit() else 0
if not (0 <= slot <= details[4]):
return " &cSlot number must be more than or equal to 0 and less than or equal to %s!" % details[4]
item = fromStack(player.getItemInHand())
if item[0] == 0 or item[1] <= 0:
if enabled:
if enabled:
items = values[uuid]
if slot in items:
del items[slot]
saveSettings()
if len(items) == 0:
del items
saveSettings()
return " &aDisabled " + details[1]
saveSettings()
return " &aCleared slot %s of setting %s" % (slot, setting)
return " &cSlot %s of setting %s was already cleared!" % (slot, setting)
return " &cAlready disabled: " + details[1]
if arglen == 2 and not arg2.isdigit():
return " &cArgument '%s' was not recognized. \nUse &o/toggle %s details &cfor more detailsrmation." % (arg2, setting)
return " &cArgument '%s' was not recognized. \nUse &o/toggle %s info &cfor more information." % (arg2, setting)
if not enabled:
values[uuid] = {}
@@ -186,66 +208,70 @@ def isEnabled(toggleSetting, uuid):
@hook.event("block.BlockPlaceEvent", "monitor")
def on_block_place(event):
if event.isCancelled():
return
player = event.getPlayer()
if not is_creative(player):
return
try:
uuid = uid(player)
block = event.getBlockPlaced()
material = block.getType()
if event.isCancelled():
return
player = event.getPlayer()
if not is_creative(player):
return
uuid = uid(player)
block = event.getBlockPlaced()
material = block.getType()
if (material in (Material.WOOD_STEP, Material.STEP)
and isEnabled("slab", uuid)
and player.hasPermission("utils.toggle.slab")
and block.getData() < 8
):
block.setData(block.getData() + 8) # Flip upside down
if (material in (Material.WOOD_STEP, Material.STEP)
and isEnabled("slab", uuid)
and player.hasPermission("utils.toggle.slab")
and block.getData() < 8
):
block.setData(block.getData() + 8) # Flip upside down
elif (material == Material.CAULDRON
and isEnabled("cauldron", uuid)
and player.hasPermission("utils.toggle.cauldron")
):
block.setData(3) #3 layers of water, 3 signal strength
elif (material == Material.CAULDRON
and isEnabled("cauldron", uuid)
and player.hasPermission("utils.toggle.cauldron")
):
block.setData(3) #3 layers of water, 3 signal strength
elif ((material == Material.FURNACE and player.hasPermission("utils.toggle.furnace"))
or (material == Material.DROPPER and player.hasPermission("utils.toggle.dropper"))
or (material == Material.HOPPER and player.hasPermission("utils.toggle.hopper"))
):
stacks = get(str(material).lower()).get(uuid)
if stacks != None: # Enabled
state = block.getState()
inv = state.getInventory()
for slot, stack in stacks.iteritems():
inv.setItem(int(slot), toStack(stack))
state.update()
"""
elif (material == Material.REDSTONE_TORCH_ON
and event.getBlockAgainst().getType() == Material.REDSTONE_BLOCK
and isEnabled("torch", uuid)
and player.hasPermission("utils.toggle.torch")
):
torches_to_break.append(block)
"""
elif ((material == Material.FURNACE and player.hasPermission("utils.toggle.furnace"))
or (material == Material.DROPPER and player.hasPermission("utils.toggle.dropper"))
or (material == Material.HOPPER and player.hasPermission("utils.toggle.hopper"))
):
stacks = get(str(material).lower()).get(uuid)
if stacks != None: # Enabled
state = block.getState()
inv = state.getInventory()
for slot, stack in stacks.iteritems():
inv.setItem(int(slot), toStack(stack))
state.update()
if (material in (Material.PISTON_BASE, Material.PISTON_STICKY_BASE)
and isEnabled("piston", uuid)
and player.hasPermission("utils.toggle.piston")
):
block.setData(faces[block.getFace(event.getBlockAgainst())])
elif (material == Material.REDSTONE_TORCH_ON
and isEnabled("torch", uuid)
and player.hasPermission("utils.toggle.torch")
and block.getData() in torch_faces
and block.getRelative(torch_faces[block.getData()]).getType() is Material.REDSTONE_BLOCK
):
torches_to_break.append(block)
elif (material in (Material.PISTON_BASE, Material.PISTON_STICKY_BASE)
and isEnabled("piston", uuid)
and player.hasPermission("utils.toggle.piston")
):
block.setData(piston_faces[block.getFace(event.getBlockAgainst())])
except:
error(trace())
@hook.event("player.PlayerInteractEvent", "monitor")
def on_interact(event):
player = event.getPlayer()
if (isEnabled("cauldron", uid(player))
and player.hasPermission("utils.toggle.cauldron")
if (isEnabled("cauldron", uid(player))
and player.hasPermission("utils.toggle.cauldron")
and is_creative(player)
and event.getAction() == Action.RIGHT_CLICK_BLOCK
and (not event.hasItem() or event.getItem().getType() == Material.REDSTONE)
@@ -257,29 +283,36 @@ def on_interact(event):
if not event2.isCancelled():
block.setData(block.getData() - 1 if block.getData() > 0 else 3)
"""
break_torches = True
torches_to_break = deque()
def stop_breaking_torches():
break_torches = False
info("Interrupted torch breaking thread")
info("[BlockPlaceMods] Interrupted torch breaking thread")
class torch_breaker(Runnable):
class JBukkitRunnable(BukkitRunnable):
def run():
try:
if break_torches:
for i in range(len(torches_to_break)):
block = torches_to_break.popleft()
mat = block.getType()
if mat == Material.REDSTONE_TORCH_OFF:
block.setTypeId(0)
elif mat == Material.REDSTONE_TORCH_ON:
def __init__(self, func):
self.run = func
def torch_breaker():
try:
if break_torches:
for i in range(len(torches_to_break)):
block = torches_to_break.popleft()
mat = block.getType()
if mat == Material.REDSTONE_TORCH_OFF:
block.setTypeId(0)
elif mat == Material.REDSTONE_TORCH_ON:
if block.getData() in torch_faces and block.getRelative(torch_faces[block.getData()]).getType() is Material.REDSTONE_BLOCK:
torches_to_break.append(block)
except:
error(trace())
"""
except:
error(trace())
def schedule_torch_breaker():
JBukkitRunnable(torch_breaker).runTaskTimer(server.getPluginManager().getPlugin("RedstonerUtils"), 0, 1)

View File

@@ -10,6 +10,12 @@ calc_perm = "utils.calc"
calc_perm_power = "utils.calc.power"
def calc(sender, text):
try:
return do_calc(sender, text.lower())
except:
return None
def do_calc(sender, text):
"""
extracts a mathematical expression from `text`
returns (expression, result) or None

402
chatalias.py Normal file
View File

@@ -0,0 +1,402 @@
# TODO: Add cg/ac/msg support
import os
import mysqlhack
import org.bukkit as bukkit
from org.bukkit import *
from helpers import *
# Version number and requirements
alias_version = "2.1.0"
helpers_versions = ["1.1.0", "2.0.0"]
enabled = False
error_msg = colorify("&cUnspecified error")
commands_per_page = 5
global_aliases = {"./":"/"}
data = {}
use_mysql = True
# Permissions:
# Grants full access immediately
permission_ALL = "utils.alias.*"
# Access to the command to display the help screen
permission_BASE = "utils.alias"
# Make replacements only when the user has this permission
permission_USE = "utils.alias.use"
# Modify aliases
permission_MODIFY = "utils.alias.modify"
permission_MODIFY_OTHERS = "utils.alias.modify.others"
# List aliases
permission_LIST = "utils.alias.list"
permission_LIST_OTHERS = "utils.alias.list.others"
# Set alias amounts/length limits, e.g. utils.alias.amount.420
permission_AMOUNT = "utils.alias.amount."
default_alias_limit = 15
permission_LENGTH = "utils.alias.length."
default_length_limit = 120
# See when the plugin was disabled due to version errors
permission_INFO = "utils.alias.info"
permission_FINFO = "utils.alias.finfo"
def safe_open_json(uuid):
if not os.path.exists("plugins/redstoner-utils.py.dir/files/aliases"):
os.makedirs("plugins/redstoner-utils.py.dir/files/aliases")
value = open_json_file("aliases/" + uuid)
if value is None:
value = dict(global_aliases)
save_json_file("aliases/" + uuid, value)
return value
def get_player_alias_limit(player):
value = get_permission_content(player, permission_AMOUNT)
if value is not None and value.isdigit():
return int(value)
return default_alias_limit
def get_player_length_limit(player):
value = get_permission_content(player, permission_LENGTH)
if value is not None and value.isdigit():
return int(value)
return default_length_limit
@hook.event("player.PlayerJoinEvent", "high")
def on_join(event):
if enabled:
t = threading.Thread(target=load_data, args=(uid(event.getPlayer()), ))
t.daemon = True
t.start()
else:
if event.getPlayer().hasPermission(permission_FINFO):
disabled_fallback(event.getPlayer())
@hook.event("player.AsyncPlayerChatEvent", "high")
def on_player_chat(event):
if enabled:
if event.isCancelled():
return
player = event.getPlayer()
if not hasPerm(player, permission_USE):
return
msg_limit = get_player_length_limit(player)
for alias, value in data[uid(player)].iteritems():
if player.hasPermission("essentials.chat.color"):
event.setMessage(event.getMessage().replace(colorify(alias), colorify(value)))
else:
event.setMessage(event.getMessage().replace(alias, value))
if not player.hasPermission(permission_ALL) and len(event.getMessage()) > msg_limit:
event.setCancelled(True)
plugin_header(player, "Chatalias")
msg(player, "The message you wanted to generate would exceed the length limit limit of %d. Please make it shorter!" % msg_limit)
return
def hasPerm(player, permission):
return (player.hasPermission(permission)) or (player.hasPermission(permission_ALL))
def disabled_fallback(receiver):
if not hasPerm(receiver, permission_INFO):
msg(receiver, colorify("&cUnknown command. Use &e/help&c, &e/plugins &cor ask a mod."))
else:
msg(receiver, colorify("&cPlugin alias v" + alias_version + " has experienced an &eEMERGENCY SHUTDOWN:"))
msg(receiver, error_msg)
msg(receiver, colorify("&cPlease contact a dev/admin (especially pep :P) about this to take a look at it."))
def can_remote(player):
return hasPerm(player, permission_LIST_OTHERS) or hasPerm(player, permission_MODIFY_OTHERS)
# Command
@hook.command("alias",
usage="/<command> <add, remove, list, help> [...]",
desc="Allows aliasing of words")
def on_alias_command(sender, cmd, label, args):
plugin_header(sender, "Chatalias")
try:
args = array_to_list(args)
if not enabled:
disabled_fallback(sender)
return
if not hasPerm(sender, permission_BASE):
noperm(sender)
return
if args[0].lower() != "player" and not is_player(sender):
msg(sender, "&cThe console cannot have aliases")
return True
subcommands[args[0].lower()](sender, args[1:])
except:
subcommands["help"](sender, "1")
return True
def help(sender, args):
commands = [colorify("&e/alias help [page]")]
if hasPerm(sender, permission_LIST):
commands += [colorify("&e/alias list &7- Lists all your aliases")]
if hasPerm(sender, permission_MODIFY):
commands += [colorify("&e/alias add <word> <alias> &7- Add an alias")]
commands += [colorify("&e/alias remove <word> &7- Remove an alias")]
if can_remote(sender):
while len(commands) < commands_per_page:
commands += [""]
commands += [colorify("&7Following commands will be executed on <player> yet all output will be redirected to you, except when you set silent to false, then <player> will see it too.")]
if hasPerm(sender, permission_LIST_OTHERS):
commands += [colorify("&e/alias player <name> list [silent]")]
if hasPerm(sender, permission_MODIFY_OTHERS):
commands += [colorify("&e/alias player <name> add <word> <alias> [silent]")]
commands += [colorify("&e/alias player <name> remove <word> [silent]")]
pages = (len(commands)-1)/commands_per_page + 1
page = 1
if len(args) != 0:
page = int(args[0])
if (page > pages):
page = pages
if page < 1:
page = 1
msg(sender, colorify("&e---- &6Help &e-- &6Page &c" + str(page) + "&6/&c" + str(pages) + " &e----"))
page -= 1
to_display = commands[5*page:5*page+5]
for message in to_display:
msg(sender, message)
if page+1 < pages:
msg(sender, colorify("&6To display the next page, type &c/alias help " + str(page+2)))
def add(sender, args):
uuid = uid(sender)
args = [args[0]] + [" ".join(args[1:])]
if (args[0] not in data[uuid]) and is_alias_limit_reached(sender, sender):
return
if not add_alias_data(uuid, args[0], args[1]):
msg(sender, colorify("&c") + "Could not add this alias because it would cause some sequences to be replaced multiple times", usecolor = False)
return
msg(sender, colorify("&7Alias: ") + args[0] + colorify("&7 -> ") + args[1] + colorify("&7 was succesfully created!"), usecolor=sender.hasPermission("essentials.chat.color"))
def radd(sender, sender_name, target, args, silent):
if len(args) < 2:
msg(sender, "&cYou must pass a sequence and an alias for it")
return
replaced = args[0]
alias = " ".join(args[1:])
uuid = uid(target)
if not silent:
if sender is not target:
plugin_header(target, "Chatalias")
msg(target, "&cPlayer %s &cis creating an alias for you!" % sender_name)
if (replaced not in data[uuid]) and is_alias_limit_reached(target, sender, silent):
return
if not add_alias_data(uuid, replaced, alias):
message = colorify("&c") + "Could not add this alias because it would cause some sequences to be replaced multiple times"
msg(sender, message, usecolor = False)
if not silent:
msg(target, message, usecolor = False)
return
message = colorify("&7Alias: &7%s&7 -> &7%s&7 was successfully created!") % ((colorify(replaced), colorify(alias)) if target.hasPermission("essentials.chat.color") else (replaced, alias))
msg(sender, message, usecolor = False)
if not silent:
msg(target, message, usecolor = False)
def is_alias_limit_reached(player, recipient, silent = True):
if player.hasPermission(permission_ALL):
return False
alias_limit = get_player_alias_limit(player)
if len(data[uid(player)]) >= alias_limit:
message = ("&cYour limit of %d has been reached" if player is recipient else "&cThe limit of %d has been reached for that player") % alias_limit
msg(recipient, message)
if not silent:
msg(player, message)
return True
return False
def add_alias_data(puuid, aliased, new_alias):
prior = dict(data[puuid])
if aliased in prior:
info("Checking prior, removing previous alias for " + aliased)
del prior[aliased]
# prevent 2 -> 3 if there is 1 -> 2
for alias in prior.values():
if aliased in alias:
info("aliased %s in alias %s" % (aliased, alias))
return False
# prevent 1 -> 2 if there is 2 -> 3
for sequence in prior:
if sequence in new_alias:
info("sequence %s in new_alias %s" % (sequence, new_alias))
return False
data[puuid][aliased] = new_alias
save_data(puuid)
return True
def remove(sender, args):
try:
msg(sender, colorify("&7Successfully removed alias ") + args[0] + colorify(" &7-> ") + data[uid(sender)].pop(args[0]) + colorify("&7!"), usecolor=sender.hasPermission("essentials.chat.color"))
save_data(uid(sender))
except:
msg(sender, colorify("&cCould not remove alias ") + args[0] + colorify(", it does not exist."), usecolor=sender.hasPermission("essentials.chat.color"))
def rremove(sender, sender_name, target, args, silent):
if len(args) < 1:
msg(sender, "&cYou must specify a sequence whose alias is to be removed")
return
removed = args[0]
uuid = uid(target)
aliases = data[uuid]
if not silent:
msg(target, "&cPlayer %s &cis removing an alias for you!" % sender_name)
if removed in aliases:
alias = aliases.pop(removed)
message = colorify("&7Alias: &7%s&7 -> &7%s&7 successfully removed!") % ((colorify(removed), colorify(alias)) if target.hasPermission("essentials.chat.color") else (removed, alias))
msg(sender, message, usecolor = False)
if not silent:
msg(target, message, usecolor = False)
save_data(uuid)
else:
message = colorify("&cCould not remove alias &7%s&c, it does not exist") % colorify(removed) if target.hasPermission("essentials.chat.color") else removed
msg(sender, message, usecolor = False)
if not silent:
msg(target, message, usecolor = False)
def list_alias(sender, args):
msg(sender, "&7You have a total of " + str(len(data[uid(sender)])) + " aliases:")
for word, alias in data[str(uid(sender))].items():
msg(sender, colorify("&7") + word + colorify("&7 -> ") + alias, usecolor=sender.hasPermission("essentials.chat.color"))
def rlist_alias(sender, sender_name, target, args, silent):
aliases = data[uid(target)]
msg(sender, "&7Player %s has a total of %d aliases:" % (target.getName(), len(aliases)))
if not silent:
if sender is not target:
plugin_header(target, "Chatalias")
msg(target, "&cPlayer %s &cis listing your aliases" % sender_name)
if target.hasPermission("essentials.chat.color"):
for pair in aliases.iteritems():
msg(sender, colorify("&7%s&7 -> %s" % pair), usecolor = False)
else:
for pair in aliases.iteritems():
msg(sender, colorify("&7%s&7 -> %s") % pair, usecolor = False)
def remote(sender, args):
if len(args) < 2:
msg(sender, "&cAlias remotes take at least 3 arguments")
return
target_remote = remotes.get(args[1].lower())
if target_remote is None:
msg(sender, "&cThat remote command does not exist")
return
target = server.getOfflinePlayer(args[0])
if target is None or not (target.hasPlayedBefore() or target.isOnline()):
msg(sender, "&cThat player could not be found")
return
silent = True
if len(args) > (2 if target_remote is rlist_alias else 3 if target_remote is rremove else 4):
if args[-1].lower() == "false":
silent = sender is target or not target.isOnline()
args = args[:-1]
elif args[-1].lower() == "true":
args = args[:-1]
target_remote(sender, sender.getDisplayName() if is_player(sender) else colorify("&6Console"), target, args[2:], silent)
subcommands = {
"help": help,
"?": help,
"add": add,
"remove": remove,
"del": remove,
"delete": remove,
"player": remote,
"remote": remote,
"list": list_alias
}
remotes = {
"add": radd,
"remove": rremove,
"del": rremove,
"delete": rremove,
"list": rlist_alias,
}
# Storage
# MySQL Table:
# CREATE TABLE `chatalias` (`uuid` VARCHAR(36) PRIMARY KEY, `alias` TEXT);
def load_data(uuid):
if use_mysql:
try:
t = threading.Thread(target=load_data_thread, args=(uuid,))
t.daemon = True
t.start()
except:
error(trace())
else:
data[uuid] = safe_open_json(uuid)
def load_data_thread(uuid):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("SELECT `alias` FROM `chatalias` WHERE `uuid` = ?;", (uuid, ))
results = curs.fetchall()
curs.close()
conn.close()
if len(results) == 0:
value = dict(global_aliases)
else:
value = json_loads(results[0][0])
data[uuid] = value
def save_data(uuid):
if use_mysql:
try:
t = threading.Thread(target=save_data_thread, args=(uuid,))
t.daemon = True
t.start()
except:
error(trace())
else:
save_json_file("aliases/" + uuid, data[uuid])
def save_data_thread(uuid):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("INSERT INTO `chatalias` (`uuid`, `alias`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `alias` = VALUES(`alias`);",
(uuid, json_dumps(data[uuid])))
conn.commit()
curs.close()
conn.close()
# OnModuleLoad
enabled = helpers_version in helpers_versions
if not enabled:
error_msg = colorify("&6Incompatible versions detected (&chelpers.py&6)")
for player in server.getOnlinePlayers():
if enabled:
load_data(uid(player))
else:
if player.hasPermission(permission_FINFO):
disabled_fallback(player)

View File

@@ -21,6 +21,8 @@ def on_chatgroup_command(sender, command, label, args):
if len(args) == 1 and args[0] == "leave":
if sender_id in groups.keys():
groupchat(sender, "left the group", True)
if sender in cg_toggle_list:
cg_toggle_list.remove(p)
group = groups[sender_id]
del(groups[sender_id])
save_groups()
@@ -43,11 +45,18 @@ def on_chatgroup_command(sender, command, label, args):
msg(sender, "&aUse chat like '&e%s<message>' to send messages to this group." % get_key(sender_id))
elif len(args) == 1 and args[0] == "key":
msg(sender, "&aYour chatgroup key is currently: '&c%s&a'" % get_key(sender_id))
elif len(args) == 1 and args[0] == "tpahere":
if sender_id in groups.keys():
do_for_chatgroup(groups[sender_id], send_tpa_request, sender)
msg(sender, "&aSent a tpahere request to all users in your chatgroup")
else:
msg(sender, "&cYou have to be in a chatgroup to do that")
else:
msg(sender, "&e/chatgroup join <name>")
msg(sender, "&e/chatgroup leave")
msg(sender, "&e/chatgroup info")
msg(sender, "&e/chatgroup key")
msg(sender, "&e/chatgroup tpahere")
@hook.command("cgt")
@@ -72,11 +81,19 @@ def groupchat(sender, message, ann = False):
mesg = "&8[&bCG&8] &e&o%s&e&o %s" % (name, message)
else:
mesg = "&8[&bCG&8] &f%s&f: &6%s" % (name, message)
mesg = colorify(mesg)
info("[ChatGroups] %s (%s): %s" % (sender.getDisplayName(), group, message))
do_for_chatgroup(group, msg, mesg, usecolor = False)
def do_for_chatgroup(group, func, *args, **kwargs):
for receiver in server.getOnlinePlayers():
groups.get(uid(receiver)) == group and msg(receiver, mesg)
if groups.get(uid(receiver)) == group:
func(receiver, *args, **kwargs)
def send_tpa_request(receiver, sender):
if not receiver == sender:
runas(sender, "/tpahere " + receiver.getName())
def save_groups():
save_json_file("chatgroups", groups)
@@ -97,12 +114,12 @@ def on_chat(event):
groupchat(sender, msge)
event.setCancelled(True)
@simplecommand("chatgroupkey",
aliases = ["cgkey"],
senderLimit = 0,
helpNoargs = True,
helpSubcmd = True,
description = "Sets a key character for chatting to your chatgroup",
@simplecommand("chatgroupkey",
aliases = ["cgkey"],
senderLimit = 0,
helpNoargs = True,
helpSubcmd = True,
description = "Sets a key character for chatting to your chatgroup",
usage = "<key>")
def chatgroupkey_command(sender, command, label, args):
key = " ".join(args)
@@ -115,5 +132,6 @@ def chatgroupkey_command(sender, command, label, args):
save_keys()
return "&aYour chatgroup key was set to: '&c%s&a'" % key
def save_keys():
save_json_file("chatgroup_keys", cg_keys)

View File

@@ -35,11 +35,11 @@ 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,))
curs.execute("SELECT DISTINCT `id`, `email`, `confirmed` FROM users WHERE `uuid` = ? LIMIT 1", (uuid,))
results = curs.fetchall()
curs.close()
conn.close()
return ("http://redstoner.com/users/%s" % results[0][0], results[0][1]) if results else (None, None)
return ("http://redstoner.com/users/%s" % results[0][0], results[0][1], False if results[0][2] == 0 else True) if results else (None, None, True)
# receive country based on the user's IP
@@ -68,6 +68,8 @@ def get_all_data(sender, player):
website = get_website_data(player)
msg(sender, "&6> Website account: &e%s" % website[0])
msg(sender, "&6> email: &e%s" % website[1])
if not website[2]:
msg(sender, "&6> &cEmail NOT Confirmed!")
msg(sender, "&7 -- Data provided by ipinfo.io")
msg(sender, "&6> Country: &e%s" % get_country(data))
msg(sender, "&7 -- Data provided by Mojang")
@@ -86,7 +88,10 @@ def on_hook_command(sender, command, label, args):
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)
t = threading.Thread(target=get_all_data, args=(sender, player))
t.daemon = True
t.start()
else:
msg(sender, "&4You don't have the required permissions to execute this command!")
return True

View File

@@ -56,7 +56,7 @@ def on_slot_change(event):
def do_cycle(player, down):
inv = player.getInventory()
items = inv.getContents()
items = inv.getStorageContents()
shift = -9 if down else 9
shift = shift % len(items)
for _ in range(4):
@@ -64,7 +64,7 @@ def do_cycle(player, down):
uniq_items = sorted(set(list(items)[:9])) # get unique inventory
if uniq_items != [None]: # row not empty
break
inv.setContents(items)
inv.setStorageContents(items)
def save_cyclers():
save_json_file("cycle", no_cyclers)

View File

@@ -1,12 +1,15 @@
#pylint: disable = F0401
from helpers import *
from time import time as now
import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
import org.bukkit.Material as Material
import org.bukkit.block.BlockFace as BlockFace
inputs = open_json_file("damnspam", {}) # format "x;y;z;World"
accepted_inputs = ["WOOD_BUTTON", "STONE_BUTTON", "LEVER"]
changing_input = False
removing_input = False
max_timeout = 240
timeout_error_str = "&cThe timeout must be -1 or within 0 and %d" % max_timeout
def save_inputs():
@@ -26,31 +29,35 @@ def add_input(creator, block, timeout_off, timeout_on):
}
def is_acceptable_timeout(timeout):
return (0 < timeout <= max_timeout) or timeout == -1
@hook.command("damnspam")
def on_dammnspam_command(sender, command, label, args):
global changing_input
plugin_header(sender, "DamnSpam")
if not checkargs(sender, args, 1, 2):
msg(sender, "&c/damnspam <seconds> &e(Buttons/Levers)")
msg(sender, "&c/damnspam <seconds after off> <seconds after on> &e(Levers only)")
return True
#Gittestlol
if not is_creative(sender):
msg(sender, "&cYou can only do this in Creative mode.")
return True
if not is_creative(sender):
msg(sender, "&cYou can only do this in Creative mode")
return True
# /damnspam <secs>
destroying_input = False # if both timeouts are 0, the plugin will attempt to remove the protection
if len(args) == 1:
timeout_on = args[0]
try:
timeout_on = round(float(timeout_on), 2)
timeout_off = timeout_on
if 60 >= timeout_on <= -2 or timeout_on == 0:
timeout_on = False
if timeout_on == False:
msg(sender, "&cThe timeout must be within 0-60 or -1.")
if timeout_on == 0:
destroying_input = True
elif not is_acceptable_timeout(timeout_on):
msg(sender, "&cThe timeout must be -1 or within 0 and %d" % max_timeout)
return True
timeout_off = timeout_on
except ValueError:
msg(sender, "&cThe timeout must be a number")
return True
@@ -62,12 +69,10 @@ def on_dammnspam_command(sender, command, label, args):
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.")
if timeout_on == 0 and timeout_off == 0:
destroying_input = True
elif not (is_acceptable_timeout(timeout_on) and is_acceptable_timeout(timeout_off)):
msg(sender, "&cThe timeout must be -1 or within 0 and %d" % max_timeout)
return True
except ValueError:
msg(sender, "&cThe timeout must be a number")
@@ -80,72 +85,111 @@ def on_dammnspam_command(sender, command, label, args):
msg(sender, "&cPlease look at a button or lever while executing this command!")
return True
if location_str(target) in inputs:
global changing_input
target_loc_str = location_str(target)
if target_loc_str in inputs:
changing_input = True # this input already has a timeout
type_str = ttype.lower().replace("_", " ")
# test if player is allowed to build here
test_event = BlockBreakEvent(target, sender)
server.getPluginManager().callEvent(test_event)
build_check = can_build(sender, target)
changing_input = False
if test_event.isCancelled():
msg(sender, "&cYou are not allowed to modify this %s" % str(target.getType()).lower())
if not build_check:
msg(sender, "&cYou are not allowed to modify this %s" % type_str)
return True
# add block to inputs
add_input(sender, target, timeout_off, timeout_on)
if destroying_input:
if target_loc_str not in inputs:
msg(sender, "&cThere is no timeout to remove on this %s (by setting the timeout to 0)" % type_str)
return True
del inputs[target_loc_str]
msg(sender, "&aSuccessfully removed the timeout for this %s" % type_str)
else:
add_input(sender, target, timeout_off, timeout_on)
msg(sender, "&aSuccessfully set a timeout for this %s" % type_str)
save_inputs()
msg(sender, "&aSuccessfully set a timeout for this %s." % ttype.lower().replace("_", " "))
return True
@hook.event("block.BlockBreakEvent", "normal")
def on_block_break(event):
global removing_input
if removing_input:
def check_block_break(break_event, block):
if str(block.getType()) not in accepted_inputs:
return
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):
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
pos_str = location_str(block)
if pos_str not in inputs:
return
sender = break_event.getPlayer()
input_str = ("this %s" if block is break_event.getBlock() else "the %s attached to that block") % str(block.getType()).lower().replace("_", " ")
if not sender.isSneaking():
msg(sender, "&cYou cannot destroy " + input_str)
msg(sender, "&c&nSneak&c and break or set the timeout to 0 if you want to remove it.")
break_event.setCancelled(True)
return
global removing_input
removing_input = True
success = can_build(sender, block)
removing_input = False
if success:
del inputs[pos_str]
save_inputs()
msg(sender, "&aSuccessfully removed %s!" % input_str)
else:
msg(sender, "&cYou are not allowed to remove " + input_str)
break_event.setCancelled(True)
# a dict for levers and buttons, with a tuple of tuples as value. The tuples in the tuple represent
# the data values which the block must have if the block were placed towards the linked blockface to be affected.
# The order is DOWN, UP, NORTH, SOUTH, WEST, EAST
attached_blocks = {
Material.LEVER: ((0, 7, 8, 15), (5, 6, 13, 14), (4, 12), (3, 11), (2, 10), (1, 9)),
Material.STONE_BUTTON: ((0, 8), (5, 6, 7, 13, 14, 15), (4, 12), (3, 11), (2, 10), (1, 9)),
Material.WOOD_BUTTON: ((0, 8), (5, 6, 7, 13, 14, 15), (4, 12), (3, 11), (2, 10), (1, 9)),
}
# returns a generator containing the levers or buttons that would be broken if this block were broken
def get_attached_blocks(block):
for i, face in ((0, BlockFace.DOWN), (1, BlockFace.UP), (2, BlockFace.NORTH), (3, BlockFace.SOUTH), (4, BlockFace.WEST), (5, BlockFace.EAST)):
side = block.getRelative(face)
dvalues = attached_blocks.get(side.getType())
if dvalues is not None and side.getData() in dvalues[i]:
yield side
@hook.event("block.BlockBreakEvent", "highest")
def on_block_break(event):
if removing_input or changing_input or event.isCancelled():
return
block = event.getBlock()
check_block_break(event, event.getBlock())
for affected_block in get_attached_blocks(block):
check_block_break(event, affected_block)
@hook.event("player.PlayerInteractEvent", "normal")
def on_interact(event):
if (str(event.getAction()) == "RIGHT_CLICK_BLOCK") and not event.isCancelled():
sender = event.getPlayer()
sender = event.getPlayer()
block = event.getClickedBlock()
btype = str(block.getType()).lower()
powered = (block.getData() & 0x8) == 0x8 if btype == "lever" else False # data > 7, but this is how bukkit does it
pos_str = location_str(block)
data = inputs.get(pos_str)
if data:
checktime = data["timeout_on"] if powered else data["timeout_off"]
sender = event.getPlayer()
btype = str(block.getType()).lower().replace("_", " ")
if btype == "lever" and block.getData() < 8:
checktime = data["timeout_off"]
else:
checktime = data["timeout_on"]
time_left = data["last_time"] + checktime - now()
if checktime == -1:
event.setCancelled(True)
msg(sender, "&cThis %s is locked permanently by /damnspam." % (btype))
elif data["last_time"] + checktime > now():
elif time_left > 0:
event.setCancelled(True)
msg(sender, "&cThis %s has a damnspam timeout of %ss." % (btype, checktime))
msg(sender, "&cThis %s has a damnspam timeout of %.2fs, with %.2fs left." % (btype, checktime, time_left))
else:
inputs[pos_str]["last_time"] = round(now(), 2)
data["last_time"] = round(now(), 2)

View File

@@ -5,6 +5,10 @@ friends = open_json_file("friends", {}) # {Player_UUID:[List_of_friend
friend_join_sound = "random.orb"
def is_friend_of(player, other):
lst = friends.get(uid(player))
return lst is not None and uid(other) in lst
@hook.event("player.PlayerJoinEvent", "high") # creates sound and sends a bold message on friend join
def fjm(event): # friend join message
@@ -25,6 +29,13 @@ def friendmessage(player, message): # sends a message with a prefix
msg(player, "&7[&aFriends&7] " + message)
def get_player(name):
result = server.getOfflinePlayer(name)
if result is not None and (result.hasPlayedBefore() or result.isOnline()):
return result
return None
def ls(sender):
try:
sender_friends = friends.get(uid(sender), False)
@@ -55,21 +66,25 @@ def add(sender, names):
added = []
notfound = []
friendalready = []
added_self = False
if not sender_id in friends:
friends[sender_id] = []
for name in names:
player = server.getPlayer(name)
player = get_player(name)
if player:
player_id = uid(player)
not_yourself = player != sender
not_yourself = sender != player
if not player_id in friends[sender_id]:
if not_yourself:
friends[sender_id].append(player_id)
added.append(player.getName())
friendmessage(player.getPlayer(), "&a&o%s &aadded you to their friends list" % stripcolors(sender.getDisplayName()))
if player.isOnline():
friendmessage(player.getPlayer(), "&a&o%s &aadded you to their friends list" % stripcolors(sender.getDisplayName()))
else:
added_self = True
else:
friendalready.append(player.getName())
@@ -80,10 +95,10 @@ def add(sender, names):
if added:
friendmessage(sender, "&a&o%s&a added." % ", ".join(added))
if notfound:
friendmessage(sender, "&c&o%s&c not found. (must be online)" % ", ".join(notfound))
friendmessage(sender, "&c&o%s&c not found." % ", ".join(notfound))
if friendalready:
friendmessage(sender, "&c&o%s&c is/are already your friend." % ", ".join(friendalready))
if not not_yourself:
if added_self:
friendmessage(sender, "&cYou can't add yourself to your friends list.")
@@ -94,18 +109,21 @@ def rem(sender, names):
notafriend = []
for name in names:
player = server.Player(name)
player = get_player(name)
if player:
player_id = uid(player)
if player_id in friends.get(sender_id, []):
friends[sender_id].remove(player_id)
removed.append(player.getName())
friendmessage(player.getPlayer(), "&c&o%s &cremoved you from their friends list" % stripcolors(sender.getDisplayName()))
if player.isOnline():
friendmessage(player.getPlayer(), "&c&o%s &cremoved you from their friends list" % stripcolors(sender.getDisplayName()))
else:
notafriend.append(player.getName())
else:
notfound.append(name)
if not friends.get(sender_id, False):
del friends[sender_id]
save_friends()
if removed:
friendmessage(sender, "&a&o%s&a removed." % ", ".join(removed))
@@ -126,35 +144,38 @@ def fhelp(sender):
@hook.command("friends")
def on_friend_command(sender, command, label, args):
if not is_player(sender):
friendmessage(sender, "&c&lYou can't have friends!")
try:
if not is_player(sender):
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
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
except:
error(trace())

107
helpers.py Normal file → Executable file
View File

@@ -6,14 +6,21 @@ import org.bukkit as bukkit
import org.bukkit.Location as Location
import org.bukkit.entity.Player as Player
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause as TeleportCause
import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
import org.bukkit.block as bblock
import org.bukkit.event.entity as entity
import org.bukkit.command.ConsoleCommandSender
from org.bukkit.entity import *
#Imports for async query
from secrets import *
import mysqlhack
from com.ziclix.python.sql import zxJDBC
import threading
from traceback import format_exc as trace
helpers_version = "2.0.0"
shared = {} # this dict can be used to share stuff across modules
server = bukkit.Bukkit.getServer()
@@ -126,7 +133,7 @@ def runas(player, cmd):
player.chat("/" + cmd)
else:
server.dispatchCommand(player, cmd)
def is_player(obj):
"""
@@ -135,6 +142,15 @@ def is_player(obj):
return (isinstance(obj, Player))
def can_build(player, block):
"""
return True if the player can change/build at the location of given block
"""
event = BlockBreakEvent(block, player)
server.getPluginManager().callEvent(event)
return not event.isCancelled()
def checkargs(sender, args, amin, amax):
"""
check if a command has a valid amount of args, otherwise notify the sender
@@ -186,6 +202,30 @@ def known_player(player):
"""
return player.hasPlayedBefore()
"""
Runs a async query, calls target function with fetchall as an argument, it will be an empty list if there is nothing to fetch.
(So make sure your function takes that argument.)
If you want your function to run sync in the case you are doing something spigot wouldn't like to be async use the bukkit scheduler.
Example can be found in loginsecurity.py
"""
def async_query(mysql_database,query,query_args,target,*target_args,**target_kwargs):
def async_query_t(mysql_database,query,query_args,target,target_args,target_kwargs):
db_conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
db_curs = db_conn.cursor()
db_curs.execute(query,query_args)
db_conn.commit()
fetchall = db_curs.fetchall()
db_curs.close()
db_conn.close()
target(fetchall,target_args,target_kwargs)
t = threading.Thread(target=async_query_t,args=(mysql_database,query,query_args,target,target_args,target_kwargs))
t.daemon = True
t.start()
def open_json_file(filename, default = None):
"""
@@ -218,9 +258,66 @@ def toggle(player, ls, name = "Toggle", add = None):
If add is given, True explicitely adds it whereas False removes it
"""
pid = uid(player)
if pid in ls or add == False:
if pid in ls or add is False:
ls.remove(pid)
msg(player, "&a%s turned off!" % name)
elif add != False:
elif add is not False:
ls.append(pid)
msg(player, "&a%s turned on!" % name)
msg(player, "&a%s turned on!" % name)
def send_JSON_message(playername, message):
bukkit.Bukkit.getServer().dispatchCommand(bukkit.Bukkit.getServer().getConsoleSender(), "tellraw " + playername + " " + message)
# Allows to check if a String is a valid IPv4 or not. Accepts any string, returns true if the String is a valid IPv4
def is_ip(tocheck):
subsets = ["","","",""]
i = 0
for j in range(0,len(tocheck)):
if not (tocheck[j] in "0123456789."):
return False
elif tocheck[j] == ".":
i += 1
if (i >= 4):
return False
else:
subsets[i] += tocheck[j]
if not (i == 3):
return False
for j in range(0,3):
if not ((int(subsets[j]) >= 0) & (int(subsets[j]) <= 255)):
return False
return True
# Allows the use of e.g. numeric permission nodes like "permission.amount.5" and similar.
# To get the data fetch the player and the start of the permission node, looking like "permission.amount."
def get_permission_content(player, permnode, default_value = None):
try:
perms = player.getEffectivePermissions()
for perm in perms:
if str(perm.getPermission()).startswith(permnode):
return str(perm.getPermission())[len(permnode):]
return default_value
except:
error(trace())
def array_to_list(array):
return_list = []
for a in array:
return_list.append(a)
return return_list
#debug wrapper
def debug(func):
def wrap(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
error(trace())
return None
return wrap

318
imbusy.py Normal file
View File

@@ -0,0 +1,318 @@
"""
This plugin permits users to
send a command that renders
them "busy", not letting them
to get tpa requests or direct
messages, except from console.
On restart, all busy data will
be cleared.
"""
from helpers import *
from friends import is_friend_of
import org.bukkit.command.Command as Command
from time import time as now
imbusy_version = "v1.1.0"
base_permission = "utils.imbusy" # for /busy status
use_permission = "utils.imbusy.use" # for being busy
override_permission = "utils.imbusy.override" # for being able to bother busy people
busy_status_change_timeout = 15 # seconds
busy_players = {} # name : (status, timeout_expire)
# possible statuses: True if SUPER busy, False if normal busy, None if not busy
@hook.command("imbusy",
aliases = ["busy"],
usage = "/<command> [on, off, status/check]",
description = "Offers control over your busy status"
)
@debug
def on_busy_command(sender, cmd, label, args):
if not is_player(sender):
msg(sender, "&7Sorry, Console cannot be busy")
return True
plugin_header(recipient = sender, name = "I'M BUSY!")
if not sender.hasPermission(base_permission):
noperm(sender)
return True
if len(args) == 0:
return toggle(sender)
arg0 = args[0].lower()
if arg0 == "on":
return on(sender)
if arg0 == "off":
return off(sender)
if arg0 in ("status", "check"):
return status(sender, args[1:])
if arg0 == "super":
return super_cmd(sender)
return help(sender)
def change_status(target, status):
target_name = target.getName()
old_status = None
if target_name in busy_players:
value = busy_players[target_name]
time_left = value[1] - now()
if time_left > 0:
msg(target, "&cYou must wait %.2fs untill you can change your status" % time_left)
return
old_status = value[0]
if old_status is status:
if status is True:
msg(target, "&cYou are already SUPER busy")
elif status is False:
msg(target, "&cYou are already busy")
else:
msg(target, "&cYou weren't busy yet")
return
busy_players[target_name] = (status, now() + busy_status_change_timeout)
if status is True:
broadcast(None, target.getDisplayName() + " &7is now SUPER busy")
elif status is False:
broadcast(None, target.getDisplayName() + " &7is now busy")
else:
broadcast(None, target.getDisplayName() + " &7is not busy anymore")
def get_status(target):
return busy_players.get(target.getName(), (None,))[0]
def toggle(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True
if get_status(sender) is None:
change_status(sender, False)
else:
change_status(sender, None)
return True
def help(sender):
msg(sender, "Let's you put yourself in busy status, preventing pms and tpa requests from other players")
msg(sender, "\n&eCommands:")
msg(sender, "&e/busy &7- Toggles busy status")
msg(sender, "&e/busy on &7- Turns on busy status")
msg(sender, "&e/busy off &7- Turns off busy status")
msg(sender, "&e/busy status [player] &7- shows your or [player]'s current busy status")
msg(sender, "&e/busy super &7- sets your status to SUPER busy such that even friends can not bother you")
return True
def on(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True
change_status(sender, False)
return True
def off(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True
change_status(sender, None)
return True
def status(sender, args):
if not sender.hasPermission(base_permission):
noperm(sender)
return True
if len(args) == 0:
target = sender
else:
target = server.getPlayer(args[0])
if target is None:
msg(sender, "&cThat player is not online")
return True
status = get_status(target)
if status is True:
status_str = "SUPER busy"
elif status is False:
status_str = "busy"
else:
status_str = "not busy"
msg(sender, "&7%s currently %s" % ("You are" if target is sender else "Player %s&7 is" % target.getDisplayName()), status_str)
return True
def super_cmd(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True
change_status(sender, True)
return True
@hook.event("player.PlayerQuitEvent", "lowest")
def on_player_leave(event):
player_name = event.getPlayer().getName()
if player_name in busy_players:
del busy_players[player_name]
# Block any bothering if should be. If a busy player msgs someone else, they can be replied to and /msg'd as well.
# It's not entirely perfect in that regard as the ability to reply is lost when you are /msg'd by someone else.
reply_targets = {} # name : (reply_target_name, true if initiated by target)
def can_send(sender, target):
if target is sender or sender.hasPermission(override_permission):
return True
status = get_status(target)
if status is None:
return True
return status is False and is_friend_of(target, sender)
def whisper(sender, target_name):
target = server.getPlayer(target_name)
if target is not None:
sender_name = sender.getName()
if not can_send(sender, target):
value = reply_targets[sender_name]
if value[0] != target_name or value[1] is False:
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
reply_targets[sender_name] = (target_name, False)
reply_targets[target_name] = (sender_name, True)
return True
def reply(sender):
sender_name = sender.getName()
if sender_name in reply_targets:
value = reply_targets[sender_name]
target = server.getPlayer(value[0])
if target is not None:
if not value[1] and not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
reply_targets[target.getName()] = (sender_name, True)
return True
class CommandWrapper(Command):
def __init__(self, wrapped, checker):
Command.__init__(self, wrapped.getName())
self.setDescription(wrapped.getDescription())
self.setPermission(wrapped.getPermission())
self.setUsage(wrapped.getUsage())
self.setAliases(wrapped.getAliases())
self.wrapped = wrapped
self.checker = checker
def execute(self, sender, label, args):
try:
if not is_player(sender) or self.checker(sender, args):
return self.wrapped.execute(sender, label, args)
except:
error(trace())
return True
def tabComplete(self, sender, alias, args):
return self.wrapped.tabComplete(sender, alias, args)
def msg_command_checker(sender, args):
return len(args) <= 1 or whisper(sender, args[0])
def reply_command_checker(sender, args):
return len(args) == 0 or reply(sender)
def tpa_command_checker(sender, args):
if len(args) == 0:
return True
target = server.getPlayer(args[0])
if target is not None and not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
return True
def tpahere_command_checker(sender, args):
return tpa_command_checker(sender, args)
def mail_command_checker(sender, args):
if len(args) < 3 or args[0].lower() != "send":
return True
target = server.getPlayer(args[1])
if target is not None and not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
return True
@hook.event("player.PlayerCommandPreprocessEvent", "monitor")
def on_player_command_preprocess(event):
message = event.getMessage().split(" ")
if len(message) > 1 and message[0].lower() in ("/tell", "/minecraft:tell") and not whisper(event.getPlayer(), message[1]):
event.setCancelled(True)
def replace_ess_commands():
try:
map_field = server.getPluginManager().getClass().getDeclaredField("commandMap")
map_field.setAccessible(True)
command_map = map_field.get(server.getPluginManager())
commands_field = command_map.getClass().getDeclaredField("knownCommands")
commands_field.setAccessible(True)
map = commands_field.get(command_map)
ess_msg_cmd = map.get("essentials:msg")
ess_reply_cmd = map.get("essentials:reply")
ess_tpa_cmd = map.get("essentials:tpa")
ess_tpahere_cmd = map.get("essentials:tpahere")
ess_mail_cmd = map.get("essentials:mail")
msg_cmd_wrapper = CommandWrapper(ess_msg_cmd, msg_command_checker)
reply_cmd_wrapper = CommandWrapper(ess_reply_cmd, reply_command_checker)
tpa_cmd_wrapper = CommandWrapper(ess_tpa_cmd, tpa_command_checker)
tpahere_cmd_wrapper = CommandWrapper(ess_tpahere_cmd, tpahere_command_checker)
mail_cmd_wrapper = CommandWrapper(ess_mail_cmd, mail_command_checker)
iterator = map.entrySet().iterator()
wrapped_commands = []
while iterator.hasNext():
entry = iterator.next()
value = entry.getValue()
changed = True
if value is ess_msg_cmd:
entry.setValue(msg_cmd_wrapper)
elif value is ess_reply_cmd:
entry.setValue(reply_cmd_wrapper)
elif value is ess_tpa_cmd:
entry.setValue(tpa_cmd_wrapper)
elif value is ess_tpahere_cmd:
entry.setValue(tpahere_cmd_wrapper)
elif value is ess_mail_cmd:
entry.setValue(mail_cmd_wrapper)
else:
changed = False
if changed:
wrapped_commands.append(entry.getKey())
info("[imbusy] wrapped commands: /" + ", /".join(wrapped_commands))
except:
error("[Imbusy] Failed to wrap essentials commands")
error(trace())

108
iptracker.py Executable file
View File

@@ -0,0 +1,108 @@
import mysqlhack
import org.bukkit as bukkit
import json
from java.util import UUID as UUID
from helpers import *
from org.bukkit import *
from traceback import format_exc as trace
from iptracker_secrets import *
iptrack_permission = "utils.iptrack"
iptrack_version = "1.1.0"
@hook.event("player.PlayerJoinEvent", "low")
def on_player_join(event):
t = threading.Thread(target=on_player_join_thread, args=(event, ))
t.daemon = True
t.start()
def on_player_join_thread(event):
player = event.getPlayer()
ip = player.getAddress().getHostString()
uuid = uid(player)
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("SELECT ips FROM uuid2ips WHERE uuid = ?", (uuid, ))
results = curs.fetchall()
if len(results) == 0:
ips = []
else:
ips = json.loads(results[0][0])
curs.execute("SELECT uuids FROM ip2uuids WHERE ip = ?", (ip, ))
results = curs.fetchall()
if len(results) == 0:
uuids = []
else:
uuids = json.loads(results[0][0])
new_ip_entry = (len(ips) == 0)
new_uuid_entry = (len(uuids) == 0)
if ip not in ips:
ips.append(ip)
if new_ip_entry:
curs.execute("INSERT INTO uuid2ips VALUES (?,?)", (uuid, json.dumps(ips), ))
else:
curs.execute("UPDATE uuid2ips SET ips = ? WHERE uuid = ?", (json.dumps(ips), uuid, ))
if uuid not in uuids:
uuids.append(uuid)
if new_uuid_entry:
curs.execute("INSERT INTO ip2uuids VALUES (?,?)", (ip, json.dumps(uuids), ))
else:
curs.execute("UPDATE ip2uuids SET uuids = ? WHERE ip = ?", (json.dumps(uuids), ip, ))
conn.commit()
curs.close()
conn.close()
@hook.command("getinfo")
def on_getinfo_command(sender, args):
t = threading.Thread(target=on_getinfo_command_thread, args=(sender, args))
t.daemon = True
t.start()
def on_getinfo_command_thread(sender, args):
if(sender.hasPermission(iptrack_permission)):
if not checkargs(sender, args, 1, 1):
return False
else:
if is_ip(args[0]):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("SELECT uuids FROM ip2uuids WHERE ip = ?", (args[0], ))
results = curs.fetchall()
curs.close()
conn.close()
if len(results) == 0:
msg(sender, "IP " + args[0] + " is not registered in the database, maybe you got a number wrong?")
else:
uuids = json.loads(results[0][0])
msg(sender, "IP " + args[0] + " was seen with " + str(len(uuids)) + " different Accounts:")
for i in range(0, len(uuids)):
p=Bukkit.getOfflinePlayer(UUID.fromString(uuids[i]))
if is_player(sender):
send_JSON_message(sender.getName(), '["",{"text":"' + p.getName() + ' - (uuid: ' + uuids[i] + '","color":"gold","clickEvent":{"action":"run_command","value":"/getinfo ' + p.getName() + '"},"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"To search for ' + p.getName() + ' in the database, simply click the name!","color":"gold"}]}}}]')
else:
msg(sender,p.getName() + " - (uuid: " + uuids[i] + ")")
else:
target = Bukkit.getOfflinePlayer(args[0])
uuid = target.getUniqueId()
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("SELECT ips FROM uuid2ips WHERE uuid = ?", (uuid.toString(), ))
results = curs.fetchall()
curs.close()
conn.close()
if len(results) == 0:
msg(sender, "Player " + args[0] + " is not registered in the database, maybe you misspelled the name?")
else:
ips = json.loads(results[0][0])
msg(sender, "Player " + args[0] + " was seen with " + str(len(ips)) + " different IPs:")
for i in range(0, len(ips)):
if is_player(sender):
send_JSON_message(sender.getName(), '["",{"text":"' + ips[i] + '","color":"gold","clickEvent":{"action":"run_command","value":"/getinfo ' + ips[i] + '"},"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"To search for the IP ' + ips[i] + ' in the database, simply click the IP!","color":"gold"}]}}}]')
else:
msg(sender,ips[i])
else:
noperm(sender)
return True

View File

@@ -7,14 +7,14 @@ from login_secrets import * #Don't forget to make login_secrets aswell
import mysqlhack
from com.ziclix.python.sql import zxJDBC
from java.lang import Runnable
from player import get_py_player, py_players
wait_time = 30 #seconds
admin_perm = "utils.loginsecurity.admin"
min_pass_length = 8
blocked_events = ["block.BlockBreakEvent", "block.BlockPlaceEvent", "player.PlayerMoveEvent","player.AsyncPlayerChatEvent"]
blocked_events = ["block.BlockBreakEvent", "block.BlockPlaceEvent", "player.AsyncPlayerChatEvent"]
logging_in = {}
def matches(password,user):
@@ -24,86 +24,131 @@ def matches(password,user):
def matches_thread(password, user):
hashed = get_pass(uid(user))
py_player = get_py_player(user)
if crypt.verify(password, hashed):
if user.getName() in logging_in:
del logging_in[user.getName()]
if py_player.logging_in:
py_player.logging_in = False
msg(user, "&aLogged in successfully!")
else:
if user.getName() in logging_in:
msg(user, "&cInvalid password")
if py_player.logging_in:
msg(user, "&cInvalid password!")
@simplecommand("cgpass",
usage = "<password> <new password>",
description = "Changes your password",
senderLimit = 0,
helpNoargs = True)
usage = "<password> <new password>",
description = "Changes your password",
senderLimit = 0,
helpNoargs = True)
def change_pass_command(sender, command, label, args):
if sender.getName() in logging_in:
py_player = get_py_player(sender)
if py_player.logging_in:
return "&cYou are not logged in"
if not len(args) == 2:
return "&cInvalid arguments"
password = args[0]
new_password = args[1]
uuid = uid(sender)
if is_registered(uuid):
change_pass(uuid, crypt.encrypt(new_password, rounds=200000, salt_size=16))
return "&aPassword changed"
return "&cYou are not registered"
@simplecommand("login",
usage = "<password>",
usage = "<password>",
description = "Logs you in if <password> matches your password.",
senderLimit = 0,
senderLimit = 0,
helpNoargs = True)
def login_command(sender, command, label, args):
py_player = get_py_player(sender)
if not py_player.logging_in:
msg(sender,"&cAlready logged in!")
password = args[0]
matches(password, sender)
@simplecommand("register",
usage = "<password>",
description = "Registers you with <password>. Next time you join, log in with /login",
senderLimit = 0,
helpNoargs = True)
def register_command(sender, command, label, args):
py_player = get_py_player(sender)
if len(args) > 1:
return "&cPassword can only be one word!"
uuid = uid(sender)
if is_registered(uuid):
return "&cYou are already registered!"
password = args[0]
if len(password) < min_pass_length:
return "&cThe password has to be made up of at least %s characters!" % min_pass_length
create_pass(uuid, password)
return "&cPassword set. Use /login <password> upon join."
@simplecommand("rmpass",
description = "Removes your password if the password matches",
senderLimit = 0,
amax = 0,
helpNoargs = False)
def rmpass_command(sender, command, label, args):
if sender.getName() in logging_in:
py_player = get_py_player(sender)
if py_player.logging_in:
return "&cYou are not logged in"
if not is_registered(uid(sender)):
return "&cYou are not registered!"
if not sender.getName() in logging_in:
if py_player.logging_in == False:
delete_pass(uid(sender))
return "&aPassword removed successfully. You will not be prompted anymore."
return "&cFailed to remove password, please contact a staff member"
@simplecommand("rmotherpass",
aliases = ["lacrmpass"],
usage = "<user>",
senderLimit = -1,
description = "Removes password of <user> and sends them a notification",
helpNoargs = True)
def rmotherpass_command(sender, command, label, args):
if sender.getName() in logging_in:
py_player = get_py_player(sender)
if py_player.logging_in:
return "&cYou are not logged in"
if not sender.hasPermission(admin_perm):
noperm(sender)
return
user = server.getOfflinePlayer(args[0])
if is_registered(uid(user)):
delete_pass(uid(user))
runas(server.getConsoleSender(), colorify("mail send %s &cYour password was reset by a staff member. Use &6/register&c to set a new one." % user.getName()))
@@ -159,19 +204,27 @@ def delete_pass(uuid):
curs.close()
conn.close()
@hook.event("player.PlayerJoinEvent", "high")
@hook.event("player.PlayerJoinEvent", "highest")
def on_join(event):
user = event.getPlayer()
py_player = get_py_player(event.getPlayer())
if is_registered(uid(user)):
msg(event.getPlayer(), "&6You will be disconnected after 60 seconds if you don't &alogin")
msg(event.getPlayer(), "&4You will be disconnected after 60 seconds if you don't &alogin")
msg(user, "&cUse /login <password>")
logging_in[user.getName()] = time.time()
py_player.logging_in = True
py_player.login_time = time.time()
return
elif user.hasPermission(admin_perm):
pass #Do what? force them to make a password, lots of code, maybe just message us on slack?
#This shouldn't be needed anymore as py_player gets removed anyway.
"""
@hook.event("player.PlayerQuitEvent", "high")
def on_quit(event):
if event.getPlayer().getName() in logging_in:
del logging_in[event.getPlayer().getName()]
"""
##Threading start
class kick_class(Runnable):
@@ -187,15 +240,18 @@ def kick_thread():
while True:
time.sleep(1)
now = time.time()
for name, jointime in logging_in.iteritems():
if now - jointime > wait_time:
player = server.getPlayer(name)
kick = kick_class(player)
server.getScheduler().runTask(server.getPluginManager().getPlugin("RedstonerUtils"), kick)
if name in logging_in:
del logging_in[name]
break
for py_player in py_players:
if py_player.logging_in:
if now - py_player.login_time > wait_time:
player = py_player.player
kick = kick_class(player)
server.getScheduler().runTask(server.getPluginManager().getPlugin("RedstonerUtils"), kick)
"""if name in logging_in:
del logging_in[name]
break
"""
thread = threading.Thread(target = kick_thread)
@@ -206,6 +262,21 @@ thread.start()
for blocked_event in blocked_events:
@hook.event(blocked_event, "high")
def on_blocked_event(event):
user = event.getPlayer()
if user.getName() in logging_in:
user = get_py_player(event.getPlayer())
if user.logging_in:
event.setCancelled(True)
@hook.event("player.PlayerCommandPreprocessEvent","normal")
def pre_command_proccess(event):
player = get_py_player(event.getPlayer())
if player.logging_in:
args = event.getMessage().split(" ")
if not args[0].lower() == "/login":
msg(player.player, "&4You need to login before you do that!")
event.setCancelled(True)
@hook.event("player.PlayerMoveEvent","normal")
def player_move(event):
user = get_py_player(event.getPlayer())
if user.logging_in:
event.setTo(event.getFrom())

41
main.py
View File

@@ -19,12 +19,19 @@ except:
@hook.enable
def on_enable():
if "blockplacemods" in shared["modules"]:
shared["modules"]["blockplacemods"].schedule_torch_breaker()
if "imbusy" in shared["modules"]:
shared["modules"]["imbusy"].replace_ess_commands()
if "serversigns" in shared["modules"]:
shared["modules"]["serversigns"].check_all_signs_and_force_commands()
info("RedstonerUtils enabled!")
@hook.disable
def on_disable():
shared["modules"]["reports"].stop_reporting()
if "reports" in shared["modules"]:
shared["modules"]["reports"].stop_reporting()
info("RedstonerUtils disabled!")
@@ -38,10 +45,14 @@ shared["load_modules"] = [
"adminchat",
# Adds /badge, allows to give players achievements
"badges",
# Adds a few block placement corrections/mods
"blockplacemods",
# Adds a few block placement corrections/mods
"blockplacemods",
# Adds /calc, toggles automatic solving of Math expressions in chat
"calc",
# Adds aliasing of chat words
"chatalias",
# For players to point friends
"friends",
# Plugin to locate laggy chunks. /lc <n> lists chunks with more than n entities
"lagchunks",
# Adds /report and /rp, Stores reports with time and location
@@ -52,6 +63,8 @@ shared["load_modules"] = [
"webtoken",
# Adds /lol, broadcasts random funyy messages. A bit like the splash text in the menu
"saylol",
# Adds /signalstrength, lets you request a signal strength and an amount of items will be inserted into target container to meet that strength.
"signalstrength",
# Shows the owner of a skull when right-clicked
"skullclick",
# Adds /listen, highlights chat and plays a sound when your name was mentioned
@@ -70,6 +83,8 @@ shared["load_modules"] = [
"check",
# Adds /an, a command you can use to share thoughts/plans/news
"adminnotes",
# Adds busy status to players
"imbusy",
# Adds /imout, displays fake leave/join messages
"imout",
#adds snowbrawl minigame
@@ -79,7 +94,25 @@ shared["load_modules"] = [
# Replacement for LoginSecurity
"loginsecurity",
# Centralized Player class
"playermanager"
"player",
# Servercontrol extension for telnet access to logs/AC
#"servercontrol",
# Script helper plugin
"scriptutils",
# Per-player notes
"tag",
# vanish toggle module - temporary fix
#"vanishfix",
# obisidian mining punishment plugin
"punishments",
# a simple replacement for the buggy essentials /vanish
"vanish",
# ip-tracking utility - disabled as of instability
#"iptracker",
#server signs for everyone
"serversigns",
# Makes player's names colored, sorts tab list by rank
"nametags"
]
shared["modules"] = {}
for module in shared["load_modules"]:

View File

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

58
misc.py
View File

@@ -6,7 +6,8 @@ from sys import exc_info
import thread
import org.bukkit.inventory.ItemStack as ItemStack
import org.bukkit.Bukkit as Bukkit
from basecommands import simplecommand
from basecommands import simplecommand, Validate
import java.util.Arrays as Arrays
@@ -70,7 +71,6 @@ def cmd_event2(event):
""" Disabled while builder can't access Trusted
@hook.event("player.PlayerGameModeChangeEvent", "low")
def on_gamemode(event):
@@ -115,8 +115,20 @@ def rs_material_broken_by_flow(material):
return length > 1 and (parts[0] == "DIODE" or parts[1] in ("TORCH", "WIRE", "BUTTON", "HOOK") or (length == 3 and parts[1] == "COMPARATOR"))
@hook.event("player.PlayerInteractEvent")
def on_interact(event):
if (not event.isCancelled()
and str(event.getAction()) == "RIGHT_CLICK_BLOCK"
and str(event.getMaterial()) in ("REDSTONE_COMPARATOR_OFF", "REDSTONE_COMPARATOR_ON")
and not can_build(player, event.getClickedBlock())
):
event.setCancelled(True)
sudo_blacklist = ["pyeval", "script_backup_begin", "script_backup_end", "script_backup_error", "script_backup_database_begin", "script_backup_database_dumps", "script_backup_database_end",
"script_backup_database_error", "script_backup_database_abort", "script_trim", "script_trim_result", "script_spigot_update", "script_disk_filled", "script_restart", "script_restart_abort",
"script_stop", "script_stop_abort", "script_shutdown", "stop", "esudo", "essentials:sudo", "sudo", "essentials:esudo"]
@simplecommand("sudo",
usage = "<player> [cmd..]",
description = "Makes <player> write [cmd..] in chat",
@@ -128,6 +140,9 @@ def on_sudo_command(sender, command, label, args):
msg(sender, "&2[SUDO] &rRunning '&e%s&r' as &3%s" % (cmd, target))
is_cmd = cmd[0] == "/"
is_console = target.lower() in ["server", "console"]
first_cmd = (args[1])[1:] if is_cmd else None
if first_cmd in sudo_blacklist and (is_player(sender) and uid(sender) not in pythoners):
return "&cYou can't sudo this command"
if is_console:
server.dispatchCommand(server.getConsoleSender(), cmd[1:] if is_cmd else cmd)
return None
@@ -139,7 +154,7 @@ def on_sudo_command(sender, command, label, args):
@simplecommand("me",
@simplecommand("me",
usage = "[message..]",
description = "Sends a message in third person",
helpNoargs = True)
@@ -158,7 +173,8 @@ def on_pluginversions_command(sender, command, label, args):
"""
try:
plugin_header(sender, "Plugin versions")
plugins = [pl.getDescription() for pl in list(ArrayList(java_array_to_list(server.getPluginManager().getPlugins())))]
raw_plugins = server.getPluginManager().getPlugins() # Plugin[]
plugins = [raw_plugins[i].getDescription() for i in range(len(raw_plugins))]
info(type(plugins[0]).__name__)
plugins.sort(key = lambda pl: pl.getDescription().getName())
msg(sender, "&3Listing all " + str(len(plugins)) + " plugins and their version:")
@@ -196,11 +212,20 @@ def eval_thread(sender, code):
msg(sender, ">>> %s: %s" % (eclass.__name__, e) + "\n ", False, "c")
thread.exit()
pythoners = (
"e452e012-2c82-456d-853b-3ac8e6b581f5", # Nemes
"ae795aa8-6327-408e-92ab-25c8a59f3ba1", # jomo
"d2693e91-93e1-4e3f-929f-f38e1ce8df03", # Pepich1851
"51f2ad3c-6cc8-40ea-aa2b-f25970316921" # Dico200
)
@simplecommand("pyeval",
usage = "[code..]",
description = "Runs python [code..] and returns the result",
helpNoargs = True)
def on_pyeval_command(sender, command, label, args):
if is_player(sender) and uid(sender) not in pythoners:
return noperm(sender)
msg(sender, " ".join(args), False, "e")
thread.start_new_thread(eval_thread, (sender, " ".join(args)))
return None
@@ -245,6 +270,31 @@ def on_modules_command(sender, command, label, args):
msg(sender, ", ".join([(("&a" if mod in shared["modules"] else "&c") + mod) for mod in shared["load_modules"]]))
@simplecommand("warn",
usage = "",
description = "Warns everybody on the server that you will cause lag shortly",
amax = 0,
helpSubcmd = True)
def warn_command(sender, command, label, args):
if sender.hasPermission("utils.warn"):
broadcast(None, " &b= &2&lLag incoming! &r-%s" % sender.getDisplayName())
else:
noperm(sender)
@simplecommand("warnp",
usage = "",
description = "Warns everybody on the server that you might cause lag shortly",
amax = 0,
helpSubcmd = True)
def warnp_command(sender, command, label, args):
if sender.hasPermission("utils.warnp"):
broadcast(None, " &b= &2&lPossible lag incoming! &r-%s" % sender.getDisplayName())
else:
noperm(sender)
""" Something I'm planning for schematics
@hook.event("player.PlayerCommandPreprocessEvent", "low")
def on_command(event):

37
nametags.py Executable file
View File

@@ -0,0 +1,37 @@
from helpers import *
##############################################################
# #
# This module automatically puts people in the corresponding #
# scoreboard team so that their name is colored properly and #
# tab will be nicely sorted. #
# #
##############################################################
ranks = ["visitor", "member", "builder", "trusted", "trainingmod", "mod", "admin"]
# prefixes are used for sorting in the tab list
prefixes = {"admin":"a", "mod":"b", "trainingmod":"c", "trusted":"d", "builder":"e", "member":"f","visitor":"g"}
@hook.event("player.PlayerJoinEvent", "low")
def on_player_join(event):
player = event.getPlayer()
team = get_team(player)
if team:
cmd = "scoreboard teams join %s %s" % (team, player.getName())
server.dispatchCommand(server.getConsoleSender(), cmd)
def get_rank(player):
player_rank = None
for rank in ranks:
if not player.hasPermission("group.%s" % rank):
break
player_rank = rank
if not player_rank:
warn("Couldn't find rank for player %s" % player.getName())
return player_rank
def get_team(player):
rank = get_rank(player)
if rank:
prefix = prefixes.get(rank)
return "_".join([prefix, rank])

View File

@@ -1,27 +1,30 @@
from helpers import *
players = []
py_players = []
class py_player:
def __init__(player):
self.player = player
#Properties TODO
#Example:
self.logging_in = False
def __init__(self,player):
self.player = player
self.logging_in = False
self.login_time = 0
def get_py_player(player):
py_player = players[players.index(player)]
return py_player
#py_player = py_players[py_players.index(player)]
for py_player in py_players:
if py_player.player.getName() == player.getName():
return py_player
@hook.event("player.PlayerJoinEvent","highest")
@hook.event("player.PlayerJoinEvent","lowest")
def on_join(event):
player = py_player(event.getPlayer())
players.append(player)
player = py_player(event.getPlayer())
py_players.append(player)
print str(len(py_players))+event.getPlayer().getName()
@hook.event("player.PlayerQuitEvent","highest")
def on_leave(event):
players.remove(get_py_player(event.getPlayer()))
player = get_py_player(event.getPlayer())
if player in py_players:
py_players.remove(player)

View File

@@ -2,4 +2,3 @@ name: RedstonerUtils
main: main.py
version: 3.1.0
author: redstone_sheep

View File

@@ -5,7 +5,11 @@ from java.util.UUID import fromString as juuid
toggle_dict = {}
permission = "utils.pmtoggle"
@hook.command("tm")
@hook.command("pmtoggle",
aliases = ["tm", "mt", "tmsg", "msgt", "pmt", "tpm"],
usage = "/<command> [player]",
description = "Toggle automatic sending of messages"
)
def on_toggle_message_command(sender, command, label, args):
if not sender.hasPermission(permission) or not is_player(sender):
noperm(sender)

129
punishments.py Normal file
View File

@@ -0,0 +1,129 @@
from helpers import *
from java.util.UUID import fromString as juuid
import org.bukkit.Material as Material
spawn_world = "Spawn"
punish_world = "Punishments"
slave_perm = "utils.minerslaves"
slaves = []
def save_slaves():
buf = []
for slave in slaves:
buf.append(slave.get_data())
save_json_file("miner_slaves", buf)
def load_slaves():
buf = open_json_file("miner_slaves", [])
for data in buf:
slave = Slave(True, None, None)
slave.load_data(data)
slaves.append(slave)
def get_slave(player):
for slave in slaves:
if slave.get_uuid() == player:
return slave
return None
class Slave(object):
def __init__(self, from_file, player, amount):
if from_file:
self.players = None
self.blocks = None
return
slave = get_slave(uid(player))
if slave != None:
slave.set_blocks(slave.get_blocks() + amount)
else:
self.player = uid(player)
self.blocks = amount
slaves.append(self)
def get_uuid(self):
return self.player
def get_blocks(self):
return self.blocks
def set_blocks(self, amount):
self.blocks = amount
def update(self):
self.blocks -= 1
if self.blocks <= 0:
server.getPlayer(juuid(self.get_uuid())).teleport(server.getWorld(spawn_world).getSpawnLocation())
slaves.remove(self)
save_slaves()
def get_data(self):
return {
"player": self.player,
"amount": self.blocks
}
def load_data(self, data):
self.player = str(data["player"])
self.blocks = int(data["amount"])
load_slaves()
@hook.event("block.BlockBreakEvent", "low")
def event(event):
if event.getPlayer().getWorld().getName() != punish_world:
return
slave = get_slave(uid(event.getPlayer()))
if slave != None and event.getBlock().getType() == Material.OBSIDIAN:
slave.update()
@hook.command("miner")
def command(sender, cmd, label, args):
if not sender.hasPermission(slave_perm):
noperm(sender)
return True
if len(args) == 0 or (len(args) != 1 and args[0] == "list") or (len(args) != 2 and args[0] == "rem") or (len(args) != 3 and args[0] == "add"):
msg(sender, "&e-&a /miner add/rem/list <name> <amount>")
return True
if args[0] == "add":
try:
int(args[2])
except:
msg(sender, "&cArgument <amount> is not a number")
return True
if args[0] == "list":
if len(slaves) == 0:
msg(sender, "&e-&a There are no people mining obsidian")
return True
for slave in slaves:
msg(sender, "&e-&a %s: %s blocks" % (server.getOfflinePlayer(juuid(slave.get_uuid())).getName(), slave.get_blocks()))
return True
elif args[0] == "add":
player = server.getOfflinePlayer(str(args[1]))
if player.isOnline():
player.teleport(server.getWorld(punish_world).getSpawnLocation())
Slave(False, player, int(args[2]))
save_slaves()
msg(player, "&e-&a You have been punished, mine %s blocks of obsidian to get out!" % args[2])
msg(sender, "&e-&a Player %s has been added into punishments for %s blocks of obsidian" % (player.getName(), args[2]))
else:
msg(sender, "&cYou can only punish online players")
return True
elif args[0] == "rem":
player = server.getOfflinePlayer(str(args[1]))
if player.isOnline():
slave = get_slave(uid(player))
if slave != None:
server.getPlayer(juuid(slave.get_uuid())).teleport(server.getWorld(spawn_world).getSpawnLocation())
slaves.remove(slave)
save_slaves()
else:
msg(sender, "&e-&a Player not in punishments")
else:
msg(sender, "&cYou can only remove online players")
return True
else:
msg(sender, "&e-&a /miner add/rem/list <name> <amount>")
return True

View File

@@ -5,7 +5,7 @@ from random import randrange
lols = open_json_file("lol", [])
timeout = 15
last_msg = 0
list_limit = 20
def save_lols():
@@ -69,8 +69,26 @@ def on_lol_command(sender, command, label, args):
noperm(sender)
elif cmd == "list":
for i in range(len(lols)):
arg1 = args[1] if len(args) > 1 else None
if not arg1:
arg1 = "1"
if not arg1.isdigit():
msg(sender, "&cInvalid argument \"%s\"" % arg1)
return True
if int(arg1) == 0:
msg(sender, "&cPage 0 does not exist")
return True
arg1 = int(arg1) - 1
offset = list_limit * arg1
if offset > len(lols):
msg(sender, "&cNot a valid page (too high).")
return True
msg(sender, " &9&nLol list page %s" % str(arg1 + 1)) #"\t" symbol displays weirdly, hence the 4 spaces
for i in range(offset, min(offset + list_limit, len(lols))):
msg(sender, "&a%s: &e%s" % (str(i).rjust(3), lols[i]))
msg(sender, "")
msg(sender, "&eFor a specific page, type &a/lol list <page>&e.")
msg(sender, "") #emptyline
elif cmd == "search":
if sender.hasPermission("utils.lol.search"):
@@ -95,9 +113,9 @@ def on_lol_command(sender, command, label, args):
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")
msg(sender, "&a/lol &eSay random message")
msg(sender, "&a/lol list [page] &eList 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

212
scriptutils.py Normal file
View File

@@ -0,0 +1,212 @@
from helpers import *
"""
Prints server restart message
arg 0 timeout
arg 1 $(whoami)
arg 2: reason
"""
@hook.command("script_restart")
def print_restart(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&2&l=============================================")
broadcast(None, "&r")
broadcast(None, "&r")
broadcast(None, "&9%s is restarting the server." % args[1])
broadcast(None, "&a&lServer is going to restart in %s seconds." % args[0])
broadcast(None, "&6&l%s" % " ".join(args[2:]))
broadcast(None, "&r")
broadcast(None, "&r")
broadcast(None, "&2&l=============================================")
else:
noperm(sender)
"""
Prints the server shut down message
arg 0 timeout
arg 1 $(whoami)
arg 2: reason
"""
@hook.command("script_stop")
def print_stop(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&2&l=============================================")
broadcast(None, "&r")
broadcast(None, "&r")
broadcast(None, "&9%s is shutting down the server." % args[1])
broadcast(None, "&a&lServer is going to shut down in %s seconds." % args[0])
broadcast(None, "&6&l%s" % " ".join(args[2:]))
broadcast(None, "&r")
broadcast(None, "&r")
broadcast(None, "&2&l=============================================")
else:
noperm(sender)
"""
Prints the shut down abort message
"""
@hook.command("script_stop_abort")
def abort_stop(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&4&oShut down has been aborted.")
else:
noperm(sender)
"""
Prints the restart abort message
"""
@hook.command("script_restart_abort")
def abort_restart(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&4&oRestart has been aborted.")
else:
noperm(sender)
"""
Prints the backup started message, saves all worlds and turns off world saving
"""
@hook.command("script_backup_begin")
def print_backup_begin(sender, command, lable, args):
if not is_player(sender):
broadcast(None, "&4 =&2 Starting backup now.")
server.dispatchCommand(server.getConsoleSender(), "save-all")
server.dispatchCommand(server.getConsoleSender(), "save-off")
else:
noperm(sender)
"""
Prints the backup finished message and turns on world saving
"""
@hook.command("script_backup_end")
def print_backup_end(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&4 =&2 Backup completed.")
server.dispatchCommand(server.getConsoleSender(), "save-on")
else:
noperm(sender)
"""
Prints the backup error message and turns on world saving
"""
@hook.command("script_backup_error")
def print_backup_error(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&4 =&c&l Error while backing up!")
server.dispatchCommand(server.getConsoleSender(), "save-on")
else:
noperm(sender)
"""
Prints the world trimming started message and starts trimming
"""
@hook.command("script_trim")
def print_backup_trim(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&4 =&3 Deleting all chunks beyond border now.")
server.dispatchCommand(server.getConsoleSender(), "wb Creative trim 1000000 15")
server.dispatchCommand(server.getConsoleSender(), "wb trim confirm")
else:
noperm(sender)
"""
Prints the thimming finished message
arg 0 size difference of world
arg 1: world border trim data
"""
@hook.command("script_trim_result")
def print_backup_trim_res(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&4 =&3 Chunk deletion saved %s (&a%sMB&3)" % (" ".join(args[1:]), args[0]))
else:
noperm(sender)
"""
Prints the database backup started message and admin-chat warning
"""
@hook.command("script_backup_database_begin")
def print_backup_db_begin(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&6 =&2 Starting database backup now.")
server.dispatchCommand(server.getConsoleSender(), "ac &aLogblock may be unavailable!")
else:
noperm(sender)
"""
Prints the database dumps compression started message
"""
@hook.command("script_backup_database_dumps")
def print_backup_db_dumps(sender, command, label, args):
if not is_player(sender):
server.dispatchCommand(server.getConsoleSender(), "ac &aDumps completed, logblock available again.")
server.dispatchCommand(server.getConsoleSender(), "ac &aNow compressing dumps, will take a while...")
else:
noperm(sender)
"""
Prints the database finished message and backup size in admin-chat
arg 0 size of backup
"""
@hook.command("script_backup_database_end")
def print_backup_db_end(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&6 =&2 Database backup completed.")
server.dispatchCommand(server.getConsoleSender(), "ac &abackup size: &2%sMB&a." % args[0])
else:
noperm(sender)
"""
Prints the database backup error message
"""
@hook.command("script_backup_database_error")
def print_backup_db_error(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&6 =&c&l Error while backing up database!")
else:
noperm(sender)
"""
Prints the database backup abort message
"""
@hook.command("script_backup_database_abort")
def print_backup_db_abort(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&6 =&2 Database backup aborted.")
else:
noperm(sender)
"""
Prints the spigot update message
"""
@hook.command("script_spigot_update")
def print_update(sender, command, label, args):
if not is_player(sender):
broadcast(None, "&9 =&2 A new Spigot version has been downloaded!")
broadcast(None, "&9 =&2 Update will be applied after the next reboot.")
else:
noperm(sender)
"""
Prints the admin-chat warning for disk is filled
arg 0 fill percentage
"""
@hook.command("script_disk_filled")
def print_disk_filled(sender, command, label, args):
if not is_player(sender):
server.dispatchCommand(server.getConsoleSender(), "ac &4&lWARNING:&6 Disk is filled > 96% (" + args[0] + "%)")
server.dispatchCommand(server.getConsoleSender(), "ac &4 Server will shut down at 98%!")
server.dispatchCommand(server.getConsoleSender(), "ac &4 Contact an admin &nimmediately&4!")
else:
noperm(sender)
"""
Saves all worlds, kicks players and shuts down the server
arg 0: reason
"""
@hook.command("script_shutdown")
def shutdown(sender, command, label, args):
if not is_player(sender):
server.dispatchCommand(server.getConsoleSender(), "save-all")
server.dispatchCommand(server.getConsoleSender(), "kickall %s" % " ".join(args))
server.dispatchCommand(server.getConsoleSender(), "stop")
else:
noperm(sender)

115
servercontrol.py Normal file
View File

@@ -0,0 +1,115 @@
from helpers import *
import socket
import threading
import time
from java.lang import Runnable
from adminchat import adminchat
"""
Module to allow our servercontrol telnet server forward chat and speak in AC
"""
host = ""
port = 1122
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
try:
sock.bind((host,port))
sock.setblocking(True)
sock.listen(5)
except socket.error as e:
print(str(e))
def command_process(text):
text = list(text)
args = []
arg = ""
for char in text:
if char != " " and char != "\n" and char != "\r" and char != "\t":
arg += char
elif arg != "":
args.append(arg)
arg = ""
if arg != "":
args.append(arg)
return args
clients = []
clients_l = threading.Lock()
class client():
def __init__(self,conn,address,name):
self.conn = conn
self.address = address
self.name = name
with clients_l:
clients.append(self)
self.conn.setblocking(False)
self.client_thread = threading.Thread(target=self.client_t)
self.client_thread.daemon = True
self.client_thread.start()
def getName(self):
return self.name
def close_connection(self):
try:
self.conn.close()
with clients_l:
clients.remove(self)
except:
pass
def client_t(self):
while True:
time.sleep(0.1)
try:
data = self.conn.recv(1024)
except:
if self not in clients:
self.close_connection()
continue
if self not in clients: #If the connection was closed, kill the thread
break
adminchat(self,data)
def handle_conn():
while True:
try:
conn, address = sock.accept()
except:
time.sleep(0.1)
continue
#Send name
data = conn.recv(1024)
data = command_process(data)
print "servercontrol connected! %s " %data[0]
client_c = client(conn, address,data[0])
handle_conn_t = threading.Thread(target=handle_conn)
handle_conn_t.daemon = True
handle_conn_t.start()
@hook.event("player.AsyncPlayerChatEvent","low")
def on_chat(event):
sender = event.getPlayer().getName()
msg = event.getMessage()
for entry in clients:
entry.conn.sendall(sender + " " + msg)

416
serversigns.py Normal file
View File

@@ -0,0 +1,416 @@
from helpers import *
from basecommands import simplecommand, Validate
import org.bukkit.Material as Material
import java.util.UUID as UUID
import org.bukkit.Material as Material
import org.bukkit.block.BlockFace as BlockFace
from math import ceil
commands_whitelist = (
"mail", "email", "memo",
"echo", "ping",
"cg join",
"cg info",
"chatgroup join",
"chatgroup info",
"i",
"item",
"p h", "plot home", "plot h", "p home", "plotme home", "plotme h",
"up",
"tppos",
"seen",
)
max_line_length = 256
max_lines = 20
help_page_size = 12
def load_signs():
signs_obj = open_json_file("serversigns", [])
loaded = {}
for entry in signs_obj:
loaded[tuple(entry[:4])] = list(entry[4:])
return loaded
def save_signs():
signs_obj = []
for key, value in signs.iteritems():
signs_obj.append(key + tuple(value))
save_json_file("serversigns", signs_obj)
# {("world", x, y, z): ["owner_id", "msg1", "msg2"]}
signs = load_signs()
# Accumulated messages so players can have longer messages: {"Dico200": "Message...........", ""}
lines = {}
def fromLoc(bLoc):
"""
# Returns a tuple containing the (bukkit)location's world's name and its x, y and z coordinates
# The format for the tuple is ("world_name", x, y, z)
"""
return (bLoc.getWorld().getName(), bLoc.getBlockX(), bLoc.getBlockY(), bLoc.getBlockZ())
def equals(loc1, loc2):
"""
# Returns whether loc1 and loc2 represent the same block
"""
for i in range(4):
if loc1[i] != loc2[i]:
return False
return True
def getOwner(sign):
"""
# Returns the name of the sign its owner
"""
return retrieve_player(sign[0]).getName()
def isOwner(sign, player):
"""
# Returns whether the given player owns the sign
"""
return sign and sign[0] == uid(player)
def canEdit(sign, player):
"""
# Returns whether the given player can edit the sign.
# Returns False if the sign wasn't claimed.
"""
return (sign and player.hasPermission("utils.serversigns.admin")) or isOwner(sign, player)
def getSign(locAt):
"""
# If data was found for a sign at the given location, returns the data.
# This data follows the format of ["owner_id", "msg1", "msg2"...].
"""
for loc, sign in signs.iteritems():
if equals(locAt, loc):
return sign
return None
def identifySign(loc):
"""
# Returns a string from which the user can tell what sign you're talking about.
# The string follows the format of "sign at (x,y,z) in world_name".
"""
return "sign at (%s) in %s" % (",".join((str(i) for i in loc[1:])), loc[0])
def signsMsg(msg, colour = '4'):
"""
# Returns the given msg, prefixed with '[Signs] '.
# The given colour is after applied to the msg.
# The colour defaults to 4 (dark red).
"""
return "&c[Signs] &" + colour + msg
# /svs command
subcommand_info = (
(("claim",), (
"Claims the sign so that you can add messages to it",
), (("[owner]", "claims.other"),)),
(("info", "lines"), (
"Displays information about the (claimed) sign",
)),
(("add",), (
"Adds the message to the sign. Use ++ at the end",
"to add the message to your buffer. You can then use",
"the same command again to create a longer message",
), (("<message>[++]", None),)),
(("remove", "rem", "del", "delete"), (
"Removes the message with the given ID from the sign.",
"The ID is given before each message by &b/svs info&a.",
), (("<message ID>", None),)),
(("switch", "reverse"), (
"Reverses the order in which the given messages are shown.",
), (("<message ID 1> <message ID 2>", None),)),
(("clear",), (
"Removes all messages from the sign.",
)),
(("reset", "unclaim"), (
"Resets the sign, removing all messages and its owner.",
)),
(("whitelist", "commands", "wl"), (
"Displays a list of whitelisted commands",
)),
(("help",), (
"Displays this help page",
), (("[page]", None),)),
)
@simplecommand(cmd = "serversigns", aliases = ["svs", "signmsg"],
description = "Makes something happen when you right click signs. \nUse /svs help for more details.",
usage = "<claim|reset|add <msg>[++]|remove <ID>|clear|info|help>",
helpNoargs = True,
senderLimit = 0)
def svs_command(sender, command, label, args):
arg1 = args[0].lower()
cmd_info = None
for cmd in subcommand_info:
if arg1 in cmd[0]:
cmd_info = cmd
break
Validate.notNone(cmd_info, signsMsg("That command could not be recognized, use &o/svs help &4for expected arguments"))
cmd = cmd_info[0][0]
Validate.isAuthorized(sender, "utils.serversigns." + cmd)
#-------------------- Sub commands that don't require any conditions -----------------------
if cmd == "help":
all_lines = [
"&aServer signs let's you add messages to a sign.",
"Right clicking the sign will display all the messages. Commands",
"can also be added, by prefixing the message with a '/'.",
"How to use &b/serversigns&a:",
]
for cmd in subcommand_info:
if sender.hasPermission("utils.serversigns." + cmd[0][0]):
params = ""
if len(cmd) == 3:
for param, perm in cmd[2]:
if perm is None or sender.hasPermission("utils.serversigns." + perm):
params += param + " "
all_lines.append("&b/svs %s %s" % ("|".join(cmd[0]), params))
for info_line in cmd[1]:
all_lines.append("&a- " + info_line)
last_page = int(ceil(len(all_lines) / help_page_size))
info("last page: %d" % last_page)
page = 1
if len(args) > 1 and args[1].isdigit():
page = int(args[1])
if page <= 0:
page = 1
elif page > last_page:
page = last_page
first_line = signsMsg("Serversigns help page %d" % page, '6')
if page < last_page:
first_line += ", &e/svs help %d&6 for the next" % (page + 1)
page_lines = [first_line] + all_lines[(page - 1) * help_page_size : min(page * help_page_size, len(all_lines))]
return "\n".join(page_lines)
if cmd == "whitelist":
return signsMsg("Whitelisted commands: &3" + ", ".join(commands_whitelist), 'a')
#-------------------------------------------------------------------------------------------
block = sender.getTargetBlock(None, 5)
Validate.isTrue(block.getType() in (Material.SIGN_POST, Material.WALL_SIGN), signsMsg("You have to be looking at a sign to use that!"))
loc = fromLoc(block.getLocation())
sign = getSign(loc)
signName = identifySign(loc)
arg2 = args[1].lower() if len(args) > 1 else None
#------------------------ Sub commands that require the block to be a sign -------------------------------
if cmd == "claim":
Validate.isTrue(not sign, signsMsg("The %s was already claimed" % signName))
Validate.isTrue(can_build2(sender, block), signsMsg("You are not permitted to claim signs here"))
target = sender
if arg2:
Validate.isTrue(player.hasPermission("utils.serversigns.admin"), signsMsg("You are not authorized to claim signs for other players"))
target = server.getOfflinePlayer(arg2)
Validate.notNone(target, signsMsg("That player could not be found"))
Validate.isTrue(target.isOnline(), signsMsg("The target has to be online"))
uuid = uid(target)
if sign != None:
if sign[0] == uuid:
return signsMsg("The " + signName + " was already owned by that player")
else:
sign[0] = uuid
else:
signs[loc] = [uuid]
save_signs()
return signsMsg("Claimed the " + signName + ((" for %s" % target.getName()) if (target != sender) else ""), 'a')
#----------------------------------------------------------------------------------------------------------
Validate.notNone(sign, signsMsg("The %s has not been claimed" % signName))
#----------------------Sub commands that require the sign to be claimed as well------------------------------------
if cmd == "info":
sign_lines = ""
for id, line in enumerate(sign[1:]):
sign_lines += ("\n &a%s: \"&f%s&a\"" % (id + 1, line))
return signsMsg("Properties of the %s:\n Owner: %s\n Lines: %s" % (signName, getOwner(sign), sign_lines), 'a')
#---------------------------------------------------------------------------------------------------------------
Validate.isTrue(canEdit(sign, sender), signsMsg("You do not own the %s!" % signName))
#---------------------- Sub commands that require you to own targeted sign as well -------------------------
if cmd == "add":
Validate.isTrue(len(sign) - 1 <= max_lines, signsMsg("This sign already has the maximum amount of lines, you cannot add more"))
line = " ".join(args[1:])
Validate.isTrue(line != "" and line != None, signsMsg("You have to enter a message to add or accumulate"))
key = sender.getName()
global lines
Validate.isTrue(key in lines or line[:1] != "/" or sender.hasPermission("utils.serversigns.command"), signsMsg("You cannot add commands to a sign!"))
if line[-2:] == "++":
if key not in lines:
lines[key] = ""
Validate.isTrue(len(lines[key]) + len(line[:-2]) + 1 <= max_line_length, signsMsg("This line would be too long, so the given message was not added to the accumulated message"))
lines[key] += " " + line[:-2]
return signsMsg("Added given message to the message you're accumulating. \nYour accumulated message is now as follows: \n&f%s" % lines[key], 'a')
if key in lines:
line = (lines[key] + " " + line)[1:]
Validate.isTrue(len(line) <= max_line_length, signsMsg("This line would be too long, so it was not added to the sign. It is however still accumulated."))
if line[0] == "/":
cmd = line[1:].lower()
whitelisted = False
for wl_cmd in commands_whitelist:
if cmd[:len(wl_cmd)] == wl_cmd:
whitelisted = True
break
Validate.isTrue(whitelisted, signsMsg("That command is not whitelisted for use with serversigns"))
if key in lines:
del lines[key]
sign.append(colorify(line) if line[0] != "/" else line)
save_signs()
return signsMsg("Added line \"&f%s&a\" to the %s" % (line, signName), 'a')
if cmd == "remove":
Validate.notNone(arg2, signsMsg("You have to enter the ID of the message to remove!"))
try:
id = int(arg2)
except:
return signsMsg("The ID of the message has to be a number and can be found by using &o/svs info")
Validate.isTrue(id != 0 and id < len(sign), signsMsg("The %s has no message with an ID of %s, use &o/svs info &4for all messages." % (signName, id)))
del sign[id]
return signsMsg("Removed message with id %s from the %s" % (id, signName), 'a')
if cmd == "switch":
Validate.isTrue(len(args) == 3, signsMsg("You have to enter the 2 IDs of the messages to reverse"))
try:
id1 = int(args[1])
id2 = int(args[2])
except:
return signsMsg("The ID of the message has to be a number and can be found by using &o/svs info")
for id in (id1, id2):
Validate.isTrue(id != 0 and id < len(sign), signsMsg("The %s has no message with an ID of %s, use &o/svs info &4for all messages." % (signName, id)))
sign[id1], sign[id2] = sign[id2], sign[id1]
save_signs()
return signsMsg("Reversed the messages with IDs %s and %s of the %s" % (id1, id2, signName), 'a')
if cmd == "clear":
signs[loc] = [sign[0]]
save_signs()
return signsMsg("Removed all messages from the %s" % signName, 'a')
if cmd == "reset":
del signs[loc]
save_signs()
return signsMsg("Removed all messages and the owner from the %s, it can now be claimed" % signName, 'a')
#-------------------------------------------------------------------------------------------------------
@hook.event("player.PlayerInteractEvent")
def on_click(event):
if str(event.getAction()) != "RIGHT_CLICK_BLOCK":
return
block = event.getClickedBlock()
if block.getType() not in (Material.WALL_SIGN, Material.SIGN_POST):
return
sign = getSign(fromLoc(block.getLocation()))
if sign != None:
player = event.getPlayer()
for message in sign[1:]:
if message[:1] == "/":
server.dispatchCommand(player, message[1:])
else:
msg(player, message, usecolor = False)
# ---------------------------Sign breaking--------------------------------
checking_block = False
faces = {
BlockFace.NORTH : (0,1,2,),
BlockFace.SOUTH : (3,),
BlockFace.WEST : (4,),
BlockFace.EAST : (5,),
}
@hook.event("block.BlockBreakEvent", "monitor")
def on_break(event):
if checking_block or event.isCancelled():
return
block = event.getBlock()
if block.getType() in (Material.SIGN_POST, Material.WALL_SIGN):
check_sign(event, block, attached = False)
for block_face, data_values in faces.iteritems():
block2 = block.getRelative(block_face)
if block2.getType() == Material.WALL_SIGN and block2.getData() in data_values:
check_sign(event, block2)
block3 = block.getRelative(BlockFace.UP)
if block3.getType() == Material.SIGN_POST:
check_sign(event, block3)
def check_sign(event, block, attached = True):
player = event.getPlayer()
loc = fromLoc(block.getLocation())
if block.getType() not in (Material.WALL_SIGN, Material.SIGN_POST) or getSign(loc) is None:
return
if not can_build2(player, block):
event.setCancelled(True)
msg(event.getPlayer(), signsMsg("You cannot break %s" % ("the sign attached to that block" if attached else "that sign")))
else:
del signs[loc]
save_signs()
msg(player, signsMsg("Reset the %s which you just broke" % identifySign(loc)))
def can_build2(player, block):
global checking_block
event = BlockBreakEvent(block, player)
checking_block = True
server.getPluginManager().callEvent(event)
checking_block = False
return not event.isCancelled()
def check_all_signs_and_force_commands():
for loc in signs:
if server.getWorld(loc[0]).getBlockAt(loc[1], loc[2], loc[3]).getType() not in (Material.WALL_SIGN, Material.SIGN_POST):
del signs[loc]
try:
map_field = server.getPluginManager().getClass().getDeclaredField("commandMap")
map_field.setAccessible(True)
command_map = map_field.get(server.getPluginManager())
commands_field = command_map.getClass().getDeclaredField("knownCommands")
commands_field.setAccessible(True)
map = commands_field.get(command_map)
rsutils_cmd = map.get("redstonerutils:serversigns")
map.put("svs", rsutils_cmd)
map.put("serversigns", rsutils_cmd)
map.put("signsmsg", rsutils_cmd)
except:
error("[Serversigns] failed to force commands")
error(trace())

175
setup.sh Executable file
View File

@@ -0,0 +1,175 @@
#!/usr/bin/env bash
# exit on failure
set -e
for cmd in curl java unzip git pip; do
if ! which "$cmd" >/dev/null; then
tput setf 4 >&2
echo "Error: please install '$cmd' to proceed" >&2
tput sgr0 >&2
exit 1
fi
done
echo -e "> This will only set up Spigot and all the plugins, configuration files are still up to you to manage"
echo -e "> Press enter to coninue"
read
mkdir -v "redstoner"
cd "redstoner"
mkdir -v "server"
mkdir -v "build"
cd "build"
echo -e "\n> Downloading Spigot build tools"
curl --progress-bar -Lo "BuildTools.jar" "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
echo -e "\n> Building Spigot, this will take a while ..."
java -jar BuildTools.jar > /dev/null
cp -v spigot-*.jar "../server/spigot.jar"
rm spigot-*.jar
cd "../server/"
mkdir -v "plugins"
cd "plugins"
echo ">> Downloading essentials.jar ..."
curl --progress-bar -Lo "essentials.jar" "https://github.com/RedstonerServer/Essentials/releases/download/stable-2.9.6-REDSTONER/Essentials-2.x-REDSTONER.jar"
echo ">> Downloading essentialschat.jar ..."
curl --progress-bar -Lo "essentialschat.jar" "https://hub.spigotmc.org/jenkins/job/Spigot-Essentials/lastSuccessfulBuild/artifact/EssentialsChat/target/EssentialsChat-2.x-SNAPSHOT.jar"
echo ">> Downloading imageonmap.jar ..."
curl --progress-bar -Lo "imageonmap.jar." "https://dev.bukkit.org/media/files/772/680/imageonmap.jar"
echo ">> Downloading logblock.jar ..."
curl --progress-bar -Lo "logblock.jar." "https://dev.bukkit.org/media/files/757/963/LogBlock.jar"
echo ">> Downloading logblockquestioner.zip ..."
curl --progress-bar -Lo "logblockquestioner.zip" "https://cloud.github.com/downloads/DiddiZ/LogBlockQuestioner/LogBlockQuestioner%20v0.03.zip"
echo ">> Downloading multiverse-core.jar ..."
curl --progress-bar -Lo "multiverse-core.jar" "https://dev.bukkit.org/media/files/588/781/Multiverse-Core-2.4.jar"
echo ">> Downloading multiverse-portals.jar ..."
curl --progress-bar -Lo "multiverse-portals.jar." "https://dev.bukkit.org/media/files/588/790/Multiverse-Portals-2.4.jar"
echo ">> Downloading multiverse-netherportals.jar ..."
curl --progress-bar -Lo "multiverse-netherportals.jar." "https://dev.bukkit.org/media/files/589/64/Multiverse-NetherPortals-2.4.jar"
echo ">> Downloading multiverse-inventories.jar ..."
curl --progress-bar -Lo "multiverse-inventories.jar." "https://dev.bukkit.org/media/files/663/303/Multiverse-Inventories-2.5.jar"
echo ">> Downloading permissionsex.jar ..."
curl --progress-bar -Lo "permissionsex.jar" "https://dev.bukkit.org/media/files/882/992/PermissionsEx-1.23.3.jar"
echo ">> Downloading plotme.jar ..."
curl --progress-bar -Lo "plotme.jar" "http://ci.worldcretornica.com/job/PlotMe-Core/244/artifact/target/PlotMe-Core.jar"
echo ">> Downloading plotme-defaultgenerator.jar ..."
curl --progress-bar -Lo "plotme-defaultgenerator.jar" "http://ci.worldcretornica.com/job/PlotMe-DefaultGenerator/83/artifact/target/PlotMe-DefaultGenerator.jar"
echo ">> Downloading serversigns.jar ..."
curl --progress-bar -Lo "serversigns.jar." "https://dev.bukkit.org/media/files/876/381/ServerSigns.jar"
echo ">> Downloading redstoneclockdetector.jar ..."
curl --progress-bar -Lo "redstoneclockdetector.jar." "https://dev.bukkit.org/media/files/577/253/RedstoneClockDetector.jar"
echo ">> Downloading vault.jar ..."
curl --progress-bar -Lo "vault.jar" "https://dev.bukkit.org/media/files/837/976/Vault.jar"
echo ">> Downloading worldborder.jar ..."
curl --progress-bar -Lo "worldborder.jar." "https://dev.bukkit.org/media/files/883/629/WorldBorder.jar"
echo ">> Downloading worldguard.jar ..."
curl --progress-bar -Lo "worldguard.jar." "https://github.com/RedstonerServer/WorldGuard/releases/download/6.0.0-redstoner/worldguard-6.0.0-REDSTONER.jar"
echo ">> Downloading worldedit.jar ..."
curl --progress-bar -Lo "worldedit.jar" "https://dev.bukkit.org/media/files/880/435/worldedit-bukkit-6.1.jar"
echo ">> Downloading pythonpluginloader.jar ..."
curl --progress-bar -Lo "pythonpluginloader.jar" "https://bamboo.gserv.me/browse/PLUG-PYPL/latestSuccessful/artifact/JOB1/Version-agnostic-jar/PyPluginLoader.jar"
echo -e "\n> Unpacking LogBlockQuestioner"
unzip -q "logblockquestioner.zip" "LogBlockQuestioner.jar"
rm "logblockquestioner.zip"
mv -v "LogBlockQuestioner.jar" "logblockquestioner.jar."
echo -e "\n> Pulling redstoner-utils ..."
git clone -q "git@github.com:RedstonerServer/redstoner-utils.git" "redstoner-utils.py.dir" > /dev/null
echo -e "\n> Installing dependencies"
pip install passlib
echo -e "\n> All plugins downloaded"
cd "redstoner-utils.py.dir"
echo -e "\n> Duplicating sample files"
for file in ./*.example; do
cp -v "$file" "$(echo "$file" | rev | cut -d "." -f 2- | rev)"
done
cd "../.."
mkdir -v "lib"
cd "lib"
echo -e "\n> Downloading MySQL Connector ..."
curl --progress-bar -Lo "mysql-connector.zip" "https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.36.zip"
echo "> Extracting MySQL Connector"
unzip -p mysql-connector.zip "mysql-connector-java-5.1.36/mysql-connector-java-5.1.36-bin.jar" > mysql-connector.jar
rm "mysql-connector.zip"
cd ".."
echo -e "\n> Creating startup script"
cat > start.sh <<EOF
#!/usr/bin/env bash
java -Xms512m -Xmx1g -jar spigot.jar
EOF
chmod +x start.sh
port="25565"
re='^[0-9]+$'
if [[ "$1" =~ $re ]]; then
port="$1"
fi
echo "> Setting port to $port"
echo "> Generating server.properties"
cat > server.properties <<EOF
#Minecraft server properties
#Sat Jul 25 15:42:21 CEST 2015
spawn-protection=16
generator-settings=
force-gamemode=false
allow-nether=true
gamemode=1
broadcast-console-to-ops=true
enable-query=false
player-idle-timeout=0
difficulty=1
spawn-monsters=true
op-permission-level=4
resource-pack-hash=
announce-player-achievements=true
pvp=true
snooper-enabled=true
level-type=FLAT
hardcore=false
enable-command-block=false
max-players=20
network-compression-threshold=256
max-world-size=29999984
server-port=$port
server-ip=
spawn-npcs=true
allow-flight=false
level-name=world
view-distance=10
resource-pack=
spawn-animals=true
white-list=false
generate-structures=true
online-mode=true
max-build-height=256
level-seed=
use-native-transport=true
motd=Redstoner dev server
enable-rcon=false
EOF
echo -e "> Generating eula.txt"
echo "eula=true" > eula.txt
echo -e "\n> $(tput setf 2)All Done! $(tput sgr0)Don't forget to configure plugins for your needs."
echo "> Run redstoner/server/start.sh to start the server"
echo "> Our plugins are in redstoner/server/plugins/redstoner-utils.py.dir"

159
signalstrength.py Normal file
View File

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

View File

@@ -49,7 +49,7 @@ class Arena(object):
self.match_goal = None # amount of deaths or time until the match ends (depends on arena_type)
self.arena_type = None # arena type (death or time)
self.explosion_damage = None
self.player_stats = {}
self.players = Queue()
self.spawn_location = []
@@ -60,7 +60,7 @@ class Arena(object):
self.corner1 = None # The corner1 given by the player (really bad for 3D position compare)
self.corner2 = None # The corner2 given by the player (really bad for 3D position compare)
self.tpp = None # The top, positive x, positive z corner
self.bnn = None # The bottom, negative x, negative z corner
self.bnn = None # The bottom, negative x, negative z corner
#set corners of arena
def set_corner(self, sender, type):
@@ -75,21 +75,21 @@ class Arena(object):
#Compares the corner1 and corner2 locations and figures out tpp and bnn so that we dont have to do it everytime we run in_arena()
def update_corner_points(self):
self.tpp = None
self.bnn = None
self.bnn = None
if self.corner1 == None or self.corner2 == None:
return
corn1 = self.corner1.get_location()
corn2 = self.corner2.get_location()
if not corn1.getWorld().getName() == corn2.getWorld().getName():
return
top = corn1.y if corn1.y > corn2.y else corn2.y
bottom = corn1.y if corn1.y < corn2.y else corn2.y
pos_x = corn1.x if corn1.x > corn2.x else corn2.x
pos_z = corn1.z if corn1.z > corn2.z else corn2.z
neg_x = corn1.x if corn1.x < corn2.x else corn2.x
neg_z = corn1.z if corn1.z < corn2.z else corn2.z
self.tpp = Coords(corn1.getWorld(), pos_x, top, pos_z, 0, 0)
self.bnn = Coords(corn2.getWorld(), neg_x, bottom, neg_z, 0, 0)
@@ -118,9 +118,9 @@ class Arena(object):
self.start_match()
return True
return False
#remove a player from the queue
def remove_player(self, player):
def remove_player(self, player):
if self.queue.contains(player):
self.queue.remove(player)
return True
@@ -132,7 +132,7 @@ class Arena(object):
return False
loc_tpp = self.tpp.get_location()
loc_bnn = self.bnn.get_location()
if loc.y > loc_tpp.y:
return False
if loc.y < loc_bnn.y:
@@ -179,12 +179,12 @@ class Arena(object):
alist[i] = alist[i+1]
alist[i+1] = temp
return alist
@make_synchronized #Jython synchronized block
def end_match(self): #End match, sort the players and print the 3 players with least amount of deaths
sorted_list = self.bubbleSort(self.players.read())
for player in self.players.read():
if player.isOnline():
loc = self.sign_location[0].get_location().get_location()
@@ -256,7 +256,7 @@ class Arena(object):
def get_click_signs(self):
return self.sign_click
#Check if player is in the queue
def in_queue(self,player):
if self.queue.contains(player):
@@ -307,7 +307,7 @@ class Arena(object):
sign.get_location().set_location(location)
break
#Remove location out of location
#Remove location out of location
def delete_location(self, name, type):
if type == "spawn":
for spawn in self.spawn_location[:]:
@@ -472,16 +472,16 @@ class Queue(object):
def __init__(self):
self.queue = []
#Appends to queue
def put(self,args):
self.queue.append(args)
#Returns the first item in the queue and removes it
def get(self):
if len(self.queue) > 0:
return self.queue.pop(0)
else:
return False
@@ -498,7 +498,7 @@ class Queue(object):
if player in self.queue:
return True
return False
#Clear the queue
def clear(self):
self.queue = []
@@ -532,7 +532,7 @@ class timings_runnable(Runnable):
self.arena = arena
def run(self):
self.arena.end_match()
self.arena.end_match()
#timings thread to end arenas if their type is time
def timings():
@@ -545,10 +545,10 @@ def timings():
if arena.start_time + arena.match_goal < current_time:
timing = timings_runnable(arena)
server.getScheduler().runTask(server.getPluginManager().getPlugin("RedstonerUtils"), timing)
time.sleep(0.1)
timingsThread = threading.Thread(target = timings)
timingsThread.daemon = True #Thread dies if main thread dies
timingsThread.start()
@@ -561,7 +561,7 @@ timingsThread.start()
# Events
##############################################################################################
@hook.event("player.PlayerMoveEvent", "high")
@hook.event("player.PlayerMoveEvent", "low")
def onMove(event):
if event.getPlayer().getWorld().getName() != "minigames":
return
@@ -663,7 +663,7 @@ def on_quit(event):
##############################################################################################
# Command handling
##############################################################################################
##############################################################################################
def create_arena(sender, args):

View File

@@ -3,6 +3,14 @@ from secrets import *
import mysqlhack
from com.ziclix.python.sql import zxJDBC
"""
WORK IN PROGRESS
"""
#-----------------------Config--------------------------
config_file = "website-roles"
ranks = {
"member" : 3,
"builder" : 7,
@@ -13,33 +21,42 @@ ranks = {
"admin" : 5
}
ranks = open_json_file(config_file, ranks)
def save_ranks():
save_json_file(config_file, ranks)
#-----------------------Event---------------------------
@hook.event("player.PlayerJoinEvent", "normal")
def on_player_join(event):
user = event.getPlayer()
uuid = uid(player).replace("-", "")
role = get_role(uuid)
if role in [1, 2, 6]: #Disabled/Banned/Superadmin
return
if role:
for rank in ranks:
if user.hasPermission("group." + rank):
if role != ranks[rank]:
set_role(uuid, ranks[rank])
return
if not user.hasPlayedBefore():
return
if role == None:
msg(user, "&cYou haven't registed yet! Make sure to do so on redstoner.com")
sql_instruction
def callback_thing(role, args):
if role in [1, 2, 6]: #Disabled/Banned/Superadmin
return
if role != None:
for rank in ranks:
if user.hasPermission("group." + rank):
if role != ranks[rank]:
set_role(uuid, ranks[rank])
elif user.hasPlayedBefore():
msg(user, "&cYou haven't registed yet! Make sure to do so on redstoner.com")
def get_role(uuid):
return execute_query("SELECT `role_id` FROM users WHERE `uuid` = ? LIMIT 1", uuid)[0][17]
results = execute_query("SELECT `role_id` FROM users WHERE `uuid` = ? LIMIT 1;", uuid)
return results[0][0]
# Returns a table with 1 row (LIMIT 1) and 1 column (SELECT `role_id`), so we're looking for the first row of the first column.
def set_role(uuid, role_id):
execute_update("UPDATE users SET `role_id` = %d WHERE `uuid` = ?" % role_id, uuid)
execute_update("UPDATE users SET `role_id` = ? WHERE `uuid` = ?;", (role_id, uuid,))
# %d is like %s for integers (unlogically, you'd expect something like %i), though %s also works here.
def execute_query(query, uuid):
@@ -56,5 +73,40 @@ def execute_update(update, uuid):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute(update, (uuid,))
conn.commit()
curs.close()
conn.close()
conn.close()
def get_role(uuid):
sql_instruction()
#--------------------------------Queries / Updates----------------------------
def sql_instruction(instruction, args, fetch = True, callback_func = ignored_func, callback_args = tuple()):
thread = threading.Thread(target = curs_instruction, args = (instruction_executor, instruction, fetch, callback_func, callback_args))
thread.start()
def curs_instruction(func, instruction, fetch, callback_func, callback_args):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.getCursor()
if fetch:
returned = func(curs, instruction, fetch)
curs.close()
conn.close()
callback_func(returned, callback_args)
else:
func(curs, instruction, fetch)
conn.commit()
curs.close()
conn.close()
def instruction_executor(curs, instruction, fetch):
curs.execute(instruction)
return curs.fetchall() if fetch else None
def ignored_func(*args):
pass

78
tag.py Normal file
View File

@@ -0,0 +1,78 @@
from helpers import *
add_perm = "utils.tag.add"
del_perm = "utils.tag.del"
check_perm = "utils.tag.check"
data = open_json_file("tag", {})
@hook.command("tag")
def command(sender, command, label, args):
if len(args) > 0:
if str(args[0]) == "add":
if sender.hasPermission(add_perm):
if len(args) > 2:
add(sender, args[1:])
else:
msg(sender, "&a-&c Usage: /tag add <name> <reason>")
else:
noperm(sender)
elif str(args[0]) == "check":
if sender.hasPermission(check_perm):
if len(args) == 2:
check(sender, args[1:])
else:
msg(sender, "&a-&c Usage: /tag check <name>")
else:
noperm(sender)
elif str(args[0]) == "del":
if sender.hasPermission(del_perm):
if len(args) == 3:
delete(sender, args[1:])
else:
msg(sender, "&a-&c Usage: /tag del <id>")
else:
msg(sender, "&a-&c Unknown subcommand! (add, check, del)")
else:
msg(sender, "&a&c Usage: /tag add/check/del")
return True
def delete(sender, args):
player = server.getOfflinePlayer(args[0])
uuid = uid(player)
try:
if data[uuid] == None:
pass
except:
msg(sender, "&a-&e There are no notes about this player")
return
if int(args[1]) - 1 >= len(data[uuid]):
msg(sender, "&a-&c Id of note is out of range")
return
del (data[uuid])[int(args[1]) - 1]
save_json_file("tag", data)
msg(sender, "&a-&e Deleted note at %s" % args[1])
def add(sender, args):
player = server.getOfflinePlayer(args[0])
uuid = uid(player)
try:
if data[uuid] == None:
pass
except:
data[uuid] = []
data[uuid].append(" ".join(args[1:]))
msg(sender, "&a-&e Note added")
save_json_file("tag", data)
def check(sender, args):
player = server.getOfflinePlayer(args[0])
uuid = uid(player)
try:
num = 0
for tag in data[uuid]:
num += 1
msg(sender, "&a-&e %s: %s" % (str(num), str(tag)))
except:
msg(sender, "&a-&e There are no notes about this player")

121
vanish.py Normal file
View File

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

14
vanishfix.py Normal file
View File

@@ -0,0 +1,14 @@
from helpers import *
from java.lang import Runnable
class run(Runnable):
def run(self):
players = server.getOnlinePlayers()
for player in players:
if player.hasPermission("essentials.vanish"):
player.performCommand("vanish")
player.performCommand("vanish")
def enabled():
server.getScheduler().runTaskTimer(server.getPluginManager().getPlugin("RedstonerUtils"), run(), 20, 1200)