Author SHA1 Message Date
Dico200 7a905643eb Enabled friends module, added friends check in imbusy, fixed small mistakes 2016-05-28 22:18:27 +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 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 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 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
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
NEMESIS13cz f865c02bf5 Added support for hex strings 2015-08-11 03:35:23 +02:00
NEMESIS13cz 6e5829f9d2 Fixed loading issues 2015-08-11 03:15:17 +02:00
NEMESIS13cz d683203aca Rewrote a lot, added a lot 2015-08-11 02:45:03 +02:00
NEMESIS13cz 77f445002c Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-08-10 20:41:35 +02:00
NEMESIS13cz 69fe651dc1 Changed calc to run on a separate thread 2015-08-10 20:40:03 +02:00
PanFritz 2a7b4a05ff custom player class idea 2015-08-10 20:38:42 +02:00
NEMESIS13cz 41d2f31048 Removed hard-coded aliases 2015-08-10 19:53:02 +02:00
NEMESIS13cz 9b3e0d19c4 Fixed error when user logs in multiple times while thread is processing hashes 2015-08-10 19:34:18 +02:00
NEMESIS13cz 09bcc687bc Removed unused stuff 2015-08-10 19:33:04 +02:00
NEMESIS13cz 3500eabde8 Changed kick timeout to 30 seconds 2015-08-10 19:25:37 +02:00
NEMESIS13cz 8edca18bb3 Fixed kick thread 2015-08-10 19:19:26 +02:00
NEMESIS13cz 3b7b61f374 Removed nickname print, dot suffixes cannot be parsed into ASCII 2015-08-10 19:06:01 +02:00
NEMESIS13cz 1faf153d75 Fixed more stuff 2015-08-10 18:57:17 +02:00
NEMESIS13cz 9e796f881e Minor fixes 2015-08-10 18:42:23 +02:00
NEMESIS13cz f45e3fa72b Fixed missing bracket 2015-08-10 18:19:57 +02:00
NEMESIS13cz 63462d6f1d Added player info command 2015-08-10 18:14:18 +02:00
NEMESIS13cz 2a53432c95 Added playermanager to module list 2015-08-10 17:38:59 +02:00
NEMESIS13cz 3f51d2dc25 Finished adding all helper functions 2015-08-10 17:37:24 +02:00
NEMESIS13cz 7e49ca9817 Fixed double message when act is on and ac_key is used 2015-08-10 16:45:18 +02:00
NEMESIS13cz 366d57c47f Created central Player class 2015-08-10 16:44:08 +02:00
NEMESIS13cz 90872da066 Fixed timed-match scheduling 2015-07-23 01:27:38 +02:00
NEMESIS13cz 09e0d761f5 modified: loginsecurity.py
Fixed scheduler and commands
2015-07-23 01:20:07 +02:00
PanFritz f64d3074e1 Merge branch 'master' into dev 2015-07-08 02:34:49 +02:00
PanFritz f661344299 Changed import 2015-07-08 02:20:04 +02:00
PanFritz 62fefcd7f9 Removed player interact entity event from blocked events 2015-07-08 01:57:42 +02:00
PanFritz e0daff2c86 helpNoargs = False 2015-07-08 01:55:45 +02:00
PanFritz 0695040988 set amax = 0 2015-07-08 01:52:05 +02:00
PanFritz 4a18474557 Removed usage from simple command 2015-07-08 01:50:08 +02:00
PanFritz 1689ddaab2 Fixed if statement for password removal 2015-07-08 01:45:23 +02:00
PanFritz 28e9a0dfad Fixed syntax 2015-07-08 01:41:28 +02:00
PanFritz 5f8ba18e53 Threaded password verifying, removed some checks 2015-07-08 01:39:02 +02:00
PanFritz b67d3efbb4 removed commented code, fixed mysql issues. commented out timing thread 2015-07-07 21:56:24 +02:00
PanFritz c8895f9bb4 Fixed mysql command missing '?' 2015-07-07 18:52:43 +02:00
PanFritz b65c2228f7 Fixing syntax errors 2015-07-07 13:07:07 +02:00
PanFritz 93965cef7e Changed import to secret 2015-07-07 13:05:19 +02:00
PanFritz 8971523d6d commented out debug code 2015-07-07 13:04:29 +02:00
PanFritz dac228800c fixed import 2015-07-07 02:09:47 +02:00
PanFritz 6bb52ed255 Finished login security, added mysql support and password hashing. 2015-07-07 01:58:05 +02:00
PanFritz 39b179cf42 Changed snowball damage to floats 2015-07-06 21:46:44 +02:00
PanFritz 839baffb24 Removed debug code, added more comments 2015-07-06 21:04:57 +02:00
PanFritz 9d61d3d61c Fixed async bug on timings thread. Fixed stats sorting 2015-07-06 20:54:09 +02:00
PanFritz 0f47853a41 Changed name to object 2015-07-01 17:17:51 +02:00
PanFritz eec11b857e Changed from sender name to sender object in quit_arena 2015-06-30 19:20:10 +02:00
PanFritz bced8beeda Changed quiting arenas to use player object and not name of player. Timing thread added try except 2015-06-30 19:11:48 +02:00
PanFritz 168d99d9a1 re enabled snowbrawl 2015-06-29 23:59:49 +02:00
PanFritz dd960b909c updated snowbrawl 2015-06-29 23:55:07 +02:00
PanFritz 1c3f2c898c Fixed match start issue 2015-06-29 23:16:39 +02:00
PanFritz 525e4825c6 more indentation fixes 2015-06-29 22:58:47 +02:00
PanFritz fdaa6265c4 Removed old code from main 2015-06-29 22:47:43 +02:00
PanFritz 72723840ed Fixed indentation 2015-06-29 22:47:06 +02:00
PanFritz 474ce0b310 remade snowbrawl 2015-06-29 22:16:18 +02:00
PanFritz 4f30fb1a83 upped explosion damage 2015-06-15 23:10:08 +02:00
PanFritz 98ae25df50 fixed indent issue 2015-06-15 22:40:04 +02:00
PanFritz caec2fd0d5 added snowbrawl to main.py 2015-06-15 22:36:50 +02:00
PanFritz 3a02a4cffc tweaks 2015-06-15 22:27:17 +02:00
Dico200 5f0d845ec0 Nemes's work on Snowbrawl 2015-06-14 17:02:42 +02:00
Dico200 40137cad4c This /up fix SHOULD WORK! 2015-06-06 12:13:18 +02:00
Dico200 35b1fe3a0f Well //up is gone again. Great. Undoing.. 2015-06-06 10:56:31 +02:00
Dico200 778fd0234e Fix /up
Tried a lot of shit but these 3 lines should do it.
2015-06-06 10:29:24 +02:00
Dico200 1b5f07f7aa Fix new attempt... :D 2015-06-03 01:26:27 +02:00
Dico200 dbeb0d53bb Another fix attempt for /up 2015-06-03 01:24:45 +02:00
Dico200 0ea2760bf4 Revert "why did //up disappear? Testing on dev server."
This reverts commit a6f5156ef4.
2015-06-03 01:18:18 +02:00
Dico200 a6f5156ef4 why did //up disappear? Testing on dev server. 2015-06-03 01:16:14 +02:00
Dico200 3cbb8dc9bd Prevent /up griefing, add /ackey, minor tweaks
Dunno why its posting 'changes' in main.py tho
2015-06-03 01:09:07 +02:00
Dico200 794f0470bf blockplacemods fix config types sharing storage obj 2015-05-18 23:34:00 +02:00
Dico200 fb3e4afe3c blockplacemods tweaks/fixes of returned messages 2015-05-18 23:32:57 +02:00
Dico200 5dba052fa9 Forgot to save this last check 2015-05-18 23:06:24 +02:00
Dico200 bd05374db0 blockplacemods update, basecommands fix
Added settings: piston, dropper, hopper
changes to the framework
made it so you can set the default contents for all slots in
furnaces/droppers as well as furnaces.
2015-05-18 23:05:54 +02:00
Dico200 057b404b03 Small change to open_json_file() 2015-05-18 23:00:54 +02:00
Dico200 dd1f0b8356 Steps towards even easier command handling.
See issue #4
2015-05-14 04:10:04 +02:00
Dico200 4599ae89e9 Fix this thing so that only 1 player has to sleep
untested
2015-05-14 03:32:34 +02:00
Dico200 6fc168eb63 Fixes, tweaks, changes 2015-05-14 02:46:54 +02:00
Dico200 83eb3a8885 Merge remote-tracking branch 'origin/dev' 2015-05-14 02:19:16 +02:00
Dico200 59816b58e2 Almost complete redo of blockplacemods, small fixes
I've redone most of blockplacemods its code. It is now MUCH easier to
expand in the future and I think the code is more elegant and stuff. It
all works the same as before, except the command is now /toggle
<setting>
I've merged the setting for /autotakewater and /autofillcauldron into
one setting named cauldron.
2015-05-14 02:16:33 +02:00
Dico200 0ef318d6b9 Removed a lot of shit from basecommands.py 2015-05-13 21:39:25 +02:00
Dico200 9f4d096a57 Cleanup misc.py and small fix, also in damnspam 2015-05-13 21:37:53 +02:00
Dico200 230e427f04 Fix BlockBreakEvent being called on lever switch 2015-05-13 21:37:23 +02:00
Dico200 88e0a298b5 Added a few untested things to misc.py 2015-05-13 21:06:26 +02:00
Dico200 7407ec0513 Merge remote-tracking branch 'origin/dev' 2015-05-08 13:47:23 +02:00
Dico200 6865e2c3b9 Revert "show network AS in /check"
This reverts commit 181c6ccfeb.
2015-05-05 16:50:55 +02:00
Dico200 eaf0f41746 Revert "use https for ipinfo.io"
This reverts commit 62569c7361.
2015-05-05 16:50:48 +02:00
Dico200 37dc80305f More blockplacemods
Trying to make it place an item (in this case 1 piece of redstone dust)
in a furnace. I know that it creates the ItemStack correctly, I know
that in this case .getInventory() returns an instance of
FurnaceInventory and I know that .update() is returning True meaning it
updated the blockstate successfully. However, the item is not appearing
in the furnace. Any idea why?
2015-05-01 21:46:24 +02:00
Dico200 ad9de19d5d right clicking empty cauldron fills it 2015-04-29 17:12:39 +02:00
Dico200 884e0a3491 Added perm check to interactevent im blockplacemods
fixes #19
2015-04-29 14:41:48 +02:00
Dico200 5e8c906bf0 Merge remote-tracking branch 'origin/dev' 2015-04-29 03:31:25 +02:00
Dico200 4e1398e514 Disable loginsecurity module 2015-04-29 03:31:01 +02:00
Dico200 3daa191d8b Remove adminnotes noperm notification 2015-04-29 03:30:00 +02:00
Dico200 9eda3ad0ff Merge remote-tracking branch 'origin/dev' 2015-04-29 03:28:17 +02:00
Dico200 1afaec2a08 Small misc cleanup 2015-04-29 03:27:52 +02:00
Dico200 c451b2247b Added blockplacemods module
Adds a few nifty features with per player customization:
- Placing a slab automatically turns it upside-down
- Placing a cauldron automatically fills it
- Right clicking a cauldron with empty hand or redstone dust lowers
water level
2015-04-29 03:27:37 +02:00
Dico200 1cac4c6ed5 Added /tempadd command: temporary group membership
Just a simpler way of writing /pex user <user> group add <group> *
604800
2015-04-28 00:08:33 +02:00
jomo 62569c7361 use https for ipinfo.io 2015-04-20 21:02:07 +02:00
jomo 181c6ccfeb show network AS in /check 2015-04-20 20:39:00 +02:00
Dico200 487375dd07 Added loginsecurity module
Added to make an easily adjustible version of LoginSecurity.
LoginSecurity does not (seem to) support name changes since it retrieves
the UUID used from a byte[] of "OfflinePlayer:<username>" which means
the UUID changes when a player changes their name. This should fix
/rmpass. It uses BCrypt. I'll test this on the dev server (hoping bcrypt
is installed)
2015-04-17 00:10:21 +02:00
Dico200 5384190741 Adminnotes fix continued message used for next note
Also code cleanup
2015-04-16 18:35:48 +02:00
PanFritzandDico200 7359437524 Fix missing var 2015-04-16 18:35:47 +02:00
Dico200 ab1087f210 Adminnotes fix continued message used for next note
Also code cleanup
2015-04-16 18:33:09 +02:00
PanFritz 7c30af86f2 Fix missing var 2015-04-16 12:40:30 +02:00
PanFritz a37fb90b06 Tab indent fix 2015-04-16 12:36:16 +02:00
PanFritz 62059e613e Added perm check for Admin notes notification 2015-04-16 12:28:58 +02:00
PanFritz 7824fdae54 Added perm check for Admin notes notification 2015-04-16 12:26:03 +02:00
Dico200 2c1292015b Made lava not break redstone components in Creative
I tested thoroughly. I don't see how this will break other parts of the
plugin either.
2015-04-14 21:20:55 +02:00
PanFritz f45da9bf42 Fix missing () 2015-04-13 20:57:25 +02:00
Dico200 055a9073f4 Hotfix in /sudo 2015-04-13 18:38:16 +02:00
Dico200 85df528fc3 Added /rp list as alias for /rp open 2015-04-13 18:38:03 +02:00
Dico200 2c063d638f Tweaks in imout, primarily making player vanish 2015-04-13 18:16:40 +02:00
Dico200 211fb08265 Removed color support for /me for players w/o perms 2015-04-13 18:16:00 +02:00
Dico200 ce3b911b35 /pluginversions is broken, Fixed mail send colours.
I attempted to fix /pluginversions but ended up just commenting it out.
The problem is in retrieving the plugins where instead of object type
Plugin it returns "array.array"? I tried a whole bunch of things but I
didn't succeed to make it work.
2015-04-10 23:55:30 +02:00
Dico200 b232cbf5cf Small fix 2015-04-10 00:39:09 +02:00
Dico200 f3833a6733 Untested change to add pyeval possibility to args
so you do like, for example:
/pex user EVAL:server.getOfflinePlayer("Dico200").getUniqueId()

this could also be used in chat. I know its pretty useless but useful in
some cases.
2015-04-10 00:37:51 +02:00
Dico200 d85b96f875 Clean up misc.py, add space support for cg key 2015-04-10 00:13:06 +02:00
Dico200 9a0767676c Didn't upload this for some reason 2015-04-09 01:39:41 +02:00
Dico200 58eea64148 I love less-than-one line list creators! 2015-04-09 01:38:58 +02:00
Dico200 812e2c3aaf Changed version to 3.1.0 :D no reason 2015-04-09 01:25:52 +02:00
Dico200 9ddd523c58 Added player configurable chatgroup keys
The keys are stored in chatgroup_keys.json
2015-04-09 01:23:00 +02:00
Dico200 34b59e61fe Revert "Revert "Change to /modules... trying to make @command work.""
This reverts commit da756d69cc.
2015-04-08 22:34:44 +02:00
Dico200 da756d69cc Revert "Change to /modules... trying to make @command work."
This reverts commit 201c766119.
2015-04-08 22:32:54 +02:00
Dico200 201c766119 Change to /modules... trying to make @command work.
@command throws an error when it tries to access current_subs, which
supposedly didn't exist. current_subs stores all subcommands found when
defining the method which @command was added to. (These SHOULD be called
first)
2015-04-08 22:32:14 +02:00
Dico200 f7abc20ca1 Don't even bother. 2015-04-03 02:04:25 +02:00
Dico200 de43b0d0db Added (sub/main)command, removed abot error check
@command is untested.
2015-04-03 02:01:57 +02:00
Dico200 661e25dc67 Some tweaks and updates 2015-03-29 12:48:32 +02:00
Dico200 6590a8d30a Added cmd check to ABOT, commented out advancedcmd
advancedcmd doens't work atm, apparently
function.func_code is a thing but adding co_consts isn't an attribute of
that.

Tested abot, seems to work well.
2015-03-28 16:39:09 +01:00
Dico200 4cfa3a598f Tiny tweaks in basecommands.py 2015-03-26 16:48:54 +01:00
Dico200 75823ed042 Added basecommands.py
Contains @simplecommand and @basecommand
Slightly alterred simplecommand, made both display the command's
required permission when displaying help if the sender has the
permission "utils.showpermission".

Also a small tweak in misc.py's join listener.
2015-03-26 16:44:21 +01:00
Dico200 9855f62e7b Replaced /pyeval too, untested atm. 2015-03-25 00:55:13 +01:00
Dico200 75c9a86ba3 Replaced /sudo and /me with @simplecommand hook
Also improved simplecommand a little bit.
Don't ask me why it doesn't work in its own file as I have no clue, it
wasn't tracing the errors.
2015-03-25 00:38:56 +01:00
Dico200 d160bbd91a Revert "Moved simplecommand to its own module"
This reverts commit 669c2d0eb8.
2015-03-24 23:45:23 +01:00
Dico200 669c2d0eb8 Moved simplecommand to its own module
The module is named simplecommand.py (wow, didn't expect that!)

And I also cleaned it up a little bit, and tried to make clear how the
fuck it works. This shit is weird.
2015-03-23 23:24:10 +01:00
Dico200 7b8242697a CommandManager works! (Renamed to simplecommand)
See at the bottom of helpers.py!
I'm quite excited for this addition <3
2015-03-23 23:03:11 +01:00
Dico200 f1b2c61411 Fix reports.py. Oops. 2015-03-23 22:04:53 +01:00
Dico200 5f2ee6add9 Added commandmanager module. ALSO UNTESTED!
Will test now.
2015-03-23 21:30:44 +01:00
Dico200 f6de0a6c78 Added synchronizeranks. Untested! 2015-03-23 20:08:38 +01:00
Dico200 8a95dc65f6 Quick fix 2015-03-20 01:28:02 +01:00
Dico200 98774e8f84 Report code cleanup and /rp reopen
These changes are not yet tested!!!
2015-03-20 01:25:35 +01:00
Dico200 71c0f8782c Removed redundant code check and small tweak 2015-03-20 00:07:47 +01:00
Dico200 3bdb56e8a2 Changed reports module fixes #10
Write /rp ingame for new commands n stuff.
2015-03-20 00:06:47 +01:00
Dico200 1750c82208 Changed all CommandExecutor arguments
Added arguments command and label to all command executor functions,
hopefully for massive performance increase.

This is due to the following mess in PythonLoader:
``` Java
@Override
public boolean onCommand(CommandSender sender, Command command, String
label, String[] args) {
boolean result;
if (argcount == -1) {
try {
result = call(4, sender, command, label, args);
argcount = 4;
} catch (PyException e) {
//this could goof up someone ... they'll probably yell at us and
eventually read this code ... fuck them
if (e.type == Py.TypeError && (e.value.toString().endsWith("takes
exactly 3 arguments (4 given)") || e.value.toString().endsWith("takes
exactly 4 arguments (5 given)"))) {
result = call(3, sender, command, label, args);
argcount = 3;
} else if (e.type == Py.TypeError && (e.value.toString().endsWith("takes
exactly 2 arguments (4 given)") || e.value.toString().endsWith("takes
exactly 3 arguments (5 given)"))) {
result = call(2, sender, command, label, args);
argcount = 2;
} else {
throw e;
}
}
} else {
result = call(argcount, sender, command, label, args);
}
return result;
}
```

Note: Still WIP on reports - I'm working on making it keep solved
reports to fix issue 10
2015-03-19 23:51:33 +01:00
Dico200 d993cc223a Changed AC from toggle or , fixes #16
This solution to log any AC isn't very optimised as it will check for
permission twice. Any fix for this?

Anyways it now runs /ac <msg> from the player every time.
2015-03-19 22:02:07 +01:00
Dico200 40fa9c0692 simplified /me in misc.py
Replaced online user iteration with broadcast method
2015-03-19 21:51:13 +01:00
Dico200 5d23fe490b Remove annoying Damnspam plugin header
I hate plugin_header, can we maybe make it return a string which we
append the message to instead? ._.
or create like plugin_message(String pluginname, Player recipient,
String message)
2015-03-19 20:25:47 +01:00
Dico200 9476a1b0b7 Remove redundant try/catch 2015-03-18 22:26:54 +01:00
Dico200 194958f034 me cmd appearance hotfix (made new cmd) fixes #15 2015-03-18 22:25:58 +01:00
Dico200 55ac6c0977 Change /sudo command fixes #14 2015-03-18 21:09:49 +01:00
Dico200 39654bf4a7 Re-enabled AdminNotes module 2015-03-17 00:56:50 +01:00
jomo 4357c46085 copy dict keys before iterating
python doesn't like changing dicts while iterating over that dict
2015-03-15 05:00:04 +01:00
jomo 1db0ac4cd5 Revert "remove redundant loop"
This reverts commit cc50dc30bc.
2015-03-15 04:40:09 +01:00
jomo 1e7bd51b3b debug pmutils player leave event 2015-03-15 04:36:08 +01:00
jomo cc50dc30bc remove redundant loop 2015-03-15 04:28:56 +01:00
jomo a87ad7b2e9 fix all bukkit/uuid issues in pmtoggle 2015-03-15 04:26:53 +01:00
jomo dbfc1dd2a2 merge 2015-03-15 04:19:02 +01:00
Dico200 f1856d3243 Disable adminnotes, fix stuff 2015-03-15 04:17:12 +01:00
Dico200 5ef17713a4 Change runas() in helpers to use player.chat 2015-03-15 04:03:40 +01:00
Dico200 96b4cb2e3f Disabled snowbrawl 2015-03-15 04:00:51 +01:00
Dico200andjomo 88a935f473 Fixed UUID problem in Pmtoggle
Thanks @jomo  for pointing out
2015-03-15 03:00:55 +01:00
Dico200andjomo ad70989a40 Add colon in pmtoggle 2015-03-15 03:00:55 +01:00
Dico200andjomo a24c7092f7 Add check if chatevent is cancelled in pmtoggle 2015-03-15 03:00:52 +01:00
Dico200andjomo dc307fc5f0 cherry-pick pmtoggle into master 2015-03-15 03:00:18 +01:00
jomo 966943b9a2 Merge branch 'master' into dev 2015-03-15 02:58:03 +01:00
Dico200 1b2b3c2fa9 Fixed UUID problem in Pmtoggle
Thanks @jomo  for pointing out
2015-03-15 02:41:58 +01:00
Dico200 c0c1879fde Add colon in pmtoggle 2015-03-15 02:30:52 +01:00
Dico200 017d53928a Add check if chatevent is cancelled in pmtoggle 2015-03-15 02:30:33 +01:00
Dico200 bab2a6e198 Added pmtoggle to shared["load_modules"] in main 2015-03-15 02:20:41 +01:00
Dico200 5a669893b4 Remove redundant try/except in Pmtoggle module 2015-03-15 02:18:02 +01:00
Dico200 9a3942c034 pmtoggle works now, Fixes comments by Jomo
BTW: I didn't use retrieve_player as it gets an Offline player which
makes it slower and I know the player is online. That's why I used
Bukkit.getPlayer(juuid(uuidstring)). (line 40)
2015-03-15 02:16:30 +01:00
Dico200 43a8ec9481 Added pmtoggle module
pmtoggle adds /tm [player](togglemessage).
When activated, any chat message you send will be sent as:
/msg [player] [msg]
2015-03-15 01:13:36 +01:00
Dico200 1fd3d591f9 Fixed a little code in snowbrawl.py... even if its an outdated version. 2015-02-21 15:55:41 +01:00
jomo 2246b9f5a8 fix mentio color codes 2015-02-09 21:31:31 +01:00
PanFritz 60181bd657 Removed . from operators, remade line 17 2015-01-17 14:33:49 +01:00
PanFritz 9b4d73cfe2 Added check for . 2015-01-17 14:03:20 +01:00
PanFritz c1a69c6a62 Fixed, upping snowball damaga 2015-01-17 05:31:32 +01:00
PanFritz 3bcfe42d65 Fixed, upping snowball damaga 2015-01-17 05:30:15 +01:00
PanFritz ebe7b433ac Fixed, upping snowball damaga 2015-01-17 05:29:08 +01:00
PanFritz 511e4aa543 Fixed, upping snowball damaga 2015-01-17 05:27:52 +01:00
PanFritz 97733e7701 Fixed, upping snowball damaga 2015-01-17 05:17:27 +01:00
PanFritz 194d10b3c2 Fixed, upping snowball damaga 2015-01-17 05:16:28 +01:00
PanFritz b8df8f8a6b Fixed, upping snowball damaga 2015-01-17 05:15:04 +01:00
PanFritz c6ff9ccfa7 Fixed, upping snowball damaga 2015-01-17 05:13:38 +01:00
PanFritz f9a99aaf0b Fixed, upping snowball damaga 2015-01-17 04:51:22 +01:00
PanFritz 955e40dc34 Fixed, upping snowball damaga 2015-01-17 04:49:41 +01:00
PanFritz eba2b6731f Fixed, upping snowball damaga 2015-01-17 04:47:30 +01:00
PanFritz a18cc32c60 Fixed, upping snowball damage 2015-01-17 04:41:45 +01:00
PanFritz 02d073eb2c Changed entity name 2015-01-17 04:40:10 +01:00
PanFritz c062ce6782 changed getType to getTypeId 2015-01-17 04:36:41 +01:00
PanFritz ea3331f540 changed getType to getTypeId 2015-01-17 04:34:21 +01:00
PanFritz 583e2cd4f9 changed getType to getTypeId 2015-01-17 04:31:03 +01:00
PanFritz 041bc029ca More debug code 2015-01-17 04:25:23 +01:00
PanFritz 8efd791e54 debug 2015-01-17 04:24:08 +01:00
PanFritz 59c5c8ed02 import 2015-01-17 04:19:03 +01:00
PanFritz d67b96debe snowbrawl fix. event.getEntity() 2015-01-17 04:13:27 +01:00
PanFritz 8937f634e0 snowbrawl fix. event.getEntity() 2015-01-17 04:08:07 +01:00
PanFritz cdc747b740 added import 2015-01-17 01:18:06 +01:00
PanFritz 973ae69fb4 syntax fix 2015-01-17 01:06:35 +01:00
PanFritz 1c4ec9227e update explosion 2015-01-17 01:04:44 +01:00
PanFritz a86331c33d added import 2015-01-17 00:47:49 +01:00
PanFritz e072580c0d changed event name 2015-01-17 00:44:21 +01:00
PanFritz 759baa869a changed event name 2015-01-17 00:41:17 +01:00
PanFritz 46b3946ee7 commented un needed stuff 2015-01-17 00:38:25 +01:00
PanFritz db4dd3c861 fixed module 2015-01-17 00:35:29 +01:00
PanFritz ce332e7c7c org.bukkit.event.entity.ProjectileHitEvent 2015-01-17 00:34:10 +01:00
PanFritz 5fc18d034f added debug code 2015-01-17 00:21:42 +01:00
PanFritz bc2c5196b2 added snowbrawl to modules 2015-01-17 00:03:49 +01:00
PanFritz 8cc089a11b added snowbrawl.py 2015-01-17 00:01:00 +01:00
PanFritz 496a5d2735 aparently i changed damnspam. Fixed 2015-01-16 23:45:17 +01:00
PanFritz 1515777494 added . to maths operator to support floats 2015-01-16 23:40:14 +01:00
Gap 9a42172c4e A space :3 2015-01-14 18:48:41 +01:00
Gap 1ad6651e52 Adds AdminNotes 2015-01-14 18:36:03 +01:00
Gap 3f9e647e25 Fixed typo + forgot variable 2015-01-14 18:35:47 +01:00
Gap 8b5b90513e Adds note module 2015-01-14 18:31:44 +01:00
Gap 86756713a1 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-01-14 18:30:31 +01:00
Gap 7c6bfd7f12 Adds note module 2015-01-14 18:29:38 +01:00
PanFritz 197ef515b9 Reverted changes 2015-01-13 13:12:00 +01:00
PanFritz 89c5c3e646 Added should_calc check and done expression var 2015-01-13 13:05:22 +01:00
PanFritz f85a8e1bab removed should_calc condition from line 23, replaced break 2015-01-13 12:51:25 +01:00
PanFritz daf325a6e4 testing 2015-01-13 12:48:12 +01:00
jomo c69e8e80b2 420 = blazeit 2015-01-11 00:56:06 +01:00
jomo 9fa736691c only output numbers
we also support shifting (>>, <<), so the > and < characters are allowed which might lead to a bool type output
we don't want to show bool output
2015-01-11 00:00:39 +01:00
jomo 00fd8e4f1e clean up check.py 2015-01-10 22:44:18 +01:00
jomo f9c6df58c5 remove tab 2015-01-10 22:26:49 +01:00
jomo c6dd5ce4a9 add >, <, ~ and % operators to calc 2015-01-10 00:37:03 +01:00
jomo 611d52ea2b Merge branch 'dev' 2015-01-09 23:06:52 +01:00
PanFritz d4813f7dc5 fixed indentation on damnspam 2015-01-09 22:39:20 +01:00
PanFritz 702c8ec2cf fixed indentation on damnspam 2015-01-09 22:31:28 +01:00
PanFritz 248a848b53 Merge branch 'dev' 2015-01-09 21:38:04 +01:00
PanFritz 4a3fcbd1d5 Changed index of results[] to fit array of tuples 2015-01-09 21:16:04 +01:00
PanFritz 22978a1700 Changed index of results[] to fit array of tuples 2015-01-09 21:11:26 +01:00
PanFritz c205f3457e Debug log results 2015-01-09 21:06:08 +01:00
PanFritz f42b1272b5 Progress 2015-01-09 21:04:02 +01:00
PanFritz 4ad849285c Testing converting results to string 2015-01-09 20:58:27 +01:00
PanFritz 1afd238799 More try/except 2015-01-09 20:51:29 +01:00
PanFritz 02bf56bf4a Added try except to str converion 2015-01-09 20:47:29 +01:00
PanFritz 2295350be6 Added try except 2015-01-09 20:45:40 +01:00
PanFritz db940cdd6e possible fix 2015-01-09 20:40:10 +01:00
jomo 65352519c7 link to info, not /faq command on first join 2015-01-09 01:35:40 +01:00
jomo 8eb0948a61 don't need quotes 2015-01-08 00:44:56 +01:00
jomo f465a4caff nope #8 2015-01-08 00:40:18 +01:00
jomo 4f3cd5ba63 possible fix for #8 2015-01-08 00:38:00 +01:00
jomo ae261d3026 fix error on offline players 2015-01-07 02:05:08 +01:00
jomo 8129bf5fd4 fix offline players 2015-01-07 02:01:00 +01:00
jomo e7c4eba51f oops 2015-01-07 01:39:41 +01:00
jomo ef770dd145 fix typo 2015-01-07 01:36:46 +01:00
jomo 60cc678470 show traceback on error 2015-01-07 01:35:26 +01:00
jomo 9230a048af improve check.py 2015-01-07 01:33:18 +01:00
jomo 7f97087ddb fix /check old usernames 2015-01-07 01:05:49 +01:00
jomo 8b2bf3bf72 delete duplicate chat message 2015-01-07 00:55:08 +01:00
jomo 68430fa175 move module descriptions to main.py or modules themself 2015-01-07 00:17:20 +01:00
jomo f579759e60 better comments in misc.py 2015-01-06 23:59:36 +01:00
jomo 9a916ed2cd change indentation from 2 spaces to 4, fix #5 2015-01-06 23:38:42 +01:00
jomo 3435e99432 Revert "Fixed calc when calling toggle"
This reverts commit 825acf330a.
2015-01-06 23:07:56 +01:00
jomo 4eed09946a Merge branch 'dev' of github.com:RedstonerServer/redstoner-utils into dev 2015-01-06 23:05:43 +01:00
PanFritz 1cb1b96755 Added imout to modules 2015-01-06 22:54:17 +01:00
jomo 91d4a1e186 re-implement toggle()'s add=True|False 2015-01-06 22:36:57 +01:00
jomo 50b09138f8 re-add optional arg to toggle() 2015-01-06 22:30:30 +01:00
PanFritz 825acf330a Fixed calc when calling toggle 2015-01-06 22:23:42 +01:00
jomo 7d7d5e16e1 remove junk in toggle() 2015-01-06 22:19:06 +01:00
PanFritz fb4aff2e04 Removed 'add' condition from helpers.py toggle method 2015-01-06 22:08:36 +01:00
jomo d8bd90544b clean up comments 2015-01-06 21:32:40 +01:00
jomo 6310633ebb disable spectator teleportation 2015-01-06 21:29:00 +01:00
Gap 3e6683725e Removed debugging/enhanced output 2015-01-02 14:12:35 +01:00
jomo 01da1ed812 more docs for helpers, removed unused warp() 2015-01-02 02:26:52 +01:00
jomo 8de52f9ab6 use name parameter for toggle() 2015-01-02 02:21:48 +01:00
jomo 11b08a20a1 /calc can only be used on sender 2015-01-02 02:21:11 +01:00
jomo 00dfc770fe add name parameter to toggle() 2015-01-02 02:20:02 +01:00
jomo d92f98307f improve calc, make users savable 2015-01-02 02:17:17 +01:00
jomo f2a30f3aa2 typo 2015-01-02 01:47:43 +01:00
jomo 226ca3ebf1 welcome to python 2015-01-02 01:47:03 +01:00
jomo 310a347bc8 fix badges style and stuff 2015-01-02 01:43:47 +01:00
jomo 6ec7ad23ed stfu pylint 2015-01-02 01:39:43 +01:00
jomo 9110fc2eda more calc improvements 2015-01-02 01:28:39 +01:00
jomo 0842d92187 docs 2015-01-02 01:23:17 +01:00
jomo a51e715bc7 using checkargs 2015-01-02 01:19:10 +01:00
jomo 24cbcb94ab stone_button = stone button 2015-01-02 01:15:25 +01:00
jomo 3e00e52632 better color 2015-01-02 01:14:35 +01:00
jomo 0dcffd0ff3 improve calc.py 2015-01-02 01:07:10 +01:00
Gap 0448386fa7 Final modification for today 2015-01-01 23:33:54 +01:00
Gap e9c78edb46 Forgot comma... -.- 2015-01-01 22:52:13 +01:00
Gap 461cfca4c6 Added check and badges 2015-01-01 22:49:33 +01:00
Gap df24abbf62 Removed debugging shit 2015-01-01 22:48:25 +01:00
Gap 1fd75516a9 Added player reward module 2015-01-01 22:31:53 +01:00
Gap fef075b7d2 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-01-01 22:27:55 +01:00
Gap e92ed7e752 (+Pan) Added small chat calculator 2015-01-01 22:24:24 +01:00
jomo 792c8405fb add license, fixes #1 2014-12-26 18:28:59 +01:00
jomo 3b2ad46ab9 fix /check output 2014-12-26 18:28:19 +01:00
Derrick Lim 967bda67da /gm finished for now, will remain commented 2014-12-27 00:42:01 +08:00
Derrick Lim e4ab382d98 Squashed some /gm bugs
Thnx sheep
2014-12-27 00:17:53 +08:00
Derrick Lim 0677f8460d Added /gm - commented for now 2014-12-26 18:48:30 +08:00
Gap 41d9f719f9 Enables ACT for players who are set to offline 2014-12-21 15:25:42 +01:00
jomo af29a62096 load check module on start 2014-12-20 18:56:35 +01:00
jomo 6cc2624621 add secrets.py.example 2014-12-20 18:53:52 +01:00
shillingp 1c7460438f Merge branch 'dev' of github.com:RedstonerServer/redstoner-utils into dev 2014-12-20 17:11:17 +00:00
jomo 6fd1f3610d add secrets.py to gitignore 2014-12-20 17:46:04 +01:00
jomo d8e2fbccf7 add secrets.py to gitignore 2014-12-20 17:45:43 +01:00
shillingp 74dfdb580d Added support for damnspam -1 time arguments 2014-12-19 23:28:33 +00:00
jomo 74121f139c use GitHub's wiki :octocat: 2014-12-18 01:16:25 +01:00
jomo 9606e21770 Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-12-17 22:19:04 +01:00
jomo ce8683e85a remove windoge line breaks 2014-12-17 22:13:23 +01:00
jomo 46fad3c2f4 remove install script from readme 2014-12-14 23:35:04 +01:00
Louis Vogt 004140b2df Added fake leave / join module 2014-12-12 20:28:23 +01:00
jomo 6f16ed15ea small cleanup 2014-08-10 05:18:06 +02:00
Louis Vogt ad4fb7a700 New check module (shows some statistics) 2014-08-09 02:15:36 +02:00
Louis Vogt b11ed0f9bf Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-08-08 23:39:28 +02:00
jomo 885589eb7b repalce input with lever/button 2014-08-08 05:47:47 +02:00
jomo 5361e0d8db move line to correct position 2014-08-08 05:42:03 +02:00
jomo d0acf1bd36 fixing endless loop 2014-08-08 05:37:45 +02:00
jomo 10d8498ce4 check if player is allowed to remove input 2014-08-08 05:14:22 +02:00
jomo 8ecae8fe23 reset changing_input 2014-08-08 04:33:27 +02:00
jomo f751207865 allowing to update timeouts | not sure if this works ;_; 2014-08-08 04:26:16 +02:00
Louis Vogt 167bc9dfcf Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-08-07 22:51:01 +02:00
jomo ff7e3e4e67 enable damnspam 2014-08-07 22:46:02 +02:00
jomo f9e09d0f86 small bugfixes 2014-08-07 22:41:02 +02:00
jomo 6c164a054a case insensitive /lol search 2014-08-07 04:21:16 +02:00
jomo 5ecd804d63 remove friends plugin. Too buggy! 2014-08-07 03:32:18 +02:00
jomo 34e703bb3e forgot to import thread 2014-08-07 03:31:47 +02:00
jomo 0b98ba42d3 forgot space 2014-08-07 03:03:27 +02:00
jomo 1238ca66f3 more threading / offlineplayer fixes 2014-08-07 02:53:24 +02:00
jomo adaddd7500 use threading for offline players 2014-08-07 02:49:34 +02:00
Louis Vogt 229ee65e2a Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-08-07 02:36:23 +02:00
jomo 0cf6c53405 use new thread for reports list 2014-08-07 02:30:44 +02:00
jomo bea7d369ac get rid of dico's stupid nonsense :3 2014-08-07 02:27:49 +02:00
jomo 6d04f31a8c get rid of offlineplayer in friends 2014-08-07 02:24:45 +02:00
jomo a48919c94c get rid of OfflinePlayer in forcefield 2014-08-07 02:21:44 +02:00
jomo 363f5cddda remove WTF methods from player welcome 2014-08-07 02:19:53 +02:00
jomo 286ca74f71 fix %s 2014-08-07 02:10:36 +02:00
jomo 733e669e8b clarifiy known_player a bit more 2014-08-07 01:50:26 +02:00
Louis Vogt cb8334b533 Modified known_player method 2014-08-07 01:46:53 +02:00
jomo b31e887aa4 better /lol search 2014-08-07 01:39:12 +02:00
jomo 9aeea06ce9 revert to mob.chicken.plop, lavapop can be overheard easiliy 2014-08-07 01:26:28 +02:00
jomo ba9f59c041 add note if no keywords 2014-08-07 01:25:20 +02:00
jomo 82e912d77e change highlight style. (underline hides parts of the next line) 2014-08-07 01:18:11 +02:00
jomo 9404f91e91 keyword must be IN the word, not exaclty the word 2014-08-07 01:17:26 +02:00
jomo 6e65173c4a don't be racist against players with uppercase characters in their name 2014-08-07 01:11:15 +02:00
jomo 43f8f95961 delete mentions if empty 2014-08-07 01:06:19 +02:00
jomo a73b1da7ca rewrite big parts of mentio 2014-08-07 00:59:13 +02:00
jomo 28d0182496 FIX THIS BEFORE MERGING! 2014-07-31 00:07:15 +02:00
jomo 044134f0c4 nicer string concatenating 2014-07-30 23:51:23 +02:00
jomo dc6d4d5f4b remove try/except. fix code if it doesn't work ;) 2014-07-27 23:55:15 +02:00
jomo b0aa83104c catch all exceptions in pyeval 2014-07-27 23:29:55 +02:00
jomo 63810a0782 better name + docs for played_before (renamed to known_player) 2014-07-27 22:44:12 +02:00
jomo 4707b0fd91 more documentation 2014-07-27 22:39:20 +02:00
jomo 81669c62d7 rename log to info 2014-07-27 22:20:18 +02:00
jomo 1ee5d9b456 add warn() logging 2014-07-27 22:17:24 +02:00
jomo 333437e87a readability 2014-07-27 21:52:55 +02:00
jomo f9d1d8a83c mentio readability, remove <> around mention highlight 2014-07-27 19:49:55 +02:00
jomo 9231d23bcb readability 2014-07-27 19:43:06 +02:00
jomo b1a3a92e49 apply file read/save helpers 2014-07-27 19:42:33 +02:00
jomo e9b0ad656b add path to save/open json file 2014-07-27 06:04:31 +02:00
jomo d58d975910 add default to open_json_file 2014-07-27 06:01:52 +02:00
jomo efc3ee439c better use of plugin_header in saylol 2014-07-27 05:41:25 +02:00
jomo e04053e46f add /lol search <text> 2014-07-27 05:28:31 +02:00
Louis Vogt 2a1c2f3919 Wrong receiver; new plop; no simplejson; still 1 bug 2014-07-26 14:19:31 +02:00
jomo 304da99ca4 Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-07-25 00:05:51 +02:00
jomo d2fe36aee3 link to latest python loader jar, remove jython download 2014-07-25 00:05:42 +02:00
Louis Vogt 047c763a23 Enabled custom mentions (not tested yet) 2014-07-24 15:20:23 +02:00
jomo fb60c0c178 allow to reset motd 2014-07-24 02:31:34 +02:00
jomo bdabfc0054 clean up friends.py 2014-07-24 02:12:54 +02:00
jomo 60b523f0d1 readme stuff
- avoid long methods
- clarify errors
- better traceback example
2014-07-24 01:19:55 +02:00
Dico aafac2fe5a Minor change 2014-07-23 01:04:53 +02:00
Dico 8751123f8c Removed useless lines 2014-07-23 00:56:31 +02:00
Dico 1cba2f9db9 Didn't add module last time...? 2014-07-23 00:55:32 +02:00
Dico 5a47cf3c20 Added friends module. Thanks piggly for testing! :D 2014-07-23 00:53:24 +02:00
jomo 2057c81918 remove test code 2014-07-23 00:00:18 +02:00
jomo 7d356f9eb0 trying stuff 2014-07-22 00:46:00 +02:00
jomo a5eb215b5b use &-colors for motd on first load 2014-07-21 02:35:06 +02:00
jomo a9e0c621ec remove test line 2014-07-21 02:34:36 +02:00
jomo 7f74482fa4 fix plugin_header 2014-07-21 02:31:46 +02:00
jomo b295f12d56 raise test error 2014-07-21 02:28:39 +02:00
jomo 3da64f301d add /modules command
lists all modules.
green if loaded, red otherwise
2014-07-21 02:24:43 +02:00
jomo ce8b20aacd fix problem with 'none' permission 2014-07-21 02:07:45 +02:00
jomo befd5a1721 nicer pyeval output 2014-07-21 02:06:15 +02:00
jomo 70668f0210 fix broken broadcast 2014-07-20 17:53:19 +02:00
jomo 3a62687d6e deploying details added to readme 2014-07-20 17:05:15 +02:00
jomo fbf7722831 renamed fyle to f 2014-07-20 16:46:20 +02:00
jomo 878caad751 fix horidicode 2014-07-20 16:37:41 +02:00
Dico 6d3d2edf51 README.md edited online with Bitbucket 2014-07-19 03:10:02 +00:00
Dico ff7053e1b3 Fixed shecode. I knowo that 'file' is the correct spelling, but that does weird stuff and turns blue so just leave it this works and sheeps code doesnt <3 2014-07-19 05:02:09 +02:00
Dico 6ae2f4971a Added toggle() to helpers.py. I haven't tested it thoroughly but it doesn't give errors on start. You can read the comment for more info :D 2014-07-19 04:53:51 +02:00
jomo df91adf7fd fix dicallignment 2014-07-19 02:41:44 +02:00
jomo 243b4fab4f use name for CG logs 2014-07-19 02:37:57 +02:00
jomo 18c0ba0b67 fix re-writing variable 2014-07-19 02:32:35 +02:00
jomo 5b1e1ca383 fix dicode 2014-07-19 02:19:12 +02:00
jomo 6268672ccf fix imports 2014-07-19 02:02:42 +02:00
Dico 4966dac92e Minor tweaks and fixes 2014-07-19 02:00:54 +02:00
Dico 7c2306df9c Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-07-19 01:52:27 +02:00
Dico 775bdc6205 Small fixes and tweaks 2014-07-19 01:51:29 +02:00
jomo f95cb0269c remove forcefield for merge with master 2014-07-19 01:50:35 +02:00
Dico 231a5b8322 Stuff added to helpers.py, forcefield updated to be a lot more efficient (simple change) 2014-07-19 01:39:08 +02:00
Dico 30d670bade minor changes. @Sheep: Take a look at the changes I made to helpers module and tell me if I'm stupid. 2014-07-18 03:45:28 +02:00
Dico d2270ac263 Git messed around with my files, I updated it to use the uid() function in helpers.py now. 2014-07-18 02:50:14 +02:00
Dico 5373a1c4a4 wtf git adding random stuff to my files 2014-07-18 02:36:52 +02:00
Dico 835a7aa9fb Happy with this version/build. @Sheep: Don't fix my 'dicode'! 2014-07-18 02:27:24 +02:00
jomo 8db6085d63 use uid(player) helper method 2014-07-17 22:24:45 +02:00
jomo ebf8a22bae using is_creative helper 2014-07-17 22:13:49 +02:00
jomo a5e9fd348f make dicode DRY and more readable 2014-07-17 21:36:05 +02:00
Dico 8701578875 Rewrote velocity calculation. 2014-07-17 17:47:49 +02:00
Dico 15c06f011b Minor fix 2014-07-17 16:06:11 +02:00
Dico 372a831c82 Converted reports module to UUID and minor changes to forcefield module 2014-07-17 15:26:48 +02:00
Dico 2c1c6928a9 removing feature which doesnt work and is stupid 2014-07-17 05:40:54 +02:00
Dico 760d2a4d16 Cool stuff 2014-07-17 05:29:55 +02:00
Dico f45547f808 Another minor change 2014-07-17 05:10:24 +02:00
Dico 9f6186ad15 Minor change 2014-07-17 04:54:44 +02:00
Dico eab60c5502 No saving to files yet, but it definitely works well now. 2014-07-17 04:49:31 +02:00
Dico f709533ade Updates! YAY! 2014-07-17 03:48:14 +02:00
Dico 23f85b4baa Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-07-17 01:17:28 +02:00
jomo a5e09e3254 show return type in pyeval 2014-07-17 01:16:37 +02:00
Dico 0b94c02757 Working version 2014-07-17 01:13:22 +02:00
jomo 400e8ec4dd undo dicode 2014-07-17 00:52:22 +02:00
Dico cda6984726 Fixing bugs & Cleaning up code. Seems to work well now! 2014-07-17 00:48:41 +02:00
jomo 6afc92102f debugging 2014-07-16 02:15:23 +02:00
jomo 306b479cad debugging 2014-07-16 02:11:52 +02:00
jomo ad94e31d21 use better names, fix bugs 2014-07-16 02:04:02 +02:00
jomo 60a1210fe1 add readability spacing 2014-07-16 01:08:04 +02:00
jomo 930ca56dfc add readability to coding guidelines 2014-07-16 00:59:02 +02:00
jomo 9a0779d168 more code cleanup 2014-07-16 00:49:55 +02:00
jomo a61691bb1d added Pro Tip (tm) 2014-07-16 00:39:25 +02:00
jomo 53519b0901 clarified camelCase usage 2014-07-16 00:38:15 +02:00
jomo d9b8252ab1 corrected s/idToPlayer/java_uuid/ 2014-07-16 00:34:49 +02:00
jomo 1430a454ed removed camelcase, added more coding style to readme 2014-07-16 00:33:43 +02:00
Dico d2ec8b6d3f Sorry for spam 2014-07-15 19:36:50 +02:00
Dico ad885d8707 Fixing movement bugs 2014-07-15 19:16:30 +02:00
Dico 2acd32f80e Think I finally fixed ALL forcefield bugs, command-side-wise 2014-07-15 18:49:36 +02:00
Dico 4b15a85ac8 Fixing moar bugs! 2014-07-15 14:19:45 +02:00
Dico b84a4d837a Fixing bugs... 2014-07-15 14:07:48 +02:00
Louis Vogt 0f5cfe6f2d Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-07-14 16:23:33 +02:00
Louis Vogt 9bbd6bba27 Added WIP custom words 2014-07-14 16:22:49 +02:00
Dico c4e206f44e Unfixing fix 2014-07-14 13:38:26 +02:00
Dico cce3c028a4 Fixing bugs 2014-07-14 13:32:37 +02:00
Dico ffae4e7d30 Added forcefield whitelist and hopefully fixed some bugs 2014-07-14 13:08:15 +02:00
jomo cf47df82ff check for cancelled event 2014-07-14 06:04:06 +02:00
jomo 4f13e417e9 check if player can build 2014-07-14 06:01:21 +02:00
jomo 4df5a18831 using floats for timeout 2014-07-14 05:57:27 +02:00
jomo 502aa3acc5 better message formatting 2014-07-14 05:42:44 +02:00
jomo 60c6b957f1 need more caffeine 2014-07-14 05:42:23 +02:00
jomo c51d703d1f fix time check 2014-07-14 05:33:46 +02:00
jomo 13b4c8c115 fix plugHeader, store last time 2014-07-14 05:32:14 +02:00
jomo 7dc4d6a88c I should stop using copy pasta 2014-07-14 05:27:59 +02:00
jomo 2979ecb44e range starts at 0 2014-07-14 05:25:57 +02:00
jomo f0e0045f70 cannot join string with ints 2014-07-14 05:24:08 +02:00
jomo a33e9ef88f don't accept 0 args, remove try 2014-07-14 05:20:30 +02:00
jomo 60c5bb9672 add damnspam to load_modules 2014-07-14 05:17:29 +02:00
jomo a6fecec165 Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-07-14 05:16:59 +02:00
jomo 7024fe4845 damnspam 2014-07-14 05:16:48 +02:00
Dico 63a2e9519e Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-07-14 02:42:45 +02:00
Dico 89cb6d2d2e added forcefield module, will make whitelist option later 2014-07-14 02:40:00 +02:00
jomo 05a68efc43 clarify how to use CG 2014-07-14 01:26:42 +02:00
jomo 879af23f9a logging groupchat messages 2014-07-14 01:25:12 +02:00
jomo bd5dcf1933 add noperm; return true 2014-07-14 01:20:42 +02:00
jomo 62b3f8a270 fix basecolor in abot 2014-07-14 01:20:11 +02:00
jomo fca2e7e1b2 add mising import 2014-07-14 01:17:51 +02:00
jomo 94932ce0bf creating shared dict 2014-07-14 01:16:40 +02:00
jomo 991030b326 getting the right name in pluginversions 2014-07-14 01:00:30 +02:00
jomo 8ee6d0f40a getting the right name in pluginversions 2014-07-14 01:00:06 +02:00
jomo c9763953d4 can't call function before definition 2014-07-14 00:56:46 +02:00
jomo 2a00635606 use json config for abot 2014-07-14 00:54:25 +02:00
jomo 7981591fb7 using jython 2.7b2 2014-07-13 17:10:14 +02:00
jomo 23973651cc typo fix 2014-07-13 17:03:11 +02:00
jomo d67bf75c24 fix merge conflicts 2014-07-13 16:35:21 +02:00
jomo 568b619122 use uuid in CG 2014-07-13 16:34:31 +02:00
Louis Vogt 41e1d3c65e Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-07-12 11:06:13 +02:00
Louis Vogt e79172af03 Added DamnSpam to descriptions 2014-07-12 11:05:08 +02:00
jomo 241292acce fix double quites 2014-07-12 03:10:42 +02:00
jomo 4b10679030 Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-07-12 03:08:10 +02:00
jomo fafba7f5a6 show online users by UUID; add quotes info to readme 2014-07-12 03:08:01 +02:00
Louis Vogt 3ad9503515 Added WIP DamnSpam module 2014-07-12 01:47:32 +02:00
Louis Vogt 0466cb781b Changed single quotes to double quotes 2014-07-12 01:17:13 +02:00
Louis Vogt b8b86be805 Uses UUID now + cg_key is now : 2014-07-11 23:50:27 +02:00
jomo f3c781ab47 more abot fixes 2014-07-11 00:26:49 +02:00
jomo 7cd3151d8c more abot fixes 2014-07-10 23:45:32 +02:00
jomo e78a147a44 match e.g. who can clear plot 2014-07-10 23:36:36 +02:00
jomo 9af08cfe4f remove empty matchgroup; first match has to be a word 2014-07-10 23:35:03 +02:00
jomo 55e3cbc137 fix false positive for e.g. MODel, MODern 2014-07-10 23:32:23 +02:00
jomo 8efb6bcc20 fix false positive for e.g. MODel, MODern 2014-07-10 23:30:35 +02:00
jomo bde3848ee6 skip abot for players with 'utils.ignore_abot' permission 2014-07-10 23:08:23 +02:00
jomo bf0507ee23 fix literal '.' in regex, fixes 2014-07-10 23:06:45 +02:00
jomo 7b742a3152 more noob matching 2014-07-10 22:58:47 +02:00
jomo 07f1a169c3 needs trailing space 2014-07-10 01:22:53 +02:00
jomo 755bd35abb fix typo, nicer output 2014-07-10 01:21:14 +02:00
jomo ec9063b6e7 do not require extra words 2014-07-10 01:11:25 +02:00
jomo 44af737e9e fucking comma 2014-07-10 01:03:39 +02:00
jomo c2814fac4a fix braces 2014-07-10 00:55:04 +02:00
jomo 2248007358 more questions 2014-07-10 00:52:32 +02:00
jomo 43e4015311 add abot (AnswerBot) to get rid of stupid FAQ asking 2014-07-10 00:37:42 +02:00
jomo 16217e1251 fix double plugin header 2014-07-09 00:24:55 +02:00
jomo c34c533dca add /echo 2014-07-09 00:18:26 +02:00
jomo 31112f95a9 make AC prefix red 2014-07-08 20:30:11 +02:00
jomo 4c893342f9 removed unused commands from welcome message 2014-07-08 19:55:54 +02:00
jomo 5ceb3f096c fix out of range /lol id 2014-07-08 02:17:37 +02:00
jomo 1017e64095 use cycle plugin in creative mode only 2014-07-06 20:49:11 +02:00
jomo 4ef56eab97 remove text-only commands, use commands.yml aliases 2014-07-05 21:28:26 +02:00
jomo 52f5f92e73 add 0.4s delay to shearing 2014-07-05 21:12:27 +02:00
jomo ab6e2a0c27 175:6 is no longer breaking clients 2014-07-05 21:05:47 +02:00
jomo da51c6f5fc tell people to use website 2014-07-05 21:05:18 +02:00
jomo c2031cbeed avoid using deleting e.g. reports[-1] 2014-07-05 18:58:22 +02:00
jomo d5e2cf282f fix broken report deletion 2014-07-05 18:54:52 +02:00
jomo 6534922886 allow newlines 2014-07-04 02:04:59 +02:00
jomo 991673779b fix broadcast 2014-07-04 02:00:04 +02:00
jomo d07883d0c4 fix plugin title 2014-07-04 01:54:23 +02:00
jomo 0a309f0f60 fix plugin title 2014-07-04 01:53:33 +02:00
jomo 4791f84356 add motd.py 2014-07-04 01:50:36 +02:00
jomo 8ffa50c436 fix deleteing non-existing report 2014-07-02 01:13:12 +02:00
jomo afdda4e564 fix shearsheep 2014-07-02 00:27:50 +02:00
jomo 15ed89098d fix typi 2014-06-29 18:28:13 +02:00
jomo 327772b03b don't cycle when sneaking 2014-06-29 18:26:02 +02:00
jomo f141f392f8 use strings for UUID 2014-06-29 16:25:17 +02:00
jomo e0e90c796f add newline to plugin headers 2014-06-29 16:22:28 +02:00
jomo 25dce528c4 save file on list change, fix up/down naming, remove logging 2014-06-29 16:21:59 +02:00
jomo f45c1c10dc save file 2014-06-29 16:15:42 +02:00
jomo 24bd4d58c2 fix indentation 2014-06-29 15:38:51 +02:00
jomo 5ed5753b38 better loggin 2014-06-29 15:37:45 +02:00
jomo 4a2cbf7f1f shift items, then check for empty line 2014-06-29 15:33:27 +02:00
jomo 04ab9e93cb shift items, then check for empty line 2014-06-29 15:21:16 +02:00
jomo dd8fe14858 move cycle plugin to new module; add features 2014-06-29 15:18:25 +02:00
jomo 91e826aec0 Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-06-29 09:19:43 +02:00
jomo 3697e19d79 use list(x) instead of x.tolist() 2014-06-29 09:19:33 +02:00
shillingp c1cf6b5b06 Complete inventory cycle 2014-06-27 15:16:03 +00:00
jomo f00215c5f5 make gettoken more user-friendly 2014-06-25 02:40:49 +02:00
jomo 98a6659ec4 Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-06-25 02:36:07 +02:00
jomo 549b64994d rename tokengen/gettoken 2014-06-25 02:35:47 +02:00
shillingp 23fb4d6644 misc.py edited online with Bitbucket 2014-06-23 23:09:55 +00:00
shillingp 53c9118755 getInventory not getContents 2014-06-23 23:07:25 +00:00
shillingp 794ff39b50 changed inventory event to player event 2014-06-23 22:59:59 +00:00
shillingp 09f2bc6e5e Added inventory cycle function 2014-06-23 22:52:04 +00:00
jomo fa944b4e37 fix comments 2014-06-23 03:16:09 +02:00
jomo 06a0bf8428 Merge branch 'dev' 2014-06-23 01:18:28 +02:00
jomo cf36f6b525 adjust rules 2014-06-23 01:18:15 +02:00
jomo 5a5092ed32 fix rule alignment; change color 2014-06-23 01:02:09 +02:00
jomo ddc700d1a4 fixed wrong prefix in /cgt 2014-06-23 00:34:00 +02:00
jomo 03d0ca1924 add mentio.py again, now working 2014-06-22 02:15:01 +02:00
jomo cd35888164 Merge branch 'dev' 2014-06-22 02:12:05 +02:00
jomo a391165995 awesome new feature 2014-06-22 02:11:43 +02:00
jomo 871f3385f3 fix deprecated event 2014-06-21 14:39:43 +02:00
jomo 7560bf1de3 fixed wrong event priority names 2014-06-21 14:34:00 +02:00
jomo 9a10123179 y u no work 2014-06-21 14:32:07 +02:00
jomo 80018d5deb derp, need to use lower event so ac cancels before mentio 2014-06-21 14:26:24 +02:00
jomo cbf0fa2cf0 Merge branch 'dev' of bitbucket.org:redstonesheep/redstoner-utils into dev 2014-06-21 14:07:15 +02:00
jomo e6b05127c0 use asyncplayerchatevent for adminchat, listen after mentio 2014-06-21 14:07:05 +02:00
jomo c02f93d466 fixed spigot link 2014-06-21 11:06:27 +00:00
jomo 9d4fc9f87b using list(x) instead of x.tolist() 2014-06-21 12:50:03 +02:00
jomo 7dcda40b1a only using recipient list when iterating 2014-06-21 12:47:25 +02:00
jomo eb06427ecf rename tokengen to gettoken, add warning 2014-06-21 12:43:16 +02:00
jomo 63c1f07a72 lots of stuff for readme 2014-06-21 12:38:44 +02:00
jomo c99e283651 catch java exceptions, too 2014-06-21 11:09:10 +02:00
jomo 4e3cecc38d ignore everything in files/ 2014-06-21 11:08:18 +02:00
jomo ade4694999 catch java exceptions, too 2014-06-21 11:05:59 +02:00
Louis Vogt a6b22945d8 Converted set into list 2014-06-21 10:01:35 +02:00
jomo a20f942a0f remove mention due to error spam 2014-06-21 02:29:04 +02:00
jomo 68018d9c2a copying recipients before iterating 2014-06-21 01:18:00 +02:00
jomo a63a28a2c4 catch everything 2014-06-21 01:12:27 +02:00
jomo 610e926a54 quick fix 2014-06-21 01:00:21 +02:00
jomo 151a8525d7 fix colors, highlight word, create sound 2014-06-21 00:52:16 +02:00
jomo 379751e1fb better way to debug plugins 2014-06-20 22:24:20 +02:00
jomo 031dea64e2 add (unused) code to create awesome screenshots :D 2014-06-20 22:23:09 +02:00
Louis Vogt d4a14b4601 Fixed indention. Finally. 2014-06-20 22:16:17 +02:00
Louis Vogt 403348daa3 Fixed intentation+spelling mistake 2014-06-20 22:13:09 +02:00
Louis Vogt 6df5cab599 Added mention module 2014-06-20 22:04:39 +02:00
Louis Vogt f23a6ee05a Added mention module 2014-06-20 21:56:30 +02:00
jomo 43b129770d delete files/ 2014-06-17 00:20:10 +02:00
jomo b36f09aca7 remove tilehelper for master 2014-06-17 00:11:49 +02:00
shillingp 6d63b37d68 spelling mistakes 2014-06-16 22:09:20 +00:00
shillingp 26c5f4d1de Messages altered and colored 2014-06-16 22:03:44 +00:00
shillingp 9752caece4 Fixed fail if statement 2014-06-16 21:53:12 +00:00
shillingp 2604ed499c spawn to teleport command, implemented head position 2014-06-16 21:41:06 +00:00
shillingp 93a2db5532 Import material removed, material as string 2014-06-16 21:24:06 +00:00
shillingp 0db2d58e89 Import materials for Material.PORTAL 2014-06-16 21:21:22 +00:00
jomo 03159d549c Merged in shillingp/portal-safety-1402935495123 (pull request #1)
misc.py added login portal safety
2014-06-16 23:11:58 +02:00
shillingp f22212a093 misc.py added login portal safety 2014-06-16 16:19:32 +00:00
jomo 75cce75aa2 log errors 2014-06-11 23:10:39 +02:00
jomo 12e1191653 use simplejson 2014-06-10 06:32:28 +02:00
jomo 012a98d0e5 load tilehelpers from file 2014-06-10 06:25:25 +02:00
jomo 5e75884482 sleep 2 ticks so changes can be applied 2014-06-10 06:06:40 +02:00
jomo 0f44ad5c53 handle right click 2014-06-10 06:01:59 +02:00
jomo 89d106967a bugfix 2014-06-10 05:43:36 +02:00
jomo 5390a6578d fix block data; use Interact instead of DamageEvent 2014-06-10 05:31:39 +02:00
jomo 34de631403 add BlockDamageEvent 2014-06-10 05:17:44 +02:00
jomo 7eeb34f65c use data from blockstate 2014-06-10 05:15:10 +02:00
jomo cddd3a1dcc add data to blockPlaceEvent 2014-06-10 05:12:18 +02:00
jomo 54e3fd052f remove debug output 2014-06-10 04:57:11 +02:00
jomo 682f22b99d bugfixes 2014-06-10 04:53:36 +02:00
jomo 5175ce5b81 AAAARGH 2014-06-10 04:50:55 +02:00
jomo c95760fe92 cannot believe this... BrakeEvent >_< 2014-06-10 04:47:59 +02:00
jomo d205c096da added BlockBrakeEvent 2014-06-10 04:45:01 +02:00
jomo cd346f9e60 oops 2014-06-10 04:23:13 +02:00
jomo 13a828ad29 trying to use new block AND new block's state 2014-06-10 04:19:41 +02:00
jomo d2d4eff3a7 debugging 2014-06-10 04:17:37 +02:00
jomo 8508b0f2b4 debugging 2014-06-10 04:13:04 +02:00
jomo 0b52b8d79f debugging 2014-06-10 04:01:46 +02:00
jomo cdf17c7f7f debugging 2014-06-10 03:58:40 +02:00
jomo 6218891146 oops, need to use newblock, not newagainst 2014-06-10 03:46:59 +02:00
jomo 1fc6489892 debug 2014-06-10 03:44:02 +02:00
jomo 20d8e506cc using block from blockstate 2014-06-10 03:15:23 +02:00
jomo 36e8b49090 changing blockstate 2014-06-10 03:10:10 +02:00
jomo a32ced6fd5 set block if event was not cancelled 2014-06-10 02:39:50 +02:00
jomo 8b6d163df1 move /pyeval back to main.py, so modules can be accessed 2014-06-10 01:36:18 +02:00
jomo 98620428ec HUGE code cleanup 2014-06-10 01:31:03 +02:00
jomo e466d5426c fix endless loop? 2014-06-10 00:32:48 +02:00
jomo aad5cbe07d fix endless loop 2014-06-10 00:30:54 +02:00
jomo 0f07ad4b27 test 2014-06-10 00:22:54 +02:00
jomo e639f302f0 firing event in defined directions 2014-06-10 00:20:02 +02:00
jomo b55c485c7d add missing import option 2014-06-09 23:54:48 +02:00
jomo 9927935074 better loading / importing of modules 2014-06-09 23:52:11 +02:00
jomo dddbcd7684 remove executable bit 2014-06-07 20:15:46 +02:00
jomo 099de5abe1 remove executable bit 2014-06-07 20:13:10 +02:00
jomo 4381db73fb started tilehelper plugin 2014-06-07 01:27:06 +02:00
jomo a9a540a73e fix path 2014-05-17 01:17:05 +02:00
jomo 97e5e2641c change mode 775 2014-05-17 01:09:35 +02:00
jomo 26d5c584eb add default files to prevent errors on first start 2014-05-17 00:46:22 +02:00
jomo ecedd98ccc remove ingame dependent files 2014-05-17 00:45:00 +02:00
jomo 53c1f8e2cb yea, i actually forgot this plugin itself... >_< 2014-05-17 00:35:32 +02:00
jomo d636f4e974 add README 2014-05-17 00:22:35 +02:00
jomo 57882c8dec rename mysql-connector 2014-05-17 00:14:40 +02:00
jomo 9f1ed1fb66 first commit via git 2014-05-16 23:04:40 +02:00
55 changed files with 6607 additions and 1626 deletions
+4
View File
@@ -1,6 +1,10 @@
*.pyc *.pyc
*.class *.class
*sublime* *sublime*
*.bat*
secrets.py
excluded.txt
.idea
# these are player/ingame specific # these are player/ingame specific
files/ files/
+1
View File
@@ -0,0 +1 @@
If you want to contribute, please [read through the pages on the wiki](https://github.com/RedstonerServer/redstoner-utils/wiki).
+21
View File
@@ -0,0 +1,21 @@
# The MIT License (MIT)
Copyright (c) Redstoner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE
+3 -240
View File
@@ -2,245 +2,8 @@
Redstoner's custom plugins, written in python. Redstoner's custom plugins, written in python.
------
# Installation / Set-up ## Contributing
1-line-install-script for bash: If you want to contribute, please [read through the pages on the wiki](https://github.com/RedstonerServer/redstoner-utils/wiki).
`wget -O install.sh "http://pastie.org/pastes/9310905/download?key = 6byp4mrqmiui8yqeo3s6yw"; md5sum --check <<<"3499671c0832e561bc9c7d476d2167cb install.sh" && sh install.sh`
Detailed description:
0. Create a new directory called 'redstoner'
0. Download [the latest spigot](http://ci.md-5.net/job/Spigot/lastStableBuild/artifact/Spigot-Server/target/spigot.jar)
0. Run it once inside redstoner, then shut it down again
0. Create a new directory (inside redstoner) called 'lib'
0. Download [mysql-connector](https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.30.zip), extract 'mysql-connector-java-X.X.XX-bin.jar
' and save it as 'mysql-connector.jar' inside lib
0. Download [PyPluginLoader](http://bamboo.gserv.me/browse/PLUG-PYPL/latestSuccessful/artifact/JOB1/Version-agnostic-jar/PyPluginLoader.jar) (we're using [this fork](https://github.com/gdude2002/Python-Plugin-Loader)) into the plugins directory
0. inside plugins, clone this directory into 'redstoner-utils**.py.dir**':
`git clone git@bitbucket.org:redstonesheep/redstoner-utils.git redstoner-utils.py.dir`
0. Download [PEX](http://dev.bukkit.org/media/files/789/291/PermissionsEx.jar) into plugins
0. **if you want** to develop mysql things, set up a local MySQL server
# branches
* **dev**
Always use this branch to change code, please test before pushing. (If something goes wrong here, that's okay)
* **master**
Never commit into this branch directly! Only merge stable versions of *dev*:
```bash
git checkout master
git merge dev
```
# Deploying on the server
**Never** edit the files directly on the server!
The dev server uses the *dev* branch, the live server uses *master*.
**Do not use `git pull` on the server!** *(All files must be pulled/owned by the 'redstoner' user.)*
### Deploying on test server
* Push all changes
* Run `<server-dir>/git_pull_utils.sh`.
* Restart (You can try reloading here, but expect the unexpected)
### Deploying on production server
* Test all code carefully on the test server
***on your machine:***
* `git checkout master`
* `git pull`
* `git merge dev`
* `git push -u origin master`
* `git checkout dev`
***on the server:***
* `rs update_utils`
* Restart
# Modules / Files
If you add a new file, please update this list!
If you want the server to load a file (*module*) on startup, add it to the `modules` list in `main.py`.
* `files/`
> All config / storage files go here
* `plugin.yml`
> The plugin.yml file required for bukkut plugins
* `main.py`
> The only file loaded by PyPluginLoader, loads all other modules
> Contains a few methods that **need to be cleaned up**
* `helpers.py`
> Library that adds a bunch of re-usable methods which are used in nearly all other modules
* `adminchat.py`
> Adds chat for staff using `/ac <text` or `,<text>`
* `chatgroups.py`
> Adds group-chat with `/chatgroup` and `/cgt` to toggle normal chat into group mode
* `lagchunks.py`
> Plugin to locate laggy chunks. `/lc <n>` lists chunks with more than `n` entities
* `mysqlhack.py`
> A library that makes use of the so called ClassPathHack for jython to allow proper loading of `mysql-connector.jar` at runtime. import only, no methods.
* `plotter.py`
> Start of a custom plot-plugin like PlotMe, on hold because the PlotMe developer continued to develop PlotMe
* `reports.py`
> The `/report <text>` and `/rp` plugin
* `saylol.py`
> Remake of sheep's old SayLol plugin, originally written as a standalone plugin in Java
* `skullclick.py`
> Shows the owner of a skull when right-clicked
* `webtoken.py`
> Adds `/token`, reads and writes from the database to generate *pronouncable* (and thus memorable) registration-tokens for the website
* `spawnplayer.py`
> Code that was used once to create [this](http://www.reddit.com/r/Minecraft/comments/28le52/screenshot_of_all_players_that_joined_my_server/) awesome [screenshot](http://i.imgur.com/v4wg5kl.png)
* `tilehelper.py`
> A plugin that automatically tiles (stacks) blocks inside a selected region in configurable directions.
* `mentio.py`
> Adds `/listen`, highlights chat and plays a sound when your name was mentioned
* `cycler.py`
> Adds `/cycler`, swaps the hotbar with inventory when player changes slot from right->left or left->right
* `motd.py`
> Adds `/getmotd` & `/setmotd` to update the motd on the fly (no reboot).
* `abot.py`
> AnswerBot. Hides stupid questions from chat and tells the sender about `/faq` or the like
* `damnspam.py`
> Adds `/damnspam`, creates timeout for buttons/levers to mitigate button spam.
* `forcefield.py`
> Adds '/forcefield', creates forcefield for players who want it.
# Code styleguide & tips
## Indentation
Never use tabs!
Use 2 spaces to indent.
## Quotes
Always use double-quotes!
Only use single-quotes when the string contains double-quotes that would need to be escaped.
## Capitalization
Do not use camelCase for variable or function names! Use under_score naming.
camelCase is okay when used like `import foo.bar.camelCase as camelCase`.
## Aligning variable assignments
In case you have multiple variable assignments, align the equals sign:
```Python
# bad
foo = 1
foobar = 2
a = 3
# good
foo = 1
foobar = 2
a = 3
```
Pro Tip: Use the AlignTab plugin for Sublime Text!
## Horizontal spacing
Use at least one space left and one space right to equals signs, and one space right to colons.
## Vertical spacing
Leave two empty lines before function definitions. In case you need to use `@hook.something`, add the two lines before that, directly followed by the definition.
## Meaningful names
Give function and variable names meaningful names. If you want to shorten long names, that's fine, but leave a comment on assigment with the actual meaning.
## Readability
Don't create long lines with lots of function calls. Split into multiple lines instead.
Also avoid methods with lots of lines. Split into multiple methods instead.
```Python
# bad
foo = int(player_data[str(server.getPlayer(args[4]).getUniqueId())]["details"].["last_login"].strftime("%s"))
# good
player = server.getPlayer(args[4])
player_id = uid(player)
logintime = player_data[played_id]["last_login"]
epoch_time = int(logintime.strftime("%s"))
```
## Comments
Comments are good!
Please comment everything that's non-obious or makes it easier to understand
## Debugging
Debugging can be a bit special with jython/PyPluginLoader.
When something goes wrong, you probably see a weird traceback that's not telling you shit.
...unless you take a closer look.
You will not see a direct traceback of the python methods.
Instead, you'll probably see a bunch of java, bukkit and python things, because it tries to translate python into java, line per line.
Take a closer look at the method names, they might tell you what it's trying to do and where it's coming from.
Watch out for something like `org.python.pycode._pyx5.horribleCode$23(/path/to/badcode.py:214) ~[?:?]`
0. In this case, `_pyx5` is our module.
0. `horribleCode` is the method that was called
0. `/path/to/badcode.py` is the actual file of our module
0. `:214` is the line in which the error occured.
Please note that the line may not be accurate. You'll often get the start of a loop, or the end of a method - when the actual error was somewhere in there.
In many cases, this is enough to find your bug. If you still cannot find it,try to catch exceptions in your code, as follows:
## Catching exceptions
If you want to catch all exceptions (e.g. for debugging), do not `catch Exception`.
Since we're using jython, this will not catch Java exceptions.
This will give you some more deatails:
```python
from traceback import format_exc as trace
try:
#code
except: # everything
print(trace())
```
+13 -4
View File
@@ -27,7 +27,7 @@ def list_answers(sender):
@hook.command("abot") @hook.command("abot")
def on_abot_command(sender, args): def on_abot_command(sender, command, label, args):
plugin_header(sender, "AnswerBot") plugin_header(sender, "AnswerBot")
if sender.hasPermission("utils.abot.admin"): if sender.hasPermission("utils.abot.admin"):
if not args: if not args:
@@ -45,10 +45,8 @@ def on_abot_command(sender, args):
return True return True
@hook.event("player.AsyncPlayerChatEvent", "low") def check_msg(event, message):
def on_chat(event):
sender = event.getPlayer() sender = event.getPlayer()
message = event.getMessage().lower()
for answer in answers: for answer in answers:
for regex in answer["regex"]: for regex in answer["regex"]:
if regex.search(message): if regex.search(message):
@@ -60,4 +58,15 @@ def on_chat(event):
break break
@hook.event("player.AsyncPlayerChatEvent", "low")
def on_chat(event):
check_msg(event, event.getMessage().lower())
@hook.event("player.PlayerCommandPreprocessEvent", "low")
def on_any_cmd(event):
words = event.getMessage().lower().split(" ")
cmd = words[0][1:]
if cmd in ["msg", "m", "t", "pm", "mail", "r", "reply"]:
check_msg(event, " ".join(words[1:]))
load_answers() load_answers()
+36 -5
View File
@@ -1,8 +1,12 @@
#pylint: disable = F0401 #pylint: disable = F0401
from helpers import * from helpers import *
from basecommands import simplecommand
ac_permission = "utils.ac" ac_permission = "utils.ac"
ac_key = ","
ac_defaultkey = ","
ac_keys = open_json_file("adminchat_keys", {})
ac_toggle_list = [] ac_toggle_list = []
ac_prefix = "&8[&cAC&8]" ac_prefix = "&8[&cAC&8]"
@@ -13,6 +17,7 @@ def adminchat(sender, msg):
except AttributeError: except AttributeError:
name = sender.getName() name = sender.getName()
broadcast(ac_permission, "%s &9%s&8: &b%s" % (ac_prefix, name, msg)) broadcast(ac_permission, "%s &9%s&8: &b%s" % (ac_prefix, name, msg))
# Needs something here like fine(message) to show up in the logs when you use ackey, but fine doesnt work for some reason. It did on the server with /pyeval (not show up on console, but show up in logs nevertheless)
# ac toggle # ac toggle
@@ -41,15 +46,41 @@ def on_ac_command(sender, args):
noperm(sender) noperm(sender)
return True return True
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",
usage = "<key>")
def adminchatkey_command(sender, command, label, args):
key = " ".join(args)
uuid = uid(sender)
if key.lower() == "default" or key == ac_defaultkey:
del ac_keys[uuid]
save_keys()
return "&aYour adminchat key was set to the default character: '&c%s&a'" % ac_defaultkey
ac_keys[uid(sender)] = key
save_keys()
return "&aYour adminchat key was set to: '&c%s&a'" % key
def save_keys():
save_json_file("adminchat_keys", ac_keys)
@hook.event("player.AsyncPlayerChatEvent", "low") @hook.event("player.AsyncPlayerChatEvent", "low")
def on_chat(event): def on_chat(event):
sender = event.getPlayer() sender = event.getPlayer()
msg = event.getMessage() msg = event.getMessage()
if sender.hasPermission(ac_permission) and not event.isCancelled(): if sender.hasPermission(ac_permission) and not event.isCancelled():
if msg[:len(ac_key)] == ac_key: key = get_key(uid(sender))
adminchat(sender, msg[1:]) if sender.getName() in ac_toggle_list:
event.setCancelled(True)
elif sender.getName() in ac_toggle_list:
adminchat(sender, msg) adminchat(sender, msg)
event.setCancelled(True) event.setCancelled(True)
elif msg[:len(key)] == key:
adminchat(sender, msg[len(key):])
event.setCancelled(True)
+134
View File
@@ -0,0 +1,134 @@
from helpers import *
from traceback import format_exc as print_traceback
import time
an_permission = "utils.an";
notes = open_json_file("adminnotes", [])
continued_messages = {}
def save_notes():
save_json_file("adminnotes", notes)
def r_ago(unit, i):
# Return ago + plural
if i != 1:
unit += "s"
return "%s %s ago" % (i, unit)
def calc_diff(time_ago):
current = time.time()
s = current-time_ago
s = int(s)
ago = "Some time ago"
if s < 10:
ago = "Just now"
elif s >= 10 and s < 60:
ago = r_ago("second", s)
elif s >= 60 and s < 3600:
ago = r_ago("minute", s/60)
elif s >= 3600 and s < 43200:
ago = r_ago("hour", s/60/60)
elif s >= 43200:
ago = r_ago("day", s/60/60/12)
return ago
def show_all_notes(sender):
if len(notes) == 0:
msg(sender, "&aNo open notes at the moment!")
return
for i in range(0, len(notes)):
arr = notes[i]
name = arr[0]
message = arr[1]
note_time = arr[2]
ago = calc_diff(note_time)
msg(sender, "&6#%s - &e%s&6, %s:" % (str(i+1), name, ago))
msg(sender, "&7%s" % colorify(message))
def show_an_help(sender):
msg(sender, "&6AdminNotes Help:")
msg(sender, "&e- /an")
msg(sender, "&7&oLists all notes")
msg(sender, "&e- /an del <ID>")
msg(sender, "&7&oRemove a note")
msg(sender, "&e- /an help")
msg(sender, "&7&oShows this menu")
msg(sender, "&e- /an Some text...")
msg(sender, "&7&oWrite a new note")
msg(sender, "&e- /an This text is very++")
msg(sender, "&7&oContinue writing your note when using &e/an long guys!&7&o again")
@hook.command("an", aliases=["adminnotes", "adminnote"])
def adminnotes_command(sender, command, label, args):
if not sender.hasPermission(an_permission):
noperm(sender)
return
try:
arglen = len(args)
# arg length not valid
if arglen == 0:
show_all_notes(sender)
return
# Shows note help
subcmd = args[0].lower()
if subcmd == "help":
show_an_help(sender)
return
# Delete note
if subcmd == "del":
if arglen != 2:
show_an_help(sender)
return
if not args[1].isdigit():
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):
msg(sender, "&cThere is no note with that ID!")
return
# Deletes note by index
del notes[note_id]
save_notes()
msg(sender, "&aSuccessfully deleted note #%s!" % str(note_id+1))
return
message = " ".join(args)
name = sender.getName()
if name in continued_messages:
message = continued_messages[name] + " " + message
del continued_messages[name]
if message[-2:] == "++":
message = message[:-2]
continued_messages[name] = message
msg(sender, "&6You can continue writing by using &e/an <text ...>")
else:
notes.append([name, message, time.time()])
save_notes()
msg(sender, "&eNew note:&6 " + message)
broadcast(an_permission, "&a%s just added a new note! &2Type /an" % name)
except:
error(print_traceback())
@hook.event("player.PlayerJoinEvent", "monitor")
def on_an_join(event):
player = event.getPlayer()
if not player.hasPermission(an_permission):
return
if len(notes) > 0:
msg(player, "&cThere are currently %s open notes!" % len(notes))
elif len(notes) == 0:
msg(player, "&aThere are currently no open notes!")
+137
View File
@@ -0,0 +1,137 @@
from helpers import *
badges = open_json_file("badges", {})
badges_available = {
"helpful" : "A very helpful player",
"expert_minecraft" : "An expert in Minecraft",
"expert_coder" : "A good coder",
"oldtimer" : "A long time player",
"good_builder" : "A very good builder",
"friendly" : "Many think that this player is friendly",
"very_active" : "A very active player",
"trustworthy" : "This player is very trustworthy",
}
badges_perm_add = "utils.badges.add"
badges_perm_del = "utils.badges.delete"
def save_badges():
save_json_file("badges", badges)
def get_badges(player):
sender_id = uid(player)
return badges.get(sender_id, [])
def show_badges(sender, player):
player_badges = get_badges(player)
if player_badges:
msg(sender, "&6Badges of " + player.getName())
for key in player_badges:
msg(sender, "&b> &3&o%s" % badges_available[key])
else:
msg(sender, "&eThis player has no badges yet")
def new_badge_event(player, badge):
msg(player, "")
msg(player, "&6Wow! You just received a badge!")
msg(player, "&b-> &3%s" % badges_available[badge])
msg(player, "&7Type /badge to see all your badges!")
msg(player, "")
player.playSound(player.getLocation(), "random.orb", 1, 1)
def del_badge_event(player, badge):
msg(player, "&cWe took your badge \"%s\"." % badges_available[badge])
def list_badges(sender):
if badges_available:
for key in badges_available.keys():
msg(sender, "&b> &3%s &7&o\"%s\"" % (key, badges_available[key]))
else:
msg(sender, "&cThere are currently no badges available")
def add_badge(sender, target, badge):
if badge in badges_available:
player_badges = get_badges(target)
if badge in player_badges:
msg(sender, "&cThis player got this badge already!")
return
player_badges.append(badge)
if player_badges:
badges[uid(target)] = player_badges
msg(sender, "&aYou just gave %s a new badge!" % target.getName())
new_badge_event(target, badge)
save_badges()
else:
msg(sender, "&cThere is no badge called %s. Check /badge list!" % badge)
def del_badge(sender, target, badge):
if badge in badges_available.keys():
player_badges = get_badges(target)
if badge in player_badges:
player_badges.remove(badge)
badges[uid(target)] = player_badges
msg(sender, "&aYou just took %s from %s!" % (badge, target.getName()))
save_badges()
del_badge_event(target, badge)
return
msg(sender, "&c%s doesn't have this badge!" % target.getName())
else:
msg(sender, "&cThere is no badge called %s. Check /badge list!" % badge)
@hook.command("badge", aliases=["badges", "rewards"])
def on_badge_command(sender, command, label, args):
argnum = int(len(args))
# No arguments
if argnum is 0:
show_badges(sender, sender)
# Length of arguments is 1
if argnum == 1:
# If only argument is "list"
if args[0].lower() == "list":
list_badges(sender)
return True
# If only argument is a player name
target = server.getPlayer(args[0])
if is_player(target):
show_badges(sender, target)
return True
else:
msg(sender, "&cThere is no player called %s online." % args[0])
return True
msg(sender, "&cUnknown syntax: /badge <playername> &o&c /badge list")
return True
# Length of arguments is 3
if argnum == 3:
cmd = args[0].lower()
target = server.getPlayer(args[1])
new_badge = args[2].lower()
if cmd == "add":
if not sender.hasPermission(badges_perm_add):
noperm(sender)
return True
add_badge(sender, target, new_badge)
return True
if cmd == "take" or cmd == "del":
if not sender.hasPermission(badges_perm_del):
noperm(sender)
return True
del_badge(sender, target, new_badge)
return True
msg(sender, "&cUnknown syntax: /badge <add|take> <playername> <badge>")
return True
+164
View File
@@ -0,0 +1,164 @@
from helpers import *
"""
@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 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 "))
help_msg += "\n \n&aSyntax: /%s %s" % (cmd, usage)
if aliases:
help_msg += ("\n&6Aliases: " + "".join([(alias + ", ") for alias in aliases]))[:-2]
if sender.hasPermission(to_see_permission):
help_msg += "\n&6Required permission: " + permission
return help_msg
def simplecommand(cmd,
aliases = [],
usage = "[args...]",
description = None,
senderLimit = -1,
amin = 0,
amax = -1,
helpNoargs = False,
helpSubcmd = False):
cmd = cmd.lower()
permission = "utils." + cmd
if not description:
description = "Handles " + cmd
if not usage:
usage = "/%s <subcmd>" % cmd
def getHelp(sender):
return helpMsg(sender, cmd, description, usage, aliases, permission)
def decorator(function):
@hook.command(cmd, aliases = aliases)
def call(sender, command, label, args):
message = run(sender, command, label, args)
if message:
if message == "HELP":
message = getHelp(sender)
msg(sender, message)
return True
def run(sender, command, label, args):
isPlayer = is_player(sender)
if not isSenderValid(senderLimit, isPlayer):
return invalidSenderMsg(isPlayer)
if not sender.hasPermission(permission):
return "&cYou do not have permission to use that command"
if ((not args) and helpNoargs) or (helpSubcmd and args and args[0].lower() == "help"):
return getHelp(sender)
if not checkargs(sender, args, amin, amax):
return None
try:
return function(sender, command, label, args)
except CommandException, e:
return e.message
except Exception, e:
error(trace())
return "&cAn internal error occurred while attempting to perform this command"
return call
return decorator
class CommandException(Exception):
pass
class Validate():
@staticmethod
def notNone(obj, msg):
if obj == None:
raise CommandException(msg)
@staticmethod
def isPlayer(sender):
if not is_player(sender):
raise CommandException("&cThat command can only be run by players")
@staticmethod
def isConsole(sender):
if is_player(sender):
raise CommandException("&cThat command can only be run from the console")
@staticmethod
def isAuthorized(sender, permission, msg = "that command"):
if not sender.hasPermission(permission):
raise CommandException("&cYou do not have permission to use " + msg)
@staticmethod
def isTrue(obj, msg):
if obj != True:
raise CommandException(msg)
@staticmethod
def checkArgs(sender, args, amin, amax):
if not checkargs(sender, args, amin, amax):
raise CommandException("")
+297
View File
@@ -0,0 +1,297 @@
from helpers import *
from basecommands import simplecommand, Validate, CommandException
from time import sleep
from collections import deque
import thread
import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
import org.bukkit.block.Furnace as Furnace
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
"""
# 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,
"easy cauldron water level control",
"Toggles whether cauldrons auto-fill upon placement and whether right clicking them with redstone dust or empty hand will cycle their water level",
["caul", "water"]
],
slab = [0,
"automatically flipping placed slabs upside-down",
"Toggles whether slabs/steps which you place should be automatically flipped upside-down",
["step"]
],
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 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"]
#],
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.",
["invert", "rp"]
],
dropper = [1,
"automatically filling droppers upon placement",
"Sets your preferred default dropper contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle dropper clear to clear all slots.",
["itemshooter", "filld"], 8
],
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 hopper clear to clear all slots.",
["itemtransporter", "fillh"], 4
]
)
defaults = {
0: list,
1: dict,
2: list
}
faces = {
BlockFace.DOWN : 0,
BlockFace.UP : 1,
BlockFace.NORTH : 2,
BlockFace.SOUTH : 3,
BlockFace.WEST : 4,
BlockFace.EAST : 5
}
playerSettings = open_json_file("blockplacemods", {})
for setting, details in settingInformation.iteritems():
if playerSettings.get(setting) == None:
playerSettings[setting] = defaults[details[0]]()
def get(setting):
return playerSettings[setting]
def saveSettings():
save_json_file("blockplacemods", playerSettings)
def getSettingDetails(arg):
try:
arg = arg.lower()
for setting, details in settingInformation.iteritems():
if setting == arg or arg in details[3]:
return (setting, details)
except:
error(trace())
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]",
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,
helpSubcmd = True,
amax = 2)
def toggle_command(sender, command, label, args):
setting, details = getSettingDetails(args[0])
Validate.isAuthorized(sender, "utils.toggle." + setting, "that setting")
values = get(setting)
player = server.getPlayer(sender.getName())
uuid = uid(player)
arglen = len(args)
if details[0] in (0,2): # Toggle
default = details[0] == 0 # If True: toggle on if list doesn't contain the uuid
enabled = (uuid not in values) == default #Invert if details[0] == 2 (toggle disabled by default)
new = None
if arglen == 1:
new = not enabled
else:
arg2 = args[1].lower()
if arg2 == "info":
return " &aSetting %s:\n &9%s\n &6Accepted arguments: [on|enable|off|disable|toggle|switch|info]\n &6Aliases: %s" % (setting, details[2], ", ".join(details[3]))
elif arg2 in ("toggle", "switch"):
new = not enabled
elif arg2 in ("on", "enable"):
new = not default
elif arg2 in ("off", "disable"):
new = default
else:
return " &cArgument '%s' was not recognized. \n Use &o/toggle %s info &cfor more information" % (arg2, setting)
if enabled == new:
return " &cAlready %s: &a%s" % ("enabled" if enabled else "disabled", details[1])
if new == default:
values.remove(uuid)
else:
values.append(uuid)
saveSettings()
return (" &aEnabled " if new else " &aDisabled ") + details[1]
elif details[0] == 1: # Save ItemStack in hand
arg2 = args[1].lower() if arglen > 1 else ""
enabled = uuid in values
if arg2 == "clear":
if enabled:
del values[uuid]
return " &aDisabled " + details[1]
return " &cAlready disabled: " + details[1]
if arg2 == "details":
return " &aSetting %s:\n &9%s \n&6Accepted arguments: [<slot>|clear|details]" % (setting, details[2])
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:
items = values[uuid]
if slot in items:
del items[slot]
saveSettings()
if len(items) == 0:
del items
return " &aDisabled " + details[1]
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)
if not enabled:
values[uuid] = {}
values[uuid][slot] = item
saveSettings()
return ((" &aEnabled setting %s, S" % setting) if len(values[uuid]) == 1 else " &aS") + "et itemstack in slot %s to item in hand" % (slot)
return None #This shouldn't happen
def fromStack(itemStack):
return [itemStack.getTypeId(), itemStack.getAmount(), itemStack.getData().getData()]
def toStack(lst):
return ItemStack(lst[0], lst[1], lst[2])
def isEnabled(toggleSetting, uuid):
return (uuid not in get(toggleSetting)) == (settingInformation[toggleSetting][0] == 0) #Invert if off by default
@hook.event("block.BlockPlaceEvent", "monitor")
def on_block_place(event):
if event.isCancelled():
return
player = event.getPlayer()
if not is_creative(player):
return
uuid = uid(player)
block = event.getBlockPlaced()
material = block.getType()
if (material in (Material.WOOD_STEP, Material.STEP)
and isEnabled("slab", uuid)
and player.hasPermission("utils.toggle.slab")
and block.getData() < 8
):
block.setData(block.getData() + 8) # Flip upside down
elif (material == Material.CAULDRON
and isEnabled("cauldron", uuid)
and player.hasPermission("utils.toggle.cauldron")
):
block.setData(3) #3 layers of water, 3 signal strength
elif ((material == Material.FURNACE and player.hasPermission("utils.toggle.furnace"))
or (material == Material.DROPPER and player.hasPermission("utils.toggle.dropper"))
or (material == Material.HOPPER and player.hasPermission("utils.toggle.hopper"))
):
stacks = get(str(material).lower()).get(uuid)
if stacks != None: # Enabled
state = block.getState()
inv = state.getInventory()
for slot, stack in stacks.iteritems():
inv.setItem(int(slot), toStack(stack))
state.update()
"""
elif (material == Material.REDSTONE_TORCH_ON
and event.getBlockAgainst().getType() == Material.REDSTONE_BLOCK
and isEnabled("torch", uuid)
and player.hasPermission("utils.toggle.torch")
):
torches_to_break.append(block)
"""
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())])
@hook.event("player.PlayerInteractEvent", "monitor")
def on_interact(event):
player = event.getPlayer()
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)
and event.getClickedBlock().getType() == Material.CAULDRON
):
block = event.getClickedBlock()
event2 = BlockBreakEvent(block, player)
server.getPluginManager().callEvent(event2)
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")
class torch_breaker(Runnable):
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:
torches_to_break.append(block)
except:
error(trace())
"""
+110
View File
@@ -0,0 +1,110 @@
from helpers import *
import threading
import time
calc_users = open_json_file("calc", [])
math_operators = ["+", "-", "*", "/", "%", ">", "<", "^", "&", "|"]
allowed_strings = ["0b", "0x", "(", ")", "hex(", "bin(", "abs(", "int(", "min(", "max(", "round(", "float("]
allowed_alpha = ["a", "b", "c", "d", "e", "f"]
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
"""
expression = ""
should_calc = False
i = 0
while True:
if i >= len(text):
break
char = text[i]
if i < len(text) - 5 and str(char + text[i+1] + text[i+2] + text[i+3] + text[i+4] + text[i+5]) in allowed_strings:
expression += char
expression += text[i + 1]
expression += text[i + 2]
expression += text[i + 3]
expression += text[i + 4]
expression += text[i + 5]
i += 5
should_calc = True
elif i < len(text) - 3 and str(char + text[i+1] + text[i+2] + text[i+3]) in allowed_strings:
expression += char
expression += text[i + 1]
expression += text[i + 2]
expression += text[i + 3]
i += 3
should_calc = True
elif i < len(text) - 1 and str(char + text[i + 1]) in allowed_strings:
expression += char
expression += text[i + 1]
i += 1
should_calc = True
elif char.isdigit() or char in allowed_alpha or (expression and char == ".") or (should_calc and char == " ") or (should_calc and char == ","):
expression += char
should_calc = True
elif char in math_operators or char in ["(", ")"]:
# calculation must include at least 1 operator
should_calc = True
expression += char
elif should_calc and char.isalpha():
# don't include any more text in the calculation
break
i += 1
last_char = ' '
for char in expression:
if last_char == '*' and char == '*':
if sender.hasPermission(calc_perm_power):
break
else:
return None
last_char = char
if should_calc:
try:
result = str(eval(expression)) # pylint: disable = W0123
except: # pylint: disable = W0702
# we can run into all kinds of errors here
# most probably SyntaxError
return None
return (expression, result)
return None
def thread_calc(message, sender):
output = calc(sender, message)
if output and sender.isOnline():
msg(sender, "&2=== Calc: &e" + output[0] + " &2= &c" + output[1])
@hook.event("player.AsyncPlayerChatEvent", "monitor")
def on_calc_chat(event):
sender = event.getPlayer()
message = event.getMessage()
if not event.isCancelled() and uid(sender) in calc_users and sender.hasPermission(calc_perm):
thread = threading.Thread(target=thread_calc, args=(message, sender))
thread.daemon = True
thread.start()
@hook.command("calc", description="Toggles chat calculations")
def on_calc_command(sender, command, label, args):
plugin_header(sender, "Chat Calculator")
if not sender.hasPermission(calc_perm):
noperm(sender)
return True
if not checkargs(sender, args, 0, 1):
return True
if not is_player(sender):
msg(sender, "&cYou are not a player!")
return True
toggle(sender, calc_users, name = "Calc")
save_json_file("calc", calc_users)
return True
+352
View File
@@ -0,0 +1,352 @@
############################################
# Alias v2.0 by Pepich #
# Changes to previous version from curs3d: #
# Dynamic alias limit from permissions #
# AC/CG/MSG support #
# Color support #
# Bugfixes #
# #
# TODO: #
# Add command support... #
############################################
import os
import mysqlhack
import org.bukkit as bukkit
from org.bukkit import *
from helpers import *
from traceback import format_exc as trace
from secrets import *
# Version number and requirements
alias_version = "2.0.0"
helpers_versions = ["1.1.0", "2.0.0"]
enabled = False
error = colorify("&cUnspecified error")
commands_per_page = 5
global_aliases = {"./":"/"}
data = {}
# DON'T SET THIS TO TRUE! MySQL requestst are NOT ASYNC yet! (And for some reason it doesn't want to store any data ._.)
use_mysql = False
# 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."
permission_LENGTH = "utils.alias.length."
# See when the plugin was disabled due to version errors
permission_INFO = "utils.alias.info"
permission_FINFO = "utils.alias.finfo"
########
# CODE #
########
# OnEnable
enabled = helpers_version in helpers_versions
if not enabled:
error = colorify("&6Incompatible versions detected (&chelpers.py&6)")
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 = global_aliases
save_json_file("aliases/" + uuid, value)
return value
@hook.command("alias",
usage="/<command> <add, remove, list, help> [...]",
desc="Allows aliasing of words")
def on_alias_command(sender, cmd, label, args):
try:
args = array_to_list(args)
if not enabled:
disabled_fallback(sender)
return True
if not hasPerm(sender, permission_BASE):
plugin_header(recipient=sender, name="Alias")
noperm(sender)
return True
return subcommands[args[0].lower()](sender, args[1:])
except:
return subcommands["help"](sender, "1")
def help(sender, args):
commands = [colorify("&e/alias help [page]")]
if hasPerm(sender, permission_LIST):
commands += [colorify("&e/alias list &7- Lists all your aliases")]
if hasPerm(sender, permission_MODIFY):
commands += [colorify("&e/alias add <word> <alias> &7- Add an alias")]
commands += [colorify("&e/alias remove <word> &7- Remove an alias")]
if can_remote(sender):
while len(commands) < commands_per_page:
commands += [""]
commands += [colorify("&7Following commands will be executed on <player> yet all output will be redirected to you, except when you set silent to false, then <player> will see it too.")]
if hasPerm(sender, permission_LIST_OTHERS):
commands += [colorify("&e/alias player <name> list [silent]")]
if hasPerm(sender, permission_MODIFY_OTHERS):
commands += [colorify("&e/alias player <name> add <word> <alias> [silent]")]
commands += [colorify("&e/alias player <name> remove <word> [silent]")]
pages = (len(commands)-1)/commands_per_page + 1
page = 1
if len(args) != 0:
page = int(args[0])
if (page > pages):
page = pages
if page < 1:
page = 1
msg(sender, colorify("&e---- &6Help &e-- &6Page &c" + str(page) + "&6/&c" + str(pages) + " &e----"))
page -= 1
to_display = commands[5*page:5*page+5]
for message in to_display:
msg(sender, message)
if page+1 < pages:
msg(sender, colorify("&6To display the next page, type &c/alias help " + str(page+2)))
return True
@hook.event("player.PlayerJoinEvent", "high")
def on_join(event):
if enabled:
t = threading.Thread(target=load_data, args=(uid(event.getPlayer()), ))
t.daemon = True
t.start()
else:
if event.getPlayer().hasPermission(permission_FINFO):
disabled_fallback(event.getPlayer())
@hook.event("player.AsyncPlayerChatEvent", "high")
def on_player_chat(event):
try:
if enabled:
if event.isCancelled():
return
if not hasPerm(event.getPlayer(), permission_USE):
return
for alias, value in data[str(uid(event.getPlayer()))].items():
if not event.getPlayer().hasPermission(permission_ALL) and len(event.getMessage()) > int(get_permission_content(event.getPlayer(), permission_LENGTH)):
event.setCanceled(True)
plugin_header(event.getPlayer, "Alias")
msg(event.getPlayer(), "The message you wanted to generate would exceed your limit. Please make it shorter!")
return
if event.getPlayer().hasPermission("essentials.chat.color"):
event.setMessage(event.getMessage().replace(colorify(alias), colorify(value)))
else:
event.setMessage(event.getMessage().replace(alias, value))
except:
print(trace())
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(receiver, colorify("&cPlease contact a dev/admin (especially pep :P) about this to take a look at it."))
def can_remote(player):
return hasPerm(player, permission_LIST_OTHERS) or hasPerm(player, permission_MODIFY_OTHERS)
def add(sender, args):
plugin_header(sender, "Alias")
if not sender.hasPermission(permission_ALL) and len(data[uid(sender)]) >= int(get_permission_content(sender, permission_AMOUNT)):
msg(sender, "&cCould not create alias: Max_limit reached!")
return True
args = [args[0]] + [" ".join(args[1:])]
if not add_alias_data(uid(sender), str(args[0]), args[1]):
msg(sender, colorify("&c") + "Could not add an alias for this sequence because a priorly added alias contains it")
return True
msg(sender, colorify("&7Alias: ") + args[0] + colorify("&7 -> " + args[1] + colorify("&7 was succesfully created!")), usecolor=sender.hasPermission("essentials.chat.color"))
return True
def radd(sender, args):
plugin_header(sender, "Alias")
args = args[0:2] + [" ".join(args[2:len(args)-1])] + [args[len(args)-1]]
if is_player(sender):
sender_name = colorify(sender.getDisplayName())
else:
sender_name = colorify("&6Console")
target = get_player(args[0])
if args[3].lower() == "false":
plugin_header(target, "Alias")
msg(target, "&cPlayer " + sender_name + " &cis creating an alias for you!")
if not sender.hasPermission(permission_ALL) and len(data[uid(sender)]) >= int(get_permission_content(target, permission_AMOUNT)):
msg(sender, "&cCould not create alias: Max_limit reached!")
if args[3].lower() == "false":
msg(target, "&cCould not create alias: Max_limit reached!")
return True
if len(args) == 3:
args += ["true"]
if not add_alias_data(uid(target), str(args[1]), str(args[2])):
message = colorify("&c") + "Could not add an alias for this sequence because a priorly added alias contains it"
msg(sender, message)
if args[3].lower() == "false":
msg(target, message)
return True
msg(sender, colorify("&7Alias: ") + args[1] + colorify("&7 -> " + args[2] + colorify("&7 was succesfully created!")), usecolor=target.hasPermission("essentials.chat.color"))
if args[3].lower() == "false":
msg(target, colorify("&7Alias: ") + args[1] + colorify("&7 -> " + args[2] + colorify("&7 was succesfully created!")), usecolor=target.hasPermission("essentials.chat.color"))
return True
def add_alias_data(puuid, aliased, new_alias):
prior = data[puuid]
if aliased not in prior:
for alias in prior.values():
if aliased in alias:
return False
prior[aliased] = new_alias
save_data(puuid)
return True
def remove(sender, args):
plugin_header(sender, "Alias")
try:
msg(sender, colorify("&7Successfully removed alias ") + args[0] + colorify(" &7-> ") + data[uid(sender)].pop(args[0]) + colorify("&7!"), usecolor=sender.hasPermission("essentials.chat.color"))
save_data(uid(sender))
except:
msg(sender, colorify("&cCould not remove alias ") + args[0] + colorify(", it does not exist."), usecolor=sender.hasPermission("essentials.chat.color"))
return True
def rremove(sender, args):
plugin_header(sender, "Alias")
target = get_player(args[0])
if is_player(sender):
sender_name = colorify(sender.getDisplayName())
else:
sender_name = colorify("&6Console")
if args[2].lower() == "false":
plugin_header(target, "Alias")
msg(target, "&cPlayer " + sender_name + " &cis removing an alias for you!")
try:
alias = data[uid(target)].pop(args[1])
msg(sender, colorify("&7Successfully removed alias ") + args[1] + colorify(" &7-> ") + alias + colorify("&7!"), usecolor=sender.hasPermission("essentials.chat.color"))
if args[2].lower() == "false":
msg(target, colorify("&7Successfully removed alias ") + args[1] + colorify(" &7-> ") + alias + colorify("&7!"), usecolor=sender.hasPermission("essentials.chat.color"))
save_data(uid(target))
except:
msg(sender, colorify("&cCould not remove alias ") + args[1] + colorify(", it does not exist."), usecolor=sender.hasPermission("essentials.chat.color"))
if args[2].lower() == "false":
msg(target, colorify("&cCould not remove alias ") + args[1] + colorify(", it does not exist."), usecolor=sender.hasPermission("essentials.chat.color"))
return True
def list_alias(sender, args):
plugin_header(sender, "Alias")
msg(sender, "&7You have a total of " + str(len(data[uid(sender)])) + " aliases:")
for word, alias in data[str(uid(sender))].items():
msg(sender, colorify("&7") + word + colorify("&7 -> ") + alias, usecolor=sender.hasPermission("essentials.chat.color"))
return True
def rlist_alias(sender, args):
plugin_header(sender, "Alias")
target = get_player(args[0])
if is_player(sender):
sender_name = colorify(sender.getDisplayName)
else:
sender_name = colorify("&6Console")
if len(args) == 1:
args += ["true"]
msg(sender, "Player " + args[0] + " has following aliases (" + str(len(data[uid(target)])) + " in total):")
if args[1].lower() == "false":
plugin_header(target, "Alias")
msg(target, "&cPlayer " + sender_name + " &cis listing your aliases (" + str(len(data[uid(target)])) + " in total):")
for word, alias in data[str(uid(target))].items():
msg(sender, colorify("&7") + word + colorify("&7 -> ") + alias, usecolor=target.hasPermission("essentials.chat.color"))
if args[1].lower() == "false":
msg(target, colorify("&7") + word + colorify("&7 -> ") + alias, usecolor=target.hasPermission("essentials.chat.color"))
return True
def remote(sender, args):
try:
return remotes[args[1].lower()](sender, [args[0]] + args[2:])
except:
return subcommands["help"](sender, ["2"])
def load_data(uuid):
try:
load_data_thread(uuid)
# t = threading.Thread(target=load_data_thread, args=(uuid))
# t.daemon = True
# t.start()
except:
print(trace())
def load_data_thread(uuid):
if use_mysql:
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("SELECT alias FROM alias WHERE uuid = ?", (uuid, ))
results = curs.fetchall()
if len(results) == 0:
results = global_aliases
curs.execute("INSERT INTO alias VALUES (?,?)", (uuid, results, ))
data[uuid] = results
else:
data[uuid] = safe_open_json(uuid)
def save_data(uuid):
try:
save_data_thread(uuid)
# t = threading.Thread(target=save_data_thread, args=(uuid))
# t.daemon = True
# t.start()
except:
print(trace())
def save_data_thread(uuid):
if use_mysql:
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("UPDATE alias SET alias = ? WHERE uuid = ?", (data[uuid], uuid, ))
else:
save_json_file("aliases/" + uuid, data[uuid])
# Subcommands:
subcommands = {
"help": help,
"add": add,
"remove": remove,
"player": remote,
"list": list_alias
}
remotes = {
"add": radd,
"remove": rremove,
"list": rlist_alias,
}
+59 -14
View File
@@ -1,20 +1,28 @@
#pylint: disable = F0401 #pylint: disable = F0401
from helpers import * from helpers import *
from basecommands import simplecommand
from java.util.UUID import fromString as juuid from java.util.UUID import fromString as juuid
from traceback import format_exc as trace
groups = open_json_file("chatgroups", {}) groups = open_json_file("chatgroups", {})
cg_key = ":" cg_defaultkey = ":"
cg_keys = open_json_file("chatgroup_keys", {})
cg_toggle_list = [] cg_toggle_list = []
def get_key(uuid):
key = cg_keys.get(uuid)
return key if key != None else cg_defaultkey
@hook.command("chatgroup") @hook.command("chatgroup")
def on_chatgroup_command(sender, args): def on_chatgroup_command(sender, command, label, args):
plugin_header(sender, "ChatGroups") plugin_header(sender, "ChatGroups")
sender_id = uid(sender) sender_id = uid(sender)
if len(args) == 1 and args[0] == "leave": if len(args) == 1 and args[0] == "leave":
if sender_id in groups.keys(): if sender_id in groups.keys():
groupchat(sender, "left the group", True) groupchat(sender, "left the group", True)
if sender in cg_toggle_list:
cg_toggle_list.remove(p)
group = groups[sender_id] group = groups[sender_id]
del(groups[sender_id]) del(groups[sender_id])
save_groups() save_groups()
@@ -24,12 +32,7 @@ def on_chatgroup_command(sender, args):
if sender_id in groups.keys(): if sender_id in groups.keys():
group = groups[sender_id] group = groups[sender_id]
msg(sender, "&aCurrent chatgroup: %s" % group) msg(sender, "&aCurrent chatgroup: %s" % group)
users = [] users = [user.getDisplayName() for user in [server.getPlayer(juuid(uuid)) for uuid, ugroup in groups.iteritems() if ugroup == group] if user]
for uuid, ugroup in groups.iteritems():
if ugroup == group:
usr = server.getPlayer(juuid(uuid))
if usr:
users.append(usr.getDisplayName())
msg(sender, "&aUsers in this group:") msg(sender, "&aUsers in this group:")
msg(sender, "&a%s" % ", ".join(users)) msg(sender, "&a%s" % ", ".join(users))
else: else:
@@ -39,15 +42,25 @@ def on_chatgroup_command(sender, args):
groupchat(sender, "joined the group", True) groupchat(sender, "joined the group", True)
save_groups() save_groups()
msg(sender, "&aYour chatgroup is set to '%s'" % args[1]) msg(sender, "&aYour chatgroup is set to '%s'" % args[1])
msg(sender, "&aUse chat like '&e%s<message>' to send messages to this group." % cg_key) 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: else:
msg(sender, "&e/chatgroup join <name>") msg(sender, "&e/chatgroup join <name>")
msg(sender, "&e/chatgroup leave") msg(sender, "&e/chatgroup leave")
msg(sender, "&e/chatgroup info") msg(sender, "&e/chatgroup info")
msg(sender, "&e/chatgroup key")
msg(sender, "&e/chatgroup tpahere")
@hook.command("cgt") @hook.command("cgt")
def on_cgt_command(sender, args): def on_cgt_command(sender, command, label, args):
p = uid(sender) p = uid(sender)
if p in cg_toggle_list: if p in cg_toggle_list:
cg_toggle_list.remove(p) cg_toggle_list.remove(p)
@@ -68,11 +81,19 @@ def groupchat(sender, message, ann = False):
mesg = "&8[&bCG&8] &e&o%s&e&o %s" % (name, message) mesg = "&8[&bCG&8] &e&o%s&e&o %s" % (name, message)
else: else:
mesg = "&8[&bCG&8] &f%s&f: &6%s" % (name, message) mesg = "&8[&bCG&8] &f%s&f: &6%s" % (name, message)
mesg = colorify(mesg)
info("[ChatGroups] %s (%s): %s" % (sender.getDisplayName(), group, message)) 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(): 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(): def save_groups():
save_json_file("chatgroups", groups) save_json_file("chatgroups", groups)
@@ -84,9 +105,33 @@ def on_chat(event):
msge = event.getMessage() msge = event.getMessage()
if not event.isCancelled(): if not event.isCancelled():
sender_id = uid(sender) sender_id = uid(sender)
if msge[:len(cg_key)] == cg_key and sender_id in groups.keys(): key = get_key(sender_id)
groupchat(sender, msge[1:]) keylen = len(key)
if msge[:keylen] == key and sender_id in groups.keys():
groupchat(sender, msge[keylen:])
event.setCancelled(True) event.setCancelled(True)
elif sender_id in cg_toggle_list: elif sender_id in cg_toggle_list:
groupchat(sender, msge) groupchat(sender, msge)
event.setCancelled(True) event.setCancelled(True)
@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)
uuid = uid(sender)
if key.lower() == "default" or key == cg_defaultkey:
del cg_keys[uuid]
save_keys()
return "&aYour chatgroup key was set to the default character: '&c%s&a'" % cg_defaultkey
cg_keys[uid(sender)] = key
save_keys()
return "&aYour chatgroup key was set to: '&c%s&a'" % key
def save_keys():
save_json_file("chatgroup_keys", cg_keys)
+95
View File
@@ -0,0 +1,95 @@
import json
import urllib2
import datetime
import mysqlhack #pylint: disable = unused-import
from traceback import format_exc as print_traceback
from com.ziclix.python.sql import zxJDBC
from secrets import *
from helpers import *
# receive info based on the user's IP. information provided by ipinfo.io
def ip_info(player):
if player.isOnline():
return json.load(urllib2.urlopen("http://ipinfo.io%s/json" % str(player.getAddress().getAddress())))
else:
return {}
# receive first join date based on the player data (may not be accurate)
def get_first_join(player):
first_join = int(player.getFirstPlayed())
dt = datetime.datetime.fromtimestamp(first_join/1000.0)
return dt.strftime("%Y-%m-%d %H:%M")
# receive last seen date based on the player data
def get_last_seen(player):
last_seen = int(player.getLastPlayed())
dt = datetime.datetime.fromtimestamp(last_seen/1000.0)
return dt.strftime("%Y-%m-%d %H:%M")
# receive link and email from website
def get_website_data(player):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
uuid = str(uid(player)).replace("-", "")
curs.execute("SELECT DISTINCT `id`, `email` FROM users WHERE `uuid` = ? LIMIT 1", (uuid,))
results = curs.fetchall()
curs.close()
conn.close()
return ("http://redstoner.com/users/%s" % results[0][0], results[0][1]) if results else (None, None)
# receive country based on the user's IP
def get_country(data):
return str(data.get("country"))
def get_all_names(player):
uuid = str(uid(player)).replace("-", "")
names = json.load(urllib2.urlopen("https://api.mojang.com/user/profiles/%s/names" % uuid))
# [ {"name": "some_name"}, {"name": "other_name"} ]
return ", ".join([name["name"] for name in names])
# combines data
def get_all_data(sender, player):
data = ip_info(player)
msg(sender, "")
try:
msg(sender, "&7 -- Data provided by Redstoner")
msg(sender, "&6> UUID: &e%s" % str(uid(player)))
msg(sender, "&6> First joined: &7(y-m-d h:m:s) &e%s" % get_first_join(player))
msg(sender, "&6> Last seen: &7(y-m-d h:m:s) &e%s" % get_last_seen(player))
website = get_website_data(player)
msg(sender, "&6> Website account: &e%s" % website[0])
msg(sender, "&6> email: &e%s" % website[1])
msg(sender, "&7 -- Data provided by ipinfo.io")
msg(sender, "&6> Country: &e%s" % get_country(data))
msg(sender, "&7 -- Data provided by Mojang")
msg(sender, "&6> All ingame names used so far: &e%s" % get_all_names(player))
except:
# can throw exceptions such as timeouts when Mojang API is down
warn(print_traceback())
msg(sender, "&cSorry, something went wrong while fetching data")
@hook.command("check", description="Displays useful stuff about a user", usage="/check <player>")
def on_hook_command(sender, command, label, args):
if sender.hasPermission("utils.check"):
if not checkargs(sender, args, 1, 1):
return True
plugin_header(sender, "Check")
msg(sender, "&7Please notice that the data may not be fully accurate!")
player = server.getOfflinePlayer(args[0]) if len(args) > 0 else None
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
+1 -1
View File
@@ -4,7 +4,7 @@ no_cyclers = open_json_file("cycle", [])
@hook.command("cycle") @hook.command("cycle")
def on_cycler_command(sender, args): def on_cycler_command(sender, command, label, args):
plugin_header(sender, "Cycle") plugin_header(sender, "Cycle")
if not is_player(sender): if not is_player(sender):
msg(sender, "&conly players can do this") msg(sender, "&conly players can do this")
+46 -20
View File
@@ -5,6 +5,8 @@ import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
inputs = open_json_file("damnspam", {}) # format "x;y;z;World" inputs = open_json_file("damnspam", {}) # format "x;y;z;World"
accepted_inputs = ["WOOD_BUTTON", "STONE_BUTTON", "LEVER"] accepted_inputs = ["WOOD_BUTTON", "STONE_BUTTON", "LEVER"]
changing_input = False
removing_input = False
def save_inputs(): def save_inputs():
@@ -25,10 +27,15 @@ def add_input(creator, block, timeout_off, timeout_on):
@hook.command("damnspam") @hook.command("damnspam")
def on_dammnspam_command(sender, args): def on_dammnspam_command(sender, command, label, args):
plugin_header(sender, "DamnSpam") global changing_input
if len(args) in [1,2]:
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): if not is_creative(sender):
msg(sender, "&cYou can only do this in Creative mode.") msg(sender, "&cYou can only do this in Creative mode.")
return True return True
@@ -39,8 +46,8 @@ def on_dammnspam_command(sender, args):
try: try:
timeout_on = round(float(timeout_on), 2) timeout_on = round(float(timeout_on), 2)
timeout_off = timeout_on timeout_off = timeout_on
if not 0 <= timeout_on <= 60: if 60 >= timeout_on <= -2 or timeout_on == 0:
msg(sender, "&cThe timeout must be within 0-60.") msg(sender, "&cThe timeout must be within 0-60 or -1.")
return True return True
except ValueError: except ValueError:
msg(sender, "&cThe timeout must be a number") msg(sender, "&cThe timeout must be a number")
@@ -53,8 +60,12 @@ def on_dammnspam_command(sender, args):
try: try:
timeout_on = round(float(timeout_on), 2) timeout_on = round(float(timeout_on), 2)
timeout_off = round(float(timeout_off), 2) timeout_off = round(float(timeout_off), 2)
if not 0 <= timeout_on <= 60 or not 0 <= timeout_off <= 60: if 60 >= timeout_on <= -2 or timeout_on == 0:
msg(sender, "&cThe timeout must be within 0-60.") timeout_on = False
if 60 >= timeout_off <= -2 or timeout_off == 0:
timeout_off = False
if timeout_on == False or timeout_off == False:
msg(sender, "&cThe timeout must be within 0-60 or -1.")
return True return True
except ValueError: except ValueError:
msg(sender, "&cThe timeout must be a number") msg(sender, "&cThe timeout must be a number")
@@ -67,39 +78,52 @@ def on_dammnspam_command(sender, args):
msg(sender, "&cPlease look at a button or lever while executing this command!") msg(sender, "&cPlease look at a button or lever while executing this command!")
return True return True
if location_str(target) in inputs:
changing_input = True # this input already has a timeout
# test if player is allowed to build here
test_event = BlockBreakEvent(target, sender) test_event = BlockBreakEvent(target, sender)
server.getPluginManager().callEvent(test_event) server.getPluginManager().callEvent(test_event)
changing_input = False
if test_event.isCancelled(): if test_event.isCancelled():
msg(sender, "&cYou are not allowed to modify this button") msg(sender, "&cYou are not allowed to modify this %s" % str(target.getType()).lower())
return True return True
# add block to inputs # add block to inputs
add_input(sender, target, timeout_off, timeout_on) add_input(sender, target, timeout_off, timeout_on)
save_inputs() save_inputs()
msg(sender, "&aSuccessfully set a timeout for this %s." % ttype.lower()) msg(sender, "&aSuccessfully set a timeout for this %s." % ttype.lower().replace("_", " "))
return True return True
else:
msg(sender, "&c/damnspam <seconds> &e(Buttons/Levers)")
msg(sender, "&c/damnspam <seconds after off> <seconds after on> &e(Levers only)")
@hook.event("block.BlockBreakEvent", "normal") @hook.event("block.BlockBreakEvent", "normal")
def on_block_break(event): def on_block_break(event):
global removing_input
if removing_input:
return
sender = event.getPlayer() sender = event.getPlayer()
block = event.getBlock() block = event.getBlock()
btype = str(block.getType()).lower()
if str(block.getType()) in accepted_inputs and not event.isCancelled(): if str(block.getType()) in accepted_inputs and not event.isCancelled():
pos_str = location_str(block) pos_str = location_str(block)
if inputs.get(pos_str): if inputs.get(pos_str):
plugin_header(sender, "DamnSpam")
if sender.isSneaking(): 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 inputs.pop(pos_str) # remove
save_inputs() save_inputs()
msg(sender, "&eSuccessfully removed the input!") msg(sender, "&eSuccessfully removed this %s!" % btype)
return True return True
else: elif not changing_input:
event.setCancelled(True) event.setCancelled(True)
msg(sender, "&cYou cannot destroy this input!") msg(sender, "&cYou cannot destroy this %s!" % btype)
msg(sender, "&c&nSneak&c and break if you want to remove it.") msg(sender, "&c&nSneak&c and break if you want to remove it.")
return True return True
@@ -115,9 +139,11 @@ def on_interact(event):
data = inputs.get(pos_str) data = inputs.get(pos_str)
if data: if data:
checktime = data["timeout_on"] if powered else data["timeout_off"] checktime = data["timeout_on"] if powered else data["timeout_off"]
if data["last_time"] + checktime > now(): if checktime == -1:
event.setCancelled(True) event.setCancelled(True)
plugin_header(sender, "DamnSpam") msg(sender, "&cThis %s is locked permanently by /damnspam." % (btype))
msg(sender, "&cThis %s has a timeout of %ss." % (btype, checktime)) elif data["last_time"] + checktime > now():
event.setCancelled(True)
msg(sender, "&cThis %s has a damnspam timeout of %ss." % (btype, checktime))
else: else:
inputs[pos_str]["last_time"] = round(now(), 2) inputs[pos_str]["last_time"] = round(now(), 2)
+6 -2
View File
@@ -1,4 +1,5 @@
#pylint: disable = F0401 #pylint: disable = F0401
import thread
from helpers import * from helpers import *
from org.bukkit.util import Vector from org.bukkit.util import Vector
from math import sin from math import sin
@@ -16,7 +17,7 @@ whitelists = {} # {ff_owner_id: [white, listed, ids]} (Adding file usage later,
@hook.command("forcefield") @hook.command("forcefield")
def on_forcefield_command(sender, args): def on_forcefield_command(sender, command, label, args):
if not is_player(sender) or not sender.hasPermission(ff_perm): if not is_player(sender) or not sender.hasPermission(ff_perm):
noperm(sender) noperm(sender)
return True return True
@@ -28,7 +29,7 @@ def on_forcefield_command(sender, args):
args[0] = args[0].upper() # If it gets to this point, there are argument(s). args[0] = args[0].upper() # If it gets to this point, there are argument(s).
if args[0] in ["WHITELIST", "WL", "WLIST"]: # Whitelist commands if args[0] in ["WHITELIST", "WL", "WLIST"]: # Whitelist commands
if not args[1:] or args[1].upper() == "LIST": if not args[1:] or args[1].upper() == "LIST":
whitelist_list(sender) thread.start_new_thread(whitelist_list, (sender,))
return True return True
args[1] = args[1].upper() # If it gets too this point, there is a second argument. args[1] = args[1].upper() # If it gets too this point, there is a second argument.
@@ -88,6 +89,7 @@ def change_whitelist(sender, add, names): #Add names if add == True else Remove
def whitelist_list(player): def whitelist_list(player):
try:
player_id = uid(player) player_id = uid(player)
count = 0 count = 0
forcefield_header(player, "&bForcefield whitelist:") forcefield_header(player, "&bForcefield whitelist:")
@@ -97,6 +99,8 @@ def whitelist_list(player):
msg(player, "&b %s. &f%s" % (count, pname)) msg(player, "&b %s. &f%s" % (count, pname))
if count == 0: if count == 0:
msg(player, "&c Your whitelist has no entries.") msg(player, "&c Your whitelist has no entries.")
except:
warn("Unable to finish whitelist_list process")
def whitelist_clear(player): def whitelist_clear(player):
+10 -4
View File
@@ -1,9 +1,14 @@
import thread
from helpers import * from helpers import *
friends = open_json_file("friends", {}) # {Player_UUID:[List_of_friend_uuids]} friends = open_json_file("friends", {}) # {Player_UUID:[List_of_friend_uuids]}
friend_join_sound = "random.orb" 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 @hook.event("player.PlayerJoinEvent", "high") # creates sound and sends a bold message on friend join
def fjm(event): # friend join message def fjm(event): # friend join message
@@ -25,6 +30,7 @@ def friendmessage(player, message): # sends a message with a prefix
def ls(sender): def ls(sender):
try:
sender_friends = friends.get(uid(sender), False) sender_friends = friends.get(uid(sender), False)
if sender_friends: if sender_friends:
friends_string = "" friends_string = ""
@@ -33,14 +39,14 @@ def ls(sender):
friendmessage(sender, "&aYour friends list: " + friends_string[:len(friends_string)-2]) friendmessage(sender, "&aYour friends list: " + friends_string[:len(friends_string)-2])
else: else:
friendmessage(sender, "&cYour friends list is empty") friendmessage(sender, "&cYour friends list is empty")
except:
warn("Unable to finish friends' ls process")
def clear(sender): def clear(sender):
sender_id = uid(sender) sender_id = uid(sender)
if friends.get(sender_id, False): if friends.get(sender_id, False):
for uuid in friends[sender_id]:
friendmessage(retrieve_player(uuid), "&c&o%s &cremoved you from their friends list" % stripcolors(sender.getDisplayName()))
friends.pop(sender_id) friends.pop(sender_id)
friendmessage(sender, "&aFriends list cleared") friendmessage(sender, "&aFriends list cleared")
save_friends() save_friends()
@@ -123,7 +129,7 @@ def fhelp(sender):
@hook.command("friends") @hook.command("friends")
def on_friend_command(sender, args): def on_friend_command(sender, command, label, args):
if not is_player(sender): if not is_player(sender):
friendmessage(sender, "&c&lYou can't have friends!") friendmessage(sender, "&c&lYou can't have friends!")
return True return True
@@ -133,7 +139,7 @@ def on_friend_command(sender, args):
# /friends list # /friends list
if cmd in ["list", "lst", "*"]: if cmd in ["list", "lst", "*"]:
ls(sender) thread.start_new_thread(ls, (sender,))
# /friends clear # /friends clear
elif cmd in ["clear", "/"]: elif cmd in ["clear", "/"]:
Regular → Executable
+141 -34
View File
@@ -6,26 +6,55 @@ import org.bukkit as bukkit
import org.bukkit.Location as Location import org.bukkit.Location as Location
import org.bukkit.entity.Player as Player import org.bukkit.entity.Player as Player
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause as TeleportCause 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.block as bblock
import org.bukkit.event.entity as entity
import org.bukkit.command.ConsoleCommandSender
from org.bukkit.entity import *
from player import get_py_player
from player import py_players
#Imports for async query
from secrets import *
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 shared = {} # this dict can be used to share stuff across modules
server = bukkit.Bukkit.getServer() server = bukkit.Bukkit.getServer()
def info(text): def info(text):
"""
Log info to console
"""
server.getLogger().info("[RedstonerUtils] %s" % text) server.getLogger().info("[RedstonerUtils] %s" % text)
def warn(text): def warn(text):
"""
Log warning to console
"""
server.getLogger().warning("[RedstonerUtils] %s" % text) server.getLogger().warning("[RedstonerUtils] %s" % text)
def error(text): def error(text):
"""
Log error to console
"""
server.getLogger().severe("[RedstonerUtils] %s" % text) server.getLogger().severe("[RedstonerUtils] %s" % text)
def fine(text):
"""
Log anything to the logs alone, not the console
"""
server.getLogger().fine(text)
def msg(player, text, usecolor = True, basecolor = None): def msg(player, text, usecolor = True, basecolor = None):
""" """
send a message to player send a message to player
@@ -33,7 +62,7 @@ def msg(player, text, usecolor = True, basecolor = None):
unless usecolor is False, &-codes are translated to real color codes unless usecolor is False, &-codes are translated to real color codes
for that case, basecolor can be useful. basecolor accepts a single character as color code for that case, basecolor can be useful. basecolor accepts a single character as color code
""" """
if player and (player == server.getConsoleSender() or player.getPlayer()): # getPlayer() returns None when offline if player and (player == server.getConsoleSender() or player.isOnline()): # getPlayer() returns None when offline
if basecolor: if basecolor:
if usecolor: if usecolor:
text = colorify(text) text = colorify(text)
@@ -42,15 +71,16 @@ def msg(player, text, usecolor = True, basecolor = None):
player.sendMessage(colorify(text) if usecolor else text) player.sendMessage(colorify(text) if usecolor else text)
def broadcast(perm, text): def broadcast(perm, text, usecolor = True):
""" """
better than bukkit's broadcast. better than bukkit's broadcast.
bukkit only works with permissibles that are subscribed to perm bukkit only works with permissibles that are subscribed to perm
""" """
if usecolor:
text = colorify(text) text = colorify(text)
for recipient in list(server.getOnlinePlayers()) + [server.getConsoleSender()]: for recipient in list(server.getOnlinePlayers()) + [server.getConsoleSender()]:
if not perm or recipient.hasPermission(perm): if not perm or recipient.hasPermission(perm):
msg(recipient, text) msg(recipient, text, usecolor = False)
def colorify(text): def colorify(text):
@@ -90,14 +120,20 @@ def plugin_header(recipient = None, name="Redstoner Utils"):
def noperm(player): def noperm(player):
"""
Send the default permission failure message to the player
"""
msg(player, "&cno permission") msg(player, "&cno permission")
def runas(player, cmd): def runas(player, cmd):
""" """
run a command as player run a command as player
the cmd should no be prefixed with a / the cmd should NOT be prefixed with a /
""" """
if is_player(player):
player.chat("/" + cmd)
else:
server.dispatchCommand(player, cmd) server.dispatchCommand(player, cmd)
@@ -108,6 +144,15 @@ def is_player(obj):
return (isinstance(obj, Player)) 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): def checkargs(sender, args, amin, amax):
""" """
check if a command has a valid amount of args, otherwise notify the sender check if a command has a valid amount of args, otherwise notify the sender
@@ -129,13 +174,6 @@ def checkargs(sender, args, amin, amax):
return True return True
def warp(player, args, warpname):
if not checkargs(player, args, 0, 1):
return False # You can check if it worked
runas(player, "warp %s" % warpname)
return True
def is_creative(player): def is_creative(player):
""" """
returns True if the player is in Creative mode returns True if the player is in Creative mode
@@ -166,25 +204,48 @@ def known_player(player):
""" """
return player.hasPlayedBefore() 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.)
def open_json_file(filename, default): 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):
""" """
opens the given json file and returns an object or returns None on error opens the given json file and returns an object or returns None on error
filename is the path + name of the file. filename is only the name of the file without .json appended.
""" """
data = None
try: try:
with open("plugins/redstoner-utils.py.dir/files/%s.json" % filename) as obj: with open("plugins/redstoner-utils.py.dir/files/%s.json" % filename) as obj:
data = json_loads(obj.read()) default = json_loads(obj.read())
except Exception, e: except Exception, e:
error("Failed to read from %s: %s" % (filename, e)) error("Failed to read from %s: %s" % (filename, e))
return (default if data is None else data) return default
def save_json_file(filename, obj): def save_json_file(filename, obj):
""" """
saves the given object as json into filename saves the given object as json into filename
filename is the path + name of the file. filename is only the name of the file without .json appended.
""" """
try: try:
with open("plugins/redstoner-utils.py.dir/files/%s.json" % filename, "w") as f: with open("plugins/redstoner-utils.py.dir/files/%s.json" % filename, "w") as f:
@@ -193,27 +254,73 @@ def save_json_file(filename, obj):
error("Failed to write to %s: %s" % (filename, e)) error("Failed to write to %s: %s" % (filename, e))
def toggle(player, ls, add = None, on = "&aToggle now on!", off = "&cToggle now off!", already = "&cToggle was already %s"): def toggle(player, ls, name = "Toggle", add = None):
""" """
Toggle presence of a player's UUID in a list (ls) Toggles presence of a player's UUID in a list
'add' controls if a player should be added(True) or removed(False) If add is given, True explicitely adds it whereas False removes it
if 'add' is None, ls will simply be toggled for that player.
when 'add' is given, but won't change anything, %s in 'already' is replaced with "ON" or "OFF"
""" """
pid = uid(player) pid = uid(player)
enabled = pid in ls if pid in ls or add == False:
# Do some checks and remove pid.
if enabled and add == False:
ls.remove(pid) ls.remove(pid)
msg(player, on) msg(player, "&a%s turned off!" % name)
elif add != False:
# Do some checks and append pid.
elif not enabled and add == True:
ls.append(pid) ls.append(pid)
msg(player, off) msg(player, "&a%s turned on!" % name)
# Already on/off (optional) 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: else:
msg(player, already % (" ON" if add else " OFF")) 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):
perms = player.getEffectivePermissions()
for perm in perms:
if str(perm.getPermission()).startswith(permnode):
return str(perm.getPermission()).replace(permnode, "")
# Gets an online player from their name
def get_player(name):
for p in bukkit.Bukkit.getServer().getOnlinePlayers():
if p.getName().lower() == name.lower():
return p
return None
def array_to_list(array):
return_list = []
for a in array:
return_list += [a]
return return_list
#debug wrapper
def debug(func):
def wrap(*args, **kwargs):
try:
func(*args, **kwargs)
except:
print(trace())
return wrap
+308
View File
@@ -0,0 +1,308 @@
##################################
# I'M BUSY! Plugin by Curs3d #
# Concept by CookieManors :D #
##################################
# 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
imbusy_version = "v1.1.0"
base_permission = "utils.busy" # for /busy status
use_permission = "utils.busy.use" # for being busy
override_permission = "utils.busy.override" # for being able to bother busy people
busy_players = {} # name : false/true where false is normal busy and true is super busy
@hook.command("imbusy",
aliases = ["busy"],
usage = "/<command> [on, off, status/check]",
description = "Offers control over your busy status"
)
def on_busy_command(sender, cmd, label, args):
if not is_player(sender):
msg(sender, "&7Sorry, Console cannot be busy")
return True
plugin_header(recipient = sender, name = "I'M BUSY!")
#args = array_to_list(args)
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 toggle(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True
sender_name = sender.getName()
if sender_name in busy_players:
del busy_players[sender_name]
broadcast(None, sender.getDisplayName() + " &7is no longer busy...")
else:
busy_players.append(sender_name)
broadcast(None, sender.getDisplayName() + " &7is now busy...")
return True
def help(sender):
msg(sender, "Let's you put yourself in busy status, preventing pms and tpa requests from other players")
msg(sender, "\n&eCommands:")
msg(sender, "&e/busy &7- Toggles busy status")
msg(sender, "&e/busy on &7- Turns on busy status")
msg(sender, "&e/busy off &7- Turns off busy status")
msg(sender, "&e/busy status [player] &7- shows your or [player]'s current busy status")
msg(sender, "&e/busy super &7- sets your status to SUPER busy such that even friends can not bother you")
return True
def on(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True
sender_name = sender.getName()
if busy_players.get(sender_name) is False: # can be None, False or True
msg(sender, "&7You are already busy!")
else:
busy_players[sender_name] = False # busy but not super busy
broadcast(None, sender.getDisplayName() + " &7is now busy...")
return True
def off(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True
sender_name = sender.getName()
if sender_name not in busy_players:
msg(sender, "&7You are not busy! You cannot be even less busy! Are you perhaps bored?")
return True
del busy_players[sender_name]
broadcast(None, sender.getDisplayName() + " &7is no longer busy...")
return True
def status(sender, args):
if not sender.hasPermission(base_permission):
noperm(sender)
return True
if len(args) == 0:
if sender.getName() in busy_players:
if busy_players[sender_name] is False:
msg(sender, "&7You are currently busy.")
else:
msg(sender, "&7You are currently SUPER busy.")
else:
msg(sender, "&7You are currently not busy.")
else:
target = server.getPlayer(args[0])
if target is None:
msg(sender, "&7That player is not online")
elif target.getName() in busy_players:
if busy_players[target.getName()] is False:
msg(sender, "&7Player %s &7is currently busy." % target.getDisplayName())
else:
msg(sender, "&7Player %s &7is currently SUPER busy." % target.getDisplayName())
else:
msg(sender, "&7Player %s &7is currently not busy." % target.getDisplayName())
return True
def super_cmd(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True
sender_name = sender.getName()
if busy_players.get(sender_name) is True:
msg(sender, "&7You are already SUPER busy!")
else:
busy_players[sender_name] = True # SUPER busy
broadcast(None, sender.getDisplayName() + " &7is now SUPER busy...")
return True
@hook.event("player.PlayerQuitEvent", "lowest")
def on_player_leave(event):
player_name = event.getPlayer().getName()
if player_name in busy_players:
del busy_players[player_name]
#---- Dicode for catching any bothering of busy people ----
reply_targets = {}
def can_send(sender, target):
if not target.getName() in busy_players:
return True
if target is sender or sender.hasPermission(override_permission):
return True
return busy_players[target.getName()] is False and is_friend_of(target, sender)
def whisper(sender, target_name):
target = server.getPlayer(target_name)
if target is not None:
if not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
reply_targets[sender.getName()] = target.getName()
# allow the target to reply regardless of sender being busy
if target.getName() in reply_targets:
del reply_targets[target.getName()]
return True
def reply(sender):
if sender.getName() in reply_targets:
target = server.getPlayer(reply_targets[sender.getName()])
if target is not None:
if not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
# allow the target to reply regardless of sender being busy
if target.getName() in reply_targets:
del reply_targets[target.getName()]
return True
class CommandWrapper(Command):
def __init__(self, wrapped, checker):
Command.__init__(self, wrapped.getName())
self.setDescription(wrapped.getDescription())
self.setPermission(wrapped.getPermission())
self.setUsage(wrapped.getUsage())
self.setAliases(wrapped.getAliases())
self.wrapped = wrapped
self.checker = checker
def execute(self, sender, label, args):
try:
if not is_player(sender) or self.checker(sender, args):
return self.wrapped.execute(sender, label, args)
except:
error(trace())
return True
def tabComplete(self, sender, alias, args):
return self.wrapped.tabComplete(sender, alias, args)
def msg_command_checker(sender, args):
return len(args) <= 1 or whisper(sender, args[0])
def reply_command_checker(sender, args):
return len(args) == 0 or reply(sender)
def tpa_command_checker(sender, args):
if len(args) == 0:
return True
target = server.getPlayer(args[0])
if target is not None and not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
return True
def tpahere_command_checker(sender, args):
return tpa_command_checker(sender, args)
def mail_command_checker(sender, args):
info("Mail command executed")
if len(args) < 3 or args[0].lower() != "send":
return True
target = server.getPlayer(args[1])
if target is not None and not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
return True
@hook.event("player.PlayerCommandPreprocessEvent", "monitor")
def on_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)
@hook.enable
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())
+32
View File
@@ -0,0 +1,32 @@
from helpers import *
from adminchat import *
imout_toggle_list = []
@hook.command("imout")
def on_imout_command(sender, command, label, args):
if not is_player(sender):
msg(sender, "&cThis command can't be run from the console")
return True
if sender.hasPermission("utils.imout"):
name = sender.getName()
symbol = "&a&l+"
if name in imout_toggle_list:
msg(sender, "&eWelcome back! You are no longer hidden")
msg(sender, "&6We disabled /act for you!")
runas(sender, "vanish off")
if name in imout_toggle_list:
imout_toggle_list.remove(name)
if name in ac_toggle_list:
ac_toggle_list.remove(name)
else:
symbol = "&c&l-"
msg(sender, "&eYou just left... Or didn't you?")
imout_toggle_list.append(name)
runas(sender, "vanish on")
if name not in ac_toggle_list:
msg(sender, "&6We enabled /act for you!")
ac_toggle_list.append(name)
broadcast(None, "%s &7%s" % (symbol, name))
return True
Executable
+108
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
+1 -1
View File
@@ -37,7 +37,7 @@ def tp_chunk(sender, id):
@hook.command("lagchunks") @hook.command("lagchunks")
def on_lagchunks_command(sender, args): def on_lagchunks_command(sender, command, label, args):
if sender.hasPermission("utils.lagchunks"): if sender.hasPermission("utils.lagchunks"):
plugin_header(sender, "Lagchunks") plugin_header(sender, "Lagchunks")
global lagchunks global lagchunks
+275
View File
@@ -0,0 +1,275 @@
from helpers import *
from passlib.hash import pbkdf2_sha256 as crypt
from basecommands import simplecommand
import time
import threading
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
wait_time = 30 #seconds
admin_perm = "utils.loginsecurity.admin"
min_pass_length = 8
blocked_events = ["block.BlockBreakEvent", "block.BlockPlaceEvent", "player.PlayerMoveEvent","player.AsyncPlayerChatEvent"]
def matches(password,user):
thread = threading.Thread(target=matches_thread, args = (password,user))
thread.start()
def matches_thread(password, user):
hashed = get_pass(uid(user))
py_player = get_py_player(user)
if crypt.verify(password, hashed):
if py_player.logging_in:
py_player.logging_in = False
msg(user, "&aLogged in successfully!")
else:
if py_player.logging_in:
msg(user, "&cInvalid password!")
@simplecommand("cgpass",
usage = "<password> <new password>",
description = "Changes your password",
senderLimit = 0,
helpNoargs = True)
def change_pass_command(sender, command, label, args):
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>",
description = "Logs you in if <password> matches your password.",
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):
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 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):
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()))
return "&aPassword of %s reset successfully" % user.getName()
return "&cThat player could not be found (or is not registered)"
def change_pass(uuid, pw):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("UPDATE secret SET pass = ? WHERE uuid = ?", (pw,uuid,))
conn.commit()
curs.close()
conn.close()
def get_pass(uuid):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("SELECT pass FROM secret WHERE uuid = ?", (uuid,))
results = curs.fetchall()
curs.close()
conn.close()
return results[0][0]
def create_pass(uuid,pw):
thread = threading.Thread(target=create_pass_thread, args=(uuid,pw))
thread.start()
def create_pass_thread(uuid, pw):
pw = crypt.encrypt(pw, rounds=200000, salt_size=16)
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("INSERT INTO secret VALUES (?,?)", (uuid,pw,))
conn.commit()
curs.close()
conn.close()
def is_registered(uuid):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("SELECT EXISTS(SELECT * FROM secret WHERE uuid = ?)", (uuid,))
results = curs.fetchall()
curs.close()
conn.close()
if results[0][0] == 1:
return True
return False
def delete_pass(uuid):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("DELETE FROM secret WHERE uuid = ?", (uuid,))
conn.commit()
curs.close()
conn.close()
@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(), "&4You will be disconnected after 60 seconds if you don't &alogin")
msg(user, "&cUse /login <password>")
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):
def __init__(self, player):
self.player = player
def run(self):
if self.player.isOnline():
self.player.kickPlayer(colorify("&aLogin timed out"))
def kick_thread():
while True:
time.sleep(1)
now = time.time()
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)
thread.daemon = True
thread.start()
##Threading end
for blocked_event in blocked_events:
@hook.event(blocked_event, "high")
def on_blocked_event(event):
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)
+62 -1
View File
@@ -9,6 +9,7 @@ from traceback import format_exc as print_traceback
sys.path += ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/pymodules/python2.7', '/usr/lib/pyshared/python2.7'] sys.path += ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/pymodules/python2.7', '/usr/lib/pyshared/python2.7']
try: try:
# Library that adds a bunch of re-usable methods which are used in nearly all other modules
from helpers import * from helpers import *
except: except:
print("[RedstonerUtils] ERROR: Failed to import helpers:") print("[RedstonerUtils] ERROR: Failed to import helpers:")
@@ -31,20 +32,80 @@ info("Loading RedstonerUtils...")
# Import all modules, in this order # Import all modules, in this order
shared["load_modules"] = [ shared["load_modules"] = [
# Collection of tiny utilities
"misc", "misc",
# Adds chat for staff using /ac <text or ,<text>
"adminchat", "adminchat",
# Adds /badge, allows to give players achievements
"badges",
# 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", "lagchunks",
# Adds /report and /rp, Stores reports with time and location
"reports", "reports",
# Adds group-chat with /chatgroup and /cgt to toggle normal chat into group mode
"chatgroups", "chatgroups",
# Adds /token, reads and writes from the database to generate pronouncable (and thus memorable) registration-tokens for the website
"webtoken", "webtoken",
# Adds /lol, broadcasts random funyy messages. A bit like the splash text in the menu
"saylol", "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", "skullclick",
# Adds /listen, highlights chat and plays a sound when your name was mentioned
"mentio", "mentio",
# Adds /cycler, swaps the hotbar with inventory when player changes slot from right->left or left->right
"cycle", "cycle",
# Adds /getmotd & /setmotd to update the motd on the fly (no reboot)
"motd", "motd",
# AnswerBot. Hides stupid questions from chat and tells the sender about /faq or the like
"abot", "abot",
# Adds '/forcefield', creates forcefield for players who want it.
"forcefield", "forcefield",
"friends" # Adds /damnspam, creates timeout for buttons/levers to mitigate button spam.
"damnspam",
# Adds /check, useful to lookup details about a player
"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
"snowbrawl",
# Adds /tm [player] for a messages to be sent to this player via /msg
"pmtoggle",
# Replacement for LoginSecurity
"loginsecurity",
# Centralized Player class
"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"] = {} shared["modules"] = {}
for module in shared["load_modules"]: for module in shared["load_modules"]:
+16 -10
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) 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") arrow = colorify(u"&r&7\u2192&r")
colors_reg = reg_compile(u"\u00A7[\\da-fk-or]") # finds color codes colors_reg = reg_compile(u"\u00A7[\\da-fk-or]") # finds color codes
@@ -13,7 +13,7 @@ def saveMentions():
save_json_file("mentio", mentions) save_json_file("mentio", mentions)
@hook.event("player.AsyncPlayerChatEvent", "high") @hook.event("player.AsyncPlayerChatEvent", "monitor")
def onChat(event): def onChat(event):
if not event.isCancelled(): if not event.isCancelled():
sender = event.getPlayer() sender = event.getPlayer()
@@ -52,7 +52,7 @@ def onChat(event):
except: except:
# list might not be mutable, ignoring. Receiver will get the message twice # list might not be mutable, ignoring. Receiver will get the message twice
pass pass
message = " ".join([sender.getDisplayName(), arrow] + rec_words) message = " "+" ".join([sender.getDisplayName(), arrow] + rec_words)
msg(recipient, message, usecolor = False) msg(recipient, message, usecolor = False)
recipient.playSound(recipient.getLocation(), "mob.chicken.plop", 1, 2) recipient.playSound(recipient.getLocation(), "mob.chicken.plop", 1, 2)
@@ -70,7 +70,7 @@ def add_keyword(sender, args):
keywords = get_keywords(sender) keywords = get_keywords(sender)
new_word = stripcolors(args[1].lower()) new_word = stripcolors(args[1].lower())
if len(keywords) >= max_amount: if (len(keywords) >= max_amount) and (max_amount >= 0):
msg(sender, "&cYou are already listening for %s words! Try &6/mentio del <word>" % max_amount) msg(sender, "&cYou are already listening for %s words! Try &6/mentio del <word>" % max_amount)
return True return True
@@ -86,7 +86,7 @@ def add_keyword(sender, args):
if keywords: if keywords:
mentions[uid(sender)] = keywords mentions[uid(sender)] = keywords
msg(sender, "&aYou are now listening for '&2%s'!" % new_word) msg(sender, "&aYou are now listening for '&2%s&2'!" % new_word)
saveMentions() saveMentions()
return True return True
@@ -107,13 +107,19 @@ def del_keyword(sender, args):
elif sender_id in mentions: elif sender_id in mentions:
del mentions[sender_id] del mentions[sender_id]
saveMentions() saveMentions()
msg(sender, "&aYou are no longer listening for '&2%s&e'!" % del_word) msg(sender, "&aYou are no longer listening for '&2%s&2'!" % del_word)
else: else:
msg(sender, "&cWe can't remove something that doesn't exist! Try &6/mentio list") msg(sender, "&cWe can't remove something that doesn't exist! Try &6/mentio list")
def show_help(player):
msg(player, "&a/mentio add <word>")
msg(player, "&a/mentio del <word>")
msg(player, "&a/mentio list")
@hook.command("mentio") @hook.command("mentio")
def onListenCommand(sender, args): def onListenCommand(sender, command, label, args):
plugin_header(sender, "Mentio") plugin_header(sender, "Mentio")
argnum = len(args) argnum = len(args)
@@ -137,7 +143,7 @@ def onListenCommand(sender, args):
if not keywords: if not keywords:
msg(sender, "&cYou are currently listening for no words! Try &6/mentio add <word>") msg(sender, "&cYou are currently listening for no words! Try &6/mentio add <word>")
else: else:
msg(sender, "&a/mentio add <word>") show_help(sender)
msg(sender, "&a/mentio del <word>") else:
msg(sender, "&a/mentio list") show_help(sender)
return True return True
+238 -82
View File
@@ -1,128 +1,205 @@
#pylint: disable = F0401 #pylint: disable = F0401
from helpers import * from helpers import *
from time import time as now from time import time as now
from time import sleep
from sys import exc_info from sys import exc_info
import thread import thread
import org.bukkit.inventory.ItemStack as ItemStack import org.bukkit.inventory.ItemStack as ItemStack
import org.bukkit.Bukkit as Bukkit
from basecommands import simplecommand, Validate
import java.util.Arrays as Arrays
#
# Welcome new players
#
@hook.event("player.PlayerJoinEvent", "monitor") @hook.event("player.PlayerJoinEvent", "monitor")
def on_join(event): def on_join(event):
"""
Welcome new players
"""
player = event.getPlayer() player = event.getPlayer()
# send welcome broadcast # send welcome broadcast
if not player.hasPlayedBefore(): if not player.hasPlayedBefore():
broadcast("utils.greet_new", "") broadcast("utils.greet_new", "\n&a&lPlease welcome &f" + player.getDisplayName() + " &a&lto Redstoner!\n")
broadcast("utils.greet_new", "&a&lPlease welcome &f" + player.getDisplayName() + " &a&lto Redstoner!")
broadcast("utils.greet_new", "")
# clear out some eventual crap before # clear out some eventual crap before
msg(player, " \n \n \n \n \n \n \n \n \n \n \n \n ") msg(player, " \n \n \n \n \n \n \n \n \n \n \n \n ")
msg(player, " &4Welcome to the Redstoner Server!") msg(player, " &4Welcome to the Redstoner Server!")
msg(player, " &6Before you ask us things, take a quick") msg(player, " &6Before you ask us things, take a quick")
msg(player, " &6look at the &a&l/FAQ &6command.") msg(player, " &6look at &a&nredstoner.com/info")
msg(player, " \n&6thank you and happy playing ;)") msg(player, " \n&6thank you and happy playing ;)")
msg(player, " \n \n") msg(player, " \n \n")
# teleport to spawn when spawning inside portal # teleport to spawn when spawning inside portal
loginloc = player.getLocation().getBlock().getType() loginloc = player.getLocation().getBlock().getType()
headloc = player.getEyeLocation().getBlock().getType() headloc = player.getEyeLocation().getBlock().getType()
if str(loginloc) == "PORTAL" or str(headloc) == "PORTAL": if "PORTAL" in [str(headloc), str(loginloc)]:
msg(player, "&4Looks like you spawned in a portal... Let me help you out") msg(player, "&4Looks like you spawned in a portal... Let me help you out")
msg(player, "&6You can use /back if you &nreally&6 want to go back") msg(player, "&6You can use /back if you &nreally&6 want to go back")
player.teleport(player.getWorld().getSpawnLocation()) player.teleport(player.getWorld().getSpawnLocation())
"""
This code fixes /up 0 destroying/replacing blocks in plots that are not yours.
If you use //up, this is caught by plotme and cancelled if you are not allowed to build.
However, if you use //up, WorldEdit does the following on "low" priority:
* Change the command to /up with the same arguments
* Run another event with /up but its cancelled (dunno why it does this)
# Keep in mind that, on "lowest" priority, PlotMe might cancel events.
# /sudo - execute command/chat *as* a player/console
#
@hook.command("sudo") """
def on_sudo_command(sender, args): dup = 0 #Used to store when someone used //up
if sender.hasPermission("utils.sudo"):
plugin_header(sender, "Sudo") @hook.event("player.PlayerCommandPreprocessEvent", "lowest")
if not checkargs(sender, args, 2, -1): def cmd_event(event):
global dup
if event.getMessage().split(" ")[0] in ("//up", "/worldedit:/up"):
dup = True
@hook.event("player.PlayerCommandPreprocessEvent", "normal")
def cmd_event2(event):
global dup
args = event.getMessage().split(" ")
if args[0].lower() in ("/up", "/worldedit:up"):
if dup: #If plotme cancelled this, it will not matter. This lets it through but PlotMe doesn't.
dup = False
elif not event.isCancelled():
event.setCancelled(True)
event.getPlayer().chat("//up " + " ".join(args[1:]))
""" Disabled while builder can't access Trusted
@hook.event("player.PlayerGameModeChangeEvent", "low")
def on_gamemode(event):
user = event.getPlayer()
if str(event.getNewGameMode()) != "SPECTATOR" and user.getWorld().getName() == "Trusted" and not user.hasPermission("mv.bypass.gamemode.Trusted"):
event.setCancelled(True)
"""
@hook.event("player.PlayerBedEnterEvent")
def on_bed_enter(event):
world = event.getPlayer().getWorld()
if world.getName() in ("Survival_1", "TrustedSurvival_1"):
for player in world.getPlayers():
player.setSleepingIgnored(True)
@hook.event("player.PlayerTeleportEvent")
def on_player_teleport(event):
"""
Disable spectator teleportation
"""
player = event.getPlayer()
if not event.isCancelled() and str(event.getCause()) == "SPECTATE" and not player.hasPermission("utils.tp.spectate"):
event.setCancelled(True)
msg(event.getPlayer(), "&cSpectator teleportation is disabled")
@hook.event("block.BlockFromToEvent", "highest")
def on_flow(event):
if event.isCancelled():
return
block = event.getToBlock()
if block.getWorld().getName() == "Creative" and rs_material_broken_by_flow(str(block.getType())):
event.setCancelled(True)
def rs_material_broken_by_flow(material):
if material in ("REDSTONE", "LEVER", "TRIPWIRE"):
return True return True
parts = material.split("_")
length = len(parts)
return length > 1 and (parts[0] == "DIODE" or parts[1] in ("TORCH", "WIRE", "BUTTON", "HOOK") or (length == 3 and parts[1] == "COMPARATOR"))
@hook.event("player.PlayerInteractEvent")
def on_interact(event):
if (not event.isCancelled()
and str(event.getAction()) == "RIGHT_CLICK_BLOCK"
and str(event.getMaterial()) in ("REDSTONE_COMPARATOR_OFF", "REDSTONE_COMPARATOR_ON")
and not can_build(player, event.getClickedBlock())
):
event.setCancelled(True)
sudo_blacklist = ["pyeval", "script_backup_begin", "script_backup_end", "script_backup_error", "script_backup_database_begin", "script_backup_database_dumps", "script_backup_database_end",
"script_backup_database_error", "script_backup_database_abort", "script_trim", "script_trim_result", "script_spigot_update", "script_disk_filled", "script_restart", "script_restart_abort",
"script_stop", "script_stop_abort", "script_shutdown", "stop", "esudo", "essentials:sudo", "sudo"]
@simplecommand("sudo",
usage = "<player> [cmd..]",
description = "Makes <player> write [cmd..] in chat",
amin = 2,
helpNoargs = True)
def on_sudo_command(sender, command, label, args):
target = args[0] target = args[0]
cmd = " ".join(args[1:]) cmd = " ".join(args[1:])
msg(sender, "Running '&e%s&r' as &3%s" % (cmd, target)) msg(sender, "&2[SUDO] &rRunning '&e%s&r' as &3%s" % (cmd, target))
if cmd[0] == "/": is_cmd = cmd[0] == "/"
cmd = cmd[1:] is_console = target.lower() in ["server", "console"]
if target.lower() == "server" or target.lower() == "console": first_cmd = (args[1])[1:] if is_cmd else None
runas(server.getConsoleSender(), cmd) if first_cmd in sudo_blacklist and (is_player(sender) and uid(sender) not in pythoners):
elif server.getPlayer(target): return "&cYou can't sudo this command"
runas(server.getPlayer(target), cmd) if is_console:
else: server.dispatchCommand(server.getConsoleSender(), cmd[1:] if is_cmd else cmd)
msg(sender, "&cPlayer %s not found!" % target) return None
else: target_player = server.getPlayer(target)
if target.lower() == "server" or target.lower() == "console": if target_player:
runas(server.getConsoleSender(), "say %s" % cmd) target_player.chat(cmd)
elif server.getPlayer(target): return None
server.getPlayer(target).chat(cmd) return "&cPlayer %s not found!" % target
else:
msg(sender, "&cPlayer %s not found!" % target)
else:
noperm(sender)
return True
#
# Clicking redstone_sheep with shears will drop redstone + wool and makes a moo sound
#
last_shear = 0.0 @simplecommand("me",
usage = "[message..]",
@hook.event("player.PlayerInteractEntityEvent") description = "Sends a message in third person",
def on_player_entity_interact(event): helpNoargs = True)
global last_shear def on_me_command(sender, command, label, args):
if not event.isCancelled(): text = colorify("&7- %s &7%s " % (sender.getDisplayName() if isinstance(sender, Player) else "&9CONSOLE", u"\u21E6"))
shear_time = now() broadcast("utils.me", text + " ".join(args), usecolor = sender.hasPermission("essentials.chat.color"))
if last_shear + 0.4 < shear_time: return None
last_shear = shear_time
sender = event.getPlayer()
entity = event.getRightClicked()
if is_player(entity) and uid(entity) == "ae795aa8-6327-408e-92ab-25c8a59f3ba1" and str(sender.getItemInHand().getType()) == "SHEARS" and is_creative(sender):
for _ in range(5):
entity.getWorld().dropItemNaturally(entity.getLocation(), ItemStack(bukkit.Material.getMaterial("REDSTONE")))
entity.getWorld().dropItemNaturally(entity.getLocation(), ItemStack(bukkit.Material.getMaterial("WOOL")))
sender.playSound(entity.getLocation(), "mob.cow.say", 1, 1)
#
# /pluginversions - print all plugins + versions; useful when updating plugins
#
@hook.command("pluginversions") @hook.command("pluginversions")
def on_pluginversions_command(sender, args): def on_pluginversions_command(sender, command, label, args):
"""
/pluginversions
print all plugins + versions; useful when updating plugins
"""
try:
plugin_header(sender, "Plugin versions") plugin_header(sender, "Plugin versions")
plugins = 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()) plugins.sort(key = lambda pl: pl.getDescription().getName())
msg(sender, "&3Listing all " + str(len(plugins)) + " plugins and their version:") msg(sender, "&3Listing all " + str(len(plugins)) + " plugins and their version:")
for plugin in plugins: for plugin in plugins:
msg(sender, "&6" + plugin.getDescription().getName() + "&r: &e" + plugin.getDescription().getVersion()) msg(sender, "&6" + pl.getDescription().getName() + "&r: &e" + pl.getDescription().getVersion())
return True return True
except:
error(trace())
#
# /echo - essentials echo sucks and prints mail alerts sometimes
#
@hook.command("echo") @hook.command("echo")
def on_echo_command(sender, args): def on_echo_command(sender, command, label, args):
"""
/echo
essentials echo sucks and prints mail alerts sometimes
"""
msg(sender, " ".join(args).replace("\\n", "\n")) msg(sender, " ".join(args).replace("\\n", "\n"))
#
# /pyeval - run python ingame
#
# has to be in main.py so we can access the modules
def eval_thread(sender, code): def eval_thread(sender, code):
"""
/pyeval
run python ingame
"""
try: try:
result = eval(code) result = eval(code)
msg(sender, ">>> %s: %s" % (colorify("&3") + type(result).__name__, colorify("&a") + unicode(result) + "\n "), usecolor = False) msg(sender, ">>> %s: %s" % (colorify("&3") + type(result).__name__, colorify("&a") + unicode(result) + "\n "), usecolor = False)
@@ -135,22 +212,101 @@ def eval_thread(sender, code):
msg(sender, ">>> %s: %s" % (eclass.__name__, e) + "\n ", False, "c") msg(sender, ">>> %s: %s" % (eclass.__name__, e) + "\n ", False, "c")
thread.exit() thread.exit()
pythoners = [
"e452e012-2c82-456d-853b-3ac8e6b581f5", # Nemes
"ae795aa8-6327-408e-92ab-25c8a59f3ba1", # jomo
"305ccbd7-0589-403e-a45b-d791dcfdee7d", # PanFritz
"51f2ad3c-6cc8-40ea-aa2b-f25970316921" # Dico
]
@hook.command("pyeval") @simplecommand("pyeval",
def on_pyeval_command(sender, args): usage = "[code..]",
if sender.hasPermission("utils.pyeval"): description = "Runs python [code..] and returns the result",
if not checkargs(sender, args, 1, -1): helpNoargs = True)
return True def on_pyeval_command(sender, command, label, args):
msg(sender, "%s" % " ".join(args), False, "e") 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))) thread.start_new_thread(eval_thread, (sender, " ".join(args)))
return None
@simplecommand("tempadd",
usage = "<user> <group> [duration]",
description = "Temporarily adds <user> to <group> for \n[duration] minutes. Defaults to 1 week.",
helpNoargs = True,
helpSubcmd = True,
amin = 2,
amax = 3)
def tempadd_command(sender, command, label, args):
if not sender.hasPermission("permissions.manage.membership." + args[1]):
return "&cYou do not have permission to manage that group!"
if len(args) == 3:
if not args[2].isdigit():
return "&cThats not a number!"
duration = int(args[2]) * 60
else: else:
noperm(sender) duration = 604800
return True if duration <= 0:
return "&cThats too short!"
cmd = "pex user %s group add %s * %s" % (args[0], args[1], duration)
runas(sender, cmd)
m, s = divmod(duration, 60)
h, m = divmod(m, 60)
d, h = divmod(h, 24)
return "&aAdded to group for %dd%dh%dm" % (d, h, m)
@hook.command("modules") @hook.command("modules")
def on_modules_command(sender, args): def on_modules_command(sender, command, label, args):
"""
/modules
list all modules, unloaded modules in red
"""
plugin_header(sender, "Modules") plugin_header(sender, "Modules")
for mod in shared["load_modules"]: msg(sender, ", ".join([(("&a" if mod in shared["modules"] else "&c") + mod) for mod in shared["load_modules"]]))
color = "a" if mod in shared["modules"] else "c"
msg(sender, "&" + color + mod)
@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):
msg = " ".split(event.getMessage())
if len(msg) < 3:
return
if msg[0].lower() not in ("/schematic", "/schem"):
return
if msg[1].lower() not in ("save", "load"):
return
msg[2] = event.getPlayer().getName() + "/" + msg[2]
"""
+2 -2
View File
@@ -5,13 +5,13 @@ default_motd = colorify(server.getMotd())
motd = default_motd motd = default_motd
@hook.command("getmotd") @hook.command("getmotd")
def on_getmotd_command(sender, args): def on_getmotd_command(sender, command, label, args):
plugin_header(sender, "MOTD") plugin_header(sender, "MOTD")
msg(sender, motd, usecolor = False) msg(sender, motd, usecolor = False)
@hook.command("setmotd") @hook.command("setmotd")
def on_setmotd_command(sender, args): def on_setmotd_command(sender, command, label, args):
global motd global motd
if sender.hasPermission("utils.setmotd"): if sender.hasPermission("utils.setmotd"):
if not checkargs(sender, args, 1, -1): if not checkargs(sender, args, 1, -1):
+5
View File
@@ -1,4 +1,9 @@
#pylint: disable = F0401 #pylint: disable = F0401
"""
A library that makes use of the so called ClassPathHack for jython
to allow proper loading of mysql-connector.jar at runtime.
Import only, no methods.
"""
import java.lang.reflect.Method import java.lang.reflect.Method
import java.io.File import java.io.File
import java.net.URL import java.net.URL
Executable
+37
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])
+29
View File
@@ -0,0 +1,29 @@
from helpers import *
py_players = []
class py_player:
def __init__(self,player):
self.player = player
self.logging_in = False
self.login_time = 0
def get_py_player(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","lowest")
def on_join(event):
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):
py_players.remove(get_py_player(event.getPlayer()))
+192
View File
@@ -0,0 +1,192 @@
from helpers import *
import org.bukkit.entity.Player as Base_player
import blockplacemods as blockmods
import snowbrawl
import loginsecurity as login
import calc
import chatgroups as cg
import adminchat as ac
import cycle
import forcefield as ff
import imout
import mentio
import pmtoggle
get_info_perm = "utils.playermanager.info"
players = []
###############################################################
# Outside-accessible functions
def get_player(name):
for player in players:
if player.get_name() == name:
return player
return None
##############################################################
# Events
@hook.event("player.PlayerQuitEvent", "highest")
def on_quit(event):
for i in range(len(players)):
if players[i].get_uuid() == uid(event.getPlayer()):
players.remove(players[i])
return
@hook.event("player.PlayerJoinEvent", "highest")
def on_join(event):
players.append(Player(event.getPlayer()))
#############################################################
# Commands
def send(sender, name, data):
if isinstance(data, bool):
if data == True:
msg(sender, "&e-&a %s&e:&a True" % name)
else:
msg(sender, "&e-&a %s&e:&c False" % name)
else:
msg(sender, "&e-&a %s&e:&6 %s" % (name, str(data)))
def send_header(sender, name):
msg(sender, "&e- &2 %s&e:" % name.upper())
def print_info(sender, player):
send_header(sender, "general")
send(sender, "Name", player.get_name())
send(sender, "UUID", player.get_uuid())
send(sender, "Logged in", player.logged_in())
send_header(sender, "snowbrawl")
send(sender, "In arena", player.in_sb_arena())
send(sender, "Arena", player.get_sb_arena())
send_header(sender, "place-mods")
send(sender, "Slab flip", player.has_autoflip_slab())
send(sender, "Cauldron fill", player.has_autofill_cauldron())
send(sender, "Piston face", player.has_autoface_piston())
send_header(sender, "chat groups")
send(sender, "In chatgroup", player.in_cg())
send(sender, "Chatgroup", player.get_cg())
send(sender, "Key", player.get_cg_key())
send(sender, "Toggle", player.has_cg_toggle())
send_header(sender, "Admin chat")
send(sender, "In adminchat", player.in_ac())
send(sender, "Key", player.get_ac_key())
send(sender, "Toggle", player.has_ac_toggle())
send_header(sender, "forcefield")
send(sender, "Whitelist", "&e, &6".join(player.get_ff_whitelist()))
send(sender, "Toggle", player.has_ff_toggle())
send_header(sender, "miscellaneous")
send(sender, "Calc", player.has_calc())
send(sender, "PM toggle", player.has_pm_toggle())
send(sender, "Cycle toggle", player.has_cycle())
send(sender, "Imout toggle", player.has_imout_toggle())
send(sender, "Mentio", "&e, &6".join(player.get_mentio_list()))
@hook.command("getinfo")
def on_command(sender, cmd, label, args):
if sender.hasPermission(get_info_perm):
if len(args) != 1:
msg(sender, "&e-&a /getinfo <name>")
else:
player = get_player(args[0])
if player != None:
print_info(sender, player)
else:
msg(sender, "&e-&c Player not online or does not exist")
else:
noperm(sender)
return True
#############################################################
# Player class
class Player():
def __init__(self, player):
self.player = player
def get_java_player(self):
return self.player
def get_uuid(self):
return uid(self.player)
def get_name(self):
return self.get_java_player().getName()
def get_display_name(self):
return self.get_java_player().getDisplayName()
def in_sb_arena(self):
for arena in snowbrawl.arenas:
if arena.in_players(self.get_java_player()):
return True
return False
def get_sb_arena(self):
for arena in snowbrawl.arenas:
if arena.in_players(self.get_java_player()):
return arena
return None
def logged_in(self):
return self.get_name() not in login.logging_in
def has_autoflip_slab(self):
return blockmods.isEnabled("slab", self.get_uuid())
def has_autofill_cauldron(self):
return blockmods.isEnabled("cauldron", self.get_uuid())
def has_autoface_piston(self):
return blockmods.isEnabled("piston", self.get_uuid())
def has_calc(self):
return self.get_uuid() in calc.calc_users
def in_cg(self):
return self.get_uuid() in cg.groups.keys()
def get_cg(self):
if self.in_cg():
return cg.groups[self.get_uuid()]
else:
return None
def get_cg_key(self):
return cg.get_key(self.get_uuid())
def has_cg_toggle(self):
return self.get_uuid() in cg.cg_toggle_list
def in_ac(self):
return self.get_java_player().hasPermission(ac.ac_permission)
def get_ac_key(self):
return ac.get_key(self.get_uuid())
def has_ac_toggle(self):
return self.get_name() in ac.ac_toggle_list
def has_cycle(self):
return self.get_uuid() not in cycle.no_cyclers
def has_ff_toggle(self):
return self.get_uuid() in ff.ff_users
def get_ff_whitelist(self):
return ff.whitelists.get(self.get_uuid(), [])
def has_imout_toggle(self):
return self.get_name() in imout.imout_toggle_list
def get_mentio_list(self):
return mentio.get_keywords(self.get_java_player())
def has_pm_toggle(self):
return self.get_uuid() in pmtoggle.toggle_dict
+4 -2
View File
@@ -1,7 +1,9 @@
#!/usr/bin/python #!/usr/bin/python
# this was going to be a PlotMe-like plugin "plotter" """
# but it seems like PlotMe is still beeing developed, so we don't need our own. *Very basic* start of a custom plot-plugin like PlotMe
on hold because the PlotMe developer continued to develop PlotMe
"""
import sys import sys
+1 -1
View File
@@ -1,4 +1,4 @@
name: RedstonerUtils name: RedstonerUtils
main: main.py main: main.py
version: 3.0.0 version: 3.1.0
author: redstone_sheep author: redstone_sheep
+57
View File
@@ -0,0 +1,57 @@
from helpers import *
import org.bukkit.Bukkit as Bukkit
from java.util.UUID import fromString as juuid
toggle_dict = {}
permission = "utils.pmtoggle"
@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)
return True
plugin_header(sender, "Private Message Toggle")
uuid = uid(sender)
if len(args) > 0:
if len(args) > 1:
msg(sender, "&cToo many arguments!")
return True
target = Bukkit.getPlayer(args[0])
if target:
toggle_dict[uuid] = uid(target)
msg(sender, "&2Enabled toggle so that you're now sending only to %s &2by default" % target.getDisplayName())
else:
msg(sender, "&cThat player could not be found")
elif uuid in toggle_dict:
del toggle_dict[uuid]
msg(sender, "&2Disabled toggle successfully")
else:
msg(sender, "&cExpected a player as argument")
return True
@hook.event("player.AsyncPlayerChatEvent", "normal")
def on_chat(event):
if event.isCancelled():
return
player = event.getPlayer()
uuid = uid(player)
if uuid in toggle_dict:
event.setCancelled(True)
target = Bukkit.getPlayer(juuid(toggle_dict[uuid])).getName()
runas(player, "msg %s %s" % (target, event.getMessage()))
@hook.event("player.PlayerQuitEvent", "normal")
def on_quit(event):
uuid = uid(event.getPlayer())
if uuid in toggle_dict:
del toggle_dict[uuid]
for pid in list(toggle_dict):
if toggle_dict[pid] == uuid:
del toggle_dict[pid]
msg(Bukkit.getPlayer(juuid(pid)), "%s &cwent off so your Private Message Toggle has been disabled!" % Bukkit.getPlayer(juuid(uuid)).getDisplayName())
+129
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
+88 -27
View File
@@ -2,6 +2,7 @@ from helpers import *
from java.util.UUID import fromString as juuid from java.util.UUID import fromString as juuid
import time import time
import thread import thread
from traceback import format_exc as trace
time_format = "%Y.%m.%d %H:%M" time_format = "%Y.%m.%d %H:%M"
@@ -13,42 +14,83 @@ rp_permission = "utils.rp"
def print_help(sender): def print_help(sender):
msg(sender, " &2/report <text> &eReport something") msg(sender, " &2/report <text> &eReport something")
msg(sender, " &2/rp list &eList unresolved reports (id, player, text)") msg(sender, " &2/rp open &eList open reports (id, player, text)")
msg(sender, " &2/rp closed &eList closed reports (id, player, text)")
msg(sender, " &2/rp tp <id> &eTeleport to report's location & show details") msg(sender, " &2/rp tp <id> &eTeleport to report's location & show details")
msg(sender, " &2/rp del <id> &eResolve a report") msg(sender, " &2/rp close <id> &eResolve an open report")
msg(sender, " &2/rp reopen <id> &eReopen a resolved report")
msg(sender, " &2/rp del <id> &eDelete a report (admin only)")
def print_list(sender): def print_list(sender, closed):
try: # new thread, anything can happen. try: # new thread, anything can happen.
msg(sender, "&a" + str(len(reports)) + " reports:") targeted_reports = dict(enumerate(reports))
for i, report in enumerate(reports): for i in list(targeted_reports):
name = server.getOfflinePlayer(juuid(report["uuid"])).getName() report = targeted_reports[i]
msg(sender, "&8[&e%s&c%s&8] &3%s&f: &a%s" % (i, report["time"], name, report["msg"])) if report["closed"] != closed:
targeted_reports.pop(i)
msg(sender, "&a%s %s reports:" % (len(targeted_reports), "closed" if closed else "open"))
for i in targeted_reports:
report = targeted_reports[i]
name = retrieve_player(report["uuid"]).getName()
msg(sender, "&8[&e%s &c%s&8] &3%s&f: &a%s" % (i, report["time"], name, report["msg"]))
except: except:
warn("Failed to complete report's print_list() thread") warn("Failed to complete report's print_list() thread")
error(trace())
def tp_report(sender, rep_id): def tp_report(sender, rep_id):
if rep_id >= len(reports) or rep_id < 0: if rep_id >= len(reports) or rep_id < 0:
msg(sender, "&cReport &3#" + str(rep_id) + "&c does not exist!") msg(sender, "&cReport &3#" + str(rep_id) + "&c does not exist!")
return True
else: else:
report = reports[rep_id] report = reports[rep_id]
safetp(sender, server.getWorld(report["world"]), report["x"], report["y"], report["z"], report["yaw"], report["pitch"]) safetp(sender, server.getWorld(report["world"]), report["x"], report["y"], report["z"], report["yaw"], report["pitch"])
msg(sender, "&aTeleported to report #%s" % rep_id ) msg(sender, "&aTeleported to %s&areport #%s" % ("&cclosed " if report["closed"] else "", rep_id))
# resolve == True: You're resolving, False: reopening
def resolve_reopen_report(sender, rep_id, resolve):
action = "resolved" if resolve else "reopened"
report = edit_report(sender, rep_id)
if report != None:
if report["closed"] == resolve:
msg(sender, "&cReport &3#%s&c was already %s!" % (rep_id, action))
else:
report["closed"] = resolve
save_reports()
msg(sender, "&aReport #%s %s" % (rep_id, action))
message_reporter(sender, report, action)
def delete_report(sender, rep_id): def delete_report(sender, rep_id):
if len(reports) > rep_id >= 0: if not sender.hasPermission(rp_permission + ".del"):
report = reports[rep_id] noperm(sender)
reports.pop(rep_id) return
action = "&cdeleted"
report = edit_report(sender, rep_id)
if report != None:
reports.remove(report)
save_reports() save_reports()
msg(sender, "&aReport #%s deleted." % rep_id) msg(sender, "&aReport #%s %s" % (rep_id, action))
reporter = server.getOfflinePlayer(juuid(report["uuid"])) message_reporter(sender, report, action)
plugin_header(reporter, "Report")
msg(reporter, "&aReport '&e%s&a' was resolved by %s." % (report["msg"], sender.getName()))
else: def edit_report(sender, rep_id):
if len(reports) > rep_id >= 0:
return reports[rep_id]
msg(sender, "&cThat report does not exist!") msg(sender, "&cThat report does not exist!")
return None
def message_reporter(sender, report, action):
reporter = get_reporter(report)
message = "&aReport '&e%s&a' was %s &aby %s." % (report["msg"], action, sender.getName())
if reporter.isOnline():
plugin_header(reporter, "Reports")
msg(reporter, message)
else:
server.dispatchCommand(sender, "mail send %s %s" % (reporter.getName(), colorify(message)))
def save_reports(): def save_reports():
@@ -56,13 +98,16 @@ def save_reports():
@hook.command("rp") @hook.command("rp")
def on_rp_command(sender, args): def on_rp_command(sender, command, label, args):
if sender.hasPermission(rp_permission): if sender.hasPermission(rp_permission):
plugin_header(sender, "Reports") plugin_header(sender, "Reports")
if len(args) > 0: if len(args) > 0:
if args[0] == "list": subcmd = args[0].lower()
if subcmd == "closed":
# needs to run in seperate thread because of getOfflinePlayer # needs to run in seperate thread because of getOfflinePlayer
thread.start_new_thread(print_list, (sender)) thread.start_new_thread(print_list, (sender, True,))
elif subcmd in ["open", "list"]:
thread.start_new_thread(print_list, (sender, False,))
else: else:
if not checkargs(sender, args, 2, 2): if not checkargs(sender, args, 2, 2):
return True return True
@@ -72,13 +117,17 @@ def on_rp_command(sender, args):
msg(sender, "&cDoesn't look like &3" + args[1] + "&c is a valid number!") msg(sender, "&cDoesn't look like &3" + args[1] + "&c is a valid number!")
print_help(sender) print_help(sender)
return True return True
if args[0] == "tp": if subcmd == "tp":
if not is_player(sender): if not is_player(sender):
msg(sender, "&conly players can do this") msg(sender, "&conly players can do this")
return True return True
tp_report(sender, repid) tp_report(sender, repid)
elif args[0] == "del": elif subcmd == "close":
resolve_reopen_report(sender, repid, True)
elif subcmd == "del":
delete_report(sender, repid) delete_report(sender, repid)
elif subcmd == "reopen":
resolve_reopen_report(sender, repid, False)
else: else:
print_help(sender) print_help(sender)
else: else:
@@ -89,7 +138,7 @@ def on_rp_command(sender, args):
@hook.command("report") @hook.command("report")
def on_report_command(sender, args): def on_report_command(sender, command, label, args):
plugin_header(sender, "Report") plugin_header(sender, "Report")
if not is_player(sender): if not is_player(sender):
msg(sender, "&conly players can do this") msg(sender, "&conly players can do this")
@@ -109,7 +158,8 @@ def on_report_command(sender, args):
"yaw": int(loc.yaw), "yaw": int(loc.yaw),
"pitch": int(loc.pitch), "pitch": int(loc.pitch),
"world": loc.getWorld().name, "world": loc.getWorld().name,
"time": time.strftime(time_format) "time": time.strftime(time_format),
"closed": False
} }
reports.append(report) reports.append(report)
save_reports() save_reports()
@@ -125,9 +175,9 @@ def reports_reminder(): # needs 2 args for unknown reason
if not check_reports: if not check_reports:
info("Reports reminder thread killed.") info("Reports reminder thread killed.")
thread.exit() thread.exit()
if len(reports) > 0: targeted_reports = get_reports(False)
broadcast(rp_permission, "&2--=[ Reports ]=--") if len(targeted_reports) > 0:
broadcast(rp_permission, "&aThere are %s pending reports!" % len(reports)) broadcast(rp_permission, "&aThere are %s open reports!" % len(targeted_reports))
def stop_reporting(): def stop_reporting():
@@ -136,4 +186,15 @@ def stop_reporting():
check_reports = False check_reports = False
def get_reports(closed):
targeted_reports = []
for report in reports:
if report["closed"] == closed:
targeted_reports.append(report)
return targeted_reports
def get_reporter(report):
return server.getOfflinePlayer(juuid(report["uuid"]))
thread.start_new_thread(reports_reminder, ()) thread.start_new_thread(reports_reminder, ())
+3 -4
View File
@@ -30,10 +30,8 @@ def print_lol(sender, lid):
broadcast(None, "&8[&blol&8] &7%s&8: &e%s" % (dispname, lols[lid])) broadcast(None, "&8[&blol&8] &7%s&8: &e%s" % (dispname, lols[lid]))
last_msg = time() last_msg = time()
else: else:
plugin_header(sender, "SayLol")
msg(sender, "&cInvalid id") msg(sender, "&cInvalid id")
else: else:
plugin_header(sender, "SayLol")
msg(sender, "&cYou can use SayLol again in &a%s seconds!" % int(timeout + 1 - (time() - last_msg))) msg(sender, "&cYou can use SayLol again in &a%s seconds!" % int(timeout + 1 - (time() - last_msg)))
@@ -41,15 +39,16 @@ def search_lols(sender, keyword):
if not keyword: if not keyword:
msg(sender, "&cPlease provide a keyword to search for!") msg(sender, "&cPlease provide a keyword to search for!")
return return
keyword = keyword.lower()
msg(sender, "&aLols containing '&6%s&a':" % keyword) msg(sender, "&aLols containing '&6%s&a':" % keyword)
for i, lol in enumerate(lols): for i, lol in enumerate(lols):
if keyword in lol: if keyword in lol.lower():
msg(sender, "&a%s: &e%s" % (str(i).rjust(3), lol)) msg(sender, "&a%s: &e%s" % (str(i).rjust(3), lol))
msg(sender, "") # empty line showing end of list msg(sender, "") # empty line showing end of list
@hook.command("lol") @hook.command("lol")
def on_lol_command(sender, args): def on_lol_command(sender, command, label, args):
plugin_header(sender, "SayLol") plugin_header(sender, "SayLol")
cmd = args[0] if len(args) > 0 else None cmd = args[0] if len(args) > 0 else None
+212
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)
+3
View File
@@ -0,0 +1,3 @@
mysql_database = "jdbc:mysql://localhost/database"
mysql_user = "username"
mysql_pass = "secret"
+115
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)
+297
View File
@@ -0,0 +1,297 @@
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
blocked_cmds = tuple(shared["modules"]["misc"].sudo_blacklist) + ("pex", "kick", "ban", "tempban", "reload", "op", "deop", "whitelist")
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)
signs = load_signs() # {("world", x, y, z): ["owner_id", "msg1", "msg2"]}
lines = {} # Accumulated messages so players can have longer messages: {"Dico200": "Message...........", ""}
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
@simplecommand(cmd = "serversigns", aliases = ["svs", "signmsg"],
description = "Makes something happen when you right click signs. \nUse /svs help for more details.",
usage = "<claim|reset|add <msg>[++]|remove <ID>|clear|info|help>",
helpNoargs = True,
senderLimit = 0)
def svs_command(sender, command, label, args):
arg1 = args[0].lower()
Validate.isTrue(arg1 in ("claim", "reset", "add", "remove", "info", "clear", "help", "switch", "reverse", "unclaim"),
signsMsg("That argument could not be recognized, use &o/svs help &4for expected arguments"))
Validate.isAuthorized(sender, "utils.serversigns." + arg1)
#-------------------- Sub commands that don't require any conditions -----------------------
if arg1 == "help":
admin = sender.hasPermission("utils.serversigns.admin")
msg = signsMsg("Server signs lets you add messages to a sign.", 'a')
msg += "\nRight clicking the sign will display all the messages. Commands"
msg += "\ncan also be added, by prefixing the message with a '/'."
msg += "\nHow to use &b/serversigns&a:"
msg += "\n&b/svs claim" + ("" if not sender.hasPermission("utils.serversigns.admin") else " [owner]")
msg += "\n&a- Claims the sign so that you can add messages to it"
msg += "\n&b/svs info"
msg += "\n&a- Displays information about the (claimed) sign"
msg += "\n&b/svs add <message>[++]"
msg += "\n&a- Adds the message to the sign. Use ++ at the end"
msg += "\n&a- to add the message to your buffer. You can then use"
msg += "\n&a- the same command again to create a longer message."
msg += "\n&b/svs remove <message ID>"
msg += "\n&a- Removes the message with the given ID from the sign."
msg += "\n&a- The ID is given before each message by &b/svs info&a."
msg += "\n&b/svs switch|reverse <message ID 1> <message ID 2>"
msg += "\n&a- Reverses the order in which the given messages are shown."
msg += "\n&b/svs clear"
msg += "\n&a- Removes all messages from the sign."
msg += "\n&b/svs reset|unclaim"
msg += "\n&a- Resets the sign, removing all messages and its owner."
return msg
#-------------------------------------------------------------------------------------------
block = sender.getTargetBlock(None, 5)
Validate.isTrue(block.getType() in (Material.SIGN_POST, Material.WALL_SIGN), signsMsg("You have to be looking at a sign to use that!"))
loc = fromLoc(block.getLocation())
sign = getSign(loc)
signName = identifySign(loc)
arg2 = args[1].lower() if len(args) > 1 else None
#------------------------ Sub commands that require the block to be a sign -------------------------------
if arg1 == "claim":
Validate.isTrue(not sign, signsMsg("The %s was already claimed" % signName))
Validate.isTrue(can_build2(sender, block), signsMsg("You are not permitted to claim signs here"))
target = sender
if arg2:
Validate.isTrue(player.hasPermission("utils.serversigns.admin"), signsMsg("You are not authorized to claim signs for other players"))
target = server.getOfflinePlayer(arg2)
Validate.notNone(target, signsMsg("That player could not be found"))
Validate.isTrue(target.isOnline(), signsMsg("The target has to be online"))
uuid = uid(target)
if sign != None:
if sign[0] == uuid:
return signsMsg("The" + signName + " was already owned by that player")
else:
sign[0] = uuid
else:
signs[loc] = [uuid]
save_signs()
return signsMsg("Claimed the " + signName + ((" for %s" % target.getName()) if (target != sender) else ""), 'a')
#----------------------------------------------------------------------------------------------------------
Validate.notNone(sign, signsMsg("The %s has not been claimed" % signName))
#----------------------Sub commands that require the sign to be claimed as well------------------------------------
if arg1 == "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 arg1 == "add":
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] = ""
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(line[0] != "/" or line.split(" ")[0][1:] not in blocked_cmds, signsMsg("Usage of that command with server signs is prohibited"))
sign.append(colorify(line) if line[0] != "/" else line)
save_signs()
return signsMsg("Added line \"&f%s&a\" to the %s" % (line, signName), 'a')
if arg1 == "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 arg1 in ("switch", "reverse"):
Validate.isTrue(len(args) == 3, signsMsg("You have to enter the 2 IDs of the messages to reverse"))
try:
id1 = int(args[1])
id2 = int(args[2])
except:
return signsMsg("The ID of the message has to be a number and can be found by using &o/svs info")
for id in (id1, id2):
Validate.isTrue(id != 0 and id < len(sign), signsMsg("The %s has no message with an ID of %s, use &o/svs info &4for all messages." % (signName, id)))
sign[id1], sign[id2] = sign[id2], sign[id1]
save_signs()
return signsMsg("Reversed the messages with IDs %s and %s of the %s" % (id1, id2, signName), 'a')
if arg1 == "clear":
signs[loc] = [sign[0]]
save_signs()
return signsMsg("Removed all messages from the %s" % signName, 'a')
if arg1 in ("reset", "unclaim"):
del signs[loc]
save_signs()
return signsMsg("Removed all messages and the owner from the %s, it can now be claimed" % signName, 'a')
#-------------------------------------------------------------------------------------------------------
@hook.event("player.PlayerInteractEvent")
def on_click(event):
if str(event.getAction()) != "RIGHT_CLICK_BLOCK":
return
block = event.getClickedBlock()
if block.getType() not in (Material.WALL_SIGN, Material.SIGN_POST):
return
sign = getSign(fromLoc(block.getLocation()))
if sign != None:
player = event.getPlayer()
for message in sign[1:]:
if message[:1] == "/":
server.dispatchCommand(player, message[1:])
else:
msg(player, message, usecolor = False)
# ---------------------------Sign breaking--------------------------------
checking_block = False
faces = {
BlockFace.NORTH : (0,1,2,),
BlockFace.SOUTH : (3,),
BlockFace.WEST : (4,),
BlockFace.EAST : (5,),
}
@hook.event("block.BlockBreakEvent", "monitor")
def on_break(event):
try:
global checking_block
if checking_block or event.isCancelled():
return
block = event.getBlock()
if block.getType() in (Material.SIGN_POST, Material.WALL_SIGN):
check_sign(event, block, attached = False)
for block_face, data_values in faces.iteritems():
block2 = block.getRelative(block_face)
if block2.getType() == Material.WALL_SIGN and block2.getData() in data_values:
check_sign(event, block2)
block3 = block.getRelative(BlockFace.UP)
if block3.getType() == Material.SIGN_POST:
check_sign(event, block3)
except:
error(trace())
def check_sign(event, block, attached = True):
player = event.getPlayer()
sign = getSign(fromLoc(block.getLocation()))
if not can_build2(player, block):
event.setCancelled(True)
msg(event.getPlayer(), signsMsg("You cannot break %s" % ("the sign attached to that block" if attached else "that sign")))
else:
loc = fromLoc(block.getLocation())
del signs[loc]
save_signs()
msg(player, signsMsg("Reset the %s which you just broke" % identifySign(loc)))
def can_build2(player, block):
global checking_block
event = BlockBreakEvent(block, player)
checking_block = True
server.getPluginManager().callEvent(event)
checking_block = False
return not event.isCancelled()
Executable
+175
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
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)
+969
View File
@@ -0,0 +1,969 @@
#Snowbrawl
from helpers import *
import time, threading, copy
import org.bukkit.inventory.ItemStack as ItemStack
import org.bukkit.Material as Material
import org.bukkit.potion.PotionEffect as PotionEffect
import org.bukkit.potion.PotionEffectType as PotionEffectType
from java.lang import Runnable
from java.util.UUID import fromString as juuid
from operator import __contains__
from traceback import format_exc as trace
import random
from synchronize import make_synchronized
#file names
file = "snowbrawl"
#permissions
list_perm = "utils.snowbrawl.list"
modify_perm = "utils.snowbrawl.modify"
teleport_perm = "utils.snowbrawl.tp"
create_perm = "utils.snowbrawl.create"
info_perm = "utils.snowbrawl.info"
join_perm = "utils.snowbrawl.join"
quit_perm = "utils.snowbrawl.quit"
#commands - tp command does not exist
list_command = "list"
del_command = "del"
set_command = "set"
name_command = "name"
pos_command = "pos"
create_command = "create"
info_command = "info"
modify_command = "modify"
modify_command_alias = "m"
quit_command = "quit"
class Arena(object):
def __init__(self, name):
self.queue = Queue()
self.name = name
self.refill = None
self.player_limit = None
self.start_time = None
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 = []
self.respawn_location = []
self.sign_location = []
self.sign_click = []
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
#set corners of arena
def set_corner(self, sender, type):
loc = sender.getLocation()
if type == "1":
self.corner1 = Coords(loc)
elif type == "2":
self.corner2 = Coords(loc)
msg(sender, "&a-&e Arena corner %s set" % type)
self.update_corner_points()
#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
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)
#add sign to sign list
def add_sign(self, sender, name):
mats = set()
mats = None
block = sender.getTargetBlock(mats, 3).getState()
if isinstance(block, bukkit.block.Sign):
self.sign_click.append(NamedCoords(name, Coords(block.getLocation())))
msg(sender, "&a-&e Arena tp sign %s created and set" % name)
#Delete a sign from the sign list
def del_sign(self, sender, name):
for sign in self.sign_click:
if sign.get_name() == name:
self.sign_click.remove(sign)
msg(sender, "&a-&e Arena tp sign %s removed" % sign.get_name())
return
msg(sender, "&a-&e Arena tp sign with this name doesn't exist")
#Adds a player to the queue if they aren't already there.
def add_player(self, player):
if not self.queue.contains(player):
self.queue.put(player)
self.start_match()
return True
return False
#remove a player from the queue
def remove_player(self, player):
if self.queue.contains(player):
self.queue.remove(player)
return True
return False
#return true if loc is inside the arena boundries
def in_arena(self, loc):
if self.tpp == None or self.bnn == None:
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:
return False
if loc.x > loc_tpp.x:
return False
if loc.x < loc_bnn.x:
return False
if loc.z > loc_tpp.z:
return False
if loc.z < loc_bnn.z:
return False
return True
def get_respawn(self):
id = random.randint(0, len(self.respawn_location) - 1)
return self.respawn_location[id]
def spawn_player(self, player):
id = random.randint(0, len(self.spawn_location) - 1)
loc = self.spawn_location[id].get_location().get_location()
safetp(player, loc.getWorld(), loc.x, loc.y, loc.z, loc.yaw, loc.pitch)
#Start match
def start_match(self):
if self.player_limit == None or self.match_goal == None or self.arena_type == None or len(self.spawn_location) == 0 or len(self.respawn_location) == 0 or len(self.sign_location) == 0:
return
if len(self.queue.read()) >= self.player_limit and len(self.players.read()) == 0:
self.start_time = time.time()
for i in range(self.player_limit):
player = self.queue.get()
self.players.put(player)
for player in self.players.read():
self.player_stats[player.getName() + "_deaths"] = 0
self.spawn_player(player)
msg(player, "&6The match has started!")
def bubbleSort(self, alist):
for passnum in range(len(alist)-1,0,-1):
for i in range(passnum):
if self.player_stats[alist[i].getName()+"_deaths"]>self.player_stats[alist[i+1].getName()+"_deaths"]:
temp = alist[i]
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()
safetp(player, loc.getWorld(), loc.x, loc.y, loc.z, loc.yaw, loc.pitch)
msg(player, "&6================= Match over =================")
msg(player, "&c&c")
if not len(sorted_list) < 1:
msg(player, "&e1. %s (%s)" % (sorted_list[0].getName(), self.player_stats[sorted_list[0].getName()+"_deaths"]))
if not len(sorted_list) < 2:
msg(player, "&e2. %s (%s)" % (sorted_list[1].getName(), self.player_stats[sorted_list[1].getName()+"_deaths"]))
if not len(sorted_list) < 3:
msg(player, "&e3. %s (%s)" % (sorted_list[2].getName(), self.player_stats[sorted_list[2].getName()+"_deaths"]))
msg(player, "&c&c")
msg(player, "&e Your deaths:&6 %s" % str(self.player_stats[player.getName() + "_deaths"]))
msg(player, "&c&c")
msg(player, "&6==============================================")
self.players.clear()
self.player_stats = {}
self.start_match()
def check_deaths(self):
if self.arena_type == "death":
for player in self.players.read():
if self.player_stats[player.getName() + "_deaths"] >= self.match_goal:
return True
return False
def is_running(self):
if len(self.players.read()) == 0:
return False
return True
def set_explosion_damage(self, dmg):
self.explosion_damage = dmg
def get_explosion_damage(self):
if self.explosion_damage == None:
return 1
return self.explosion_damage
def in_players(self, player):
return self.players.contains(player)
def set_player_limit(self, limit):
self.player_limit = limit
def set_end_goal(self, value):
self.match_goal = value
def set_type(self, type):
self.arena_type = type
def get_name(self):
return self.name
def set_refill(self, amount):
self.refill = int(amount)
def set_name(self, name):
self.name = name
def get_refill(self):
if self.refill == None:
return 16
return self.refill
def get_tp_signs(self):
return self.sign_location
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):
return True
return False
#Returns queue contents in list. use "".join(queue) to get a string
def get_queue_contents(self):
return self.queue.read()
#Returns queue object
def get_queue(self):
return self.queue
#Returns list of location objects of type, type.
def get_location(self, type):
if type == "spawn":
return self.spawn_location
elif type == "respawn":
return self.respawn_location
elif type == "sign":
return self.sign_location
#Add a location to list of type location
def add_location(self, name, location, type):
named_loc = NamedCoords(name, Coords(location))
if type == "spawn":
self.spawn_location.append(named_loc)
elif type == "respawn":
self.respawn_location.append(named_loc)
elif type == "sign":
self.sign_location.append(named_loc)
#Change location of location of type, type
def change_location(self, name, location, type):
if type == "spawn":
for spawn in self.spawn_location:
if spawn.get_name() == name:
spawn.get_location().set_location(location)
break
elif type == "respawn":
for respawn in self.respawn_location:
if respawn.get_name() == name:
respawn.get_location().set_location(location)
break
elif type == "sign":
for sign in self.sign_location:
if sign.get_name() == name:
sign.get_location().set_location(location)
break
#Remove location out of location
def delete_location(self, name, type):
if type == "spawn":
for spawn in self.spawn_location[:]:
if spawn.get_name() == name:
self.spawn_location.remove(spawn)
break
elif type == "respawn":
for respawn in self.respawn_location[:]:
if respawn.get_name() == name:
self.respawn_location.remove(respawn)
break
elif type == "sign":
for sign in self.sign_location[:]:
if sign.get_name() == name:
self.sign_location.remove(sign)
break
def get_data(self):
spawns = []
for spawn in self.spawn_location:
spawns.append(spawn.get_data())
respawns = []
for respawn in self.respawn_location:
respawns.append(respawn.get_data())
signs = []
for sign in self.sign_location:
signs.append(sign.get_data())
sign_clicks = []
for click in self.sign_click:
sign_clicks.append(click.get_data())
corners = []
corners.append(self.corner1.get_data() if not self.corner1 == None else None)
corners.append(self.corner2.get_data() if not self.corner2 == None else None)
corners.append(self.tpp.get_data() if not self.tpp == None else None)
corners.append(self.bnn.get_data() if not self.bnn == None else None)
data = {
"spawns": spawns,
"respawns": respawns,
"signs": signs,
"clicks": sign_clicks,
"corners": corners,
"explosion": self.explosion_damage,
"players": self.player_limit,
"refill": self.refill,
"type": self.arena_type,
"goal": self.match_goal,
"name": self.name
}
return data
def load(self, data):
self.explosion_damage = None if str(data["explosion"]) == "None" else float(data["explosion"])
self.player_limit = None if str(data["players"]) == "None" else int(data["players"])
self.refill = None if str(data["refill"]) == "None" else int(data["refill"])
self.arena_type = str(data["type"])
self.match_goal = None if str(data["goal"]) == "None" else int(data["goal"])
self.corner1 = Coords(None).load(data["corners"][0]) if not data["corners"][0] == None else None
self.corner2 = Coords(None).load(data["corners"][1]) if not data["corners"][1] == None else None
self.tpp = Coords(None).load(data["corners"][2]) if not data["corners"][2] == None else None
self.bnn = Coords(None).load(data["corners"][3]) if not data["corners"][3] == None else None
for subdata in data["spawns"]:
self.spawn_location.append(NamedCoords(None, None).load(subdata))
for subdata in data["respawns"]:
self.respawn_location.append(NamedCoords(None, None).load(subdata))
for subdata in data["signs"]:
self.sign_location.append(NamedCoords(None, None).load(subdata))
for subdata in data["clicks"]:
self.sign_click.append(NamedCoords(None, None).load(subdata))
self.name = data["name"]
return self
#coord = an instance of Coords class, adds a name to it.
class NamedCoords(object):
def __init__(self, name, coord):
self.name = name
self.coord = coord
def get_name(self):
return self.name
def get_location(self):
return self.coord
def get_data(self):
coords = self.coord.get_location()
data = {
"x": coords.x,
"y": coords.y,
"z": coords.z,
"yaw": coords.yaw,
"pitch": coords.pitch,
"world": coords.getWorld().getName(),
"name": self.name
}
return data
def load(self, data):
self.name = str(data["name"])
self.coord = Coords(None).load(data)
return self
class Coords(object):
def __init__(self, world = None, x = None, y = None, z = None, yaw = None, pitch = None):
if world == None:
self.world = None
self.x = None
self.y = None
self.z = None
self.yaw = None
self.pitch = None
return
if not isinstance(world, Location):
self.x = x
self.y = y
self.z = z
self.yaw = yaw
self.pitch = pitch
self.world = world.getName()
else:
location = world
self.x = location.x
self.y = location.y
self.z = location.z
self.yaw = location.yaw
self.pitch = location.pitch
self.world = location.getWorld().getName()
def get_location(self):
return Location(server.getWorld(str(self.world)), float(self.x), float(self.y), float(self.z), int(self.yaw), int(self.pitch))
def set_location(self, location):
self.x = location.x
self.y = location.y
self.z = location.z
self.yaw = location.yaw
self.pitch = location.pitch
self.world = location.getWorld().getName()
def get_data(self):
data = {
"x": self.x,
"y": self.y,
"z": self.z,
"yaw": self.yaw,
"pitch": self.pitch,
"world": self.world
}
return data
def load(self, data):
self.x = float(data["x"])
self.y = float(data["y"])
self.z = float(data["z"])
self.yaw = int(data["yaw"])
self.pitch = int(data["pitch"])
self.world = str(data["world"])
return self
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
#Returns the queue's list object
def read(self):
return self.queue
#Removes the value args from the queue
def remove(self,args):
self.queue.remove(args)
#Check if queue contains player
def contains(self, player):
if player in self.queue:
return True
return False
#Clear the queue
def clear(self):
self.queue = []
##############################################################################################
# Initialization
##############################################################################################
def save_snowbrawl():
out = []
for arena in arenas:
out.append(arena.get_data())
save_json_file(file, out)
def load_snowbrawl():
out = []
buffer = open_json_file(file, [])
for data in buffer:
out.append(Arena(None).load(data))
return out
arenas = load_snowbrawl()
##############################################################################################
# Threads
##############################################################################################
class timings_runnable(Runnable):
def __init__(self, arena):
self.arena = arena
def run(self):
self.arena.end_match()
#timings thread to end arenas if their type is time
def timings():
while True:
for arena in arenas:
if arena.is_running():
if arena.arena_type == "time":
current_time = time.time()
start_time = arena.start_time
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()
##############################################################################################
# Events
##############################################################################################
@hook.event("player.PlayerMoveEvent", "low")
def onMove(event):
if event.getPlayer().getWorld().getName() != "minigames":
return
player = event.getPlayer()
for arena in arenas:
if arena.in_players(player):
loc = player.getLocation()
block = player.getWorld().getBlockAt(int(loc.x), int(loc.y) - 1, int(loc.z))
if block != None:
material = block.getType()
if material == Material.SPONGE:
player.addPotionEffect(PotionEffect(PotionEffectType.JUMP, 60, 0))
elif material == Material.GLASS or material == Material.STAINED_GLASS:
player.addPotionEffect(PotionEffect(PotionEffectType.SPEED, 60, 0))
elif material == Material.OBSIDIAN:
player.addPotionEffect(PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 300, 0))
break
@hook.event("entity.PlayerDeathEvent", "high")
def onDeath(event):
if event.getEntity().getWorld().getName() != "minigames":
return
if not isinstance(event.getEntity(), bukkit.entity.Player):
return
for arena in arenas:
if arena.in_players(event.getEntity()):
arena.player_stats[event.getEntity().getName() + "_deaths"] += 1
if arena.check_deaths():
arena.end_match()
break
@hook.event("player.PlayerRespawnEvent", "high")
def onRespawn(event):
if event.getPlayer().getWorld().getName() != "minigames":
return
player = event.getPlayer()
for arena in arenas:
if arena.in_players(player):
event.setRespawnLocation(arena.get_respawn().get_location().get_location())
break
@hook.event("entity.ProjectileHitEvent", "high")
def onHit(event):
if event.getEntity().getWorld().getName() != "minigames":
return
if event.getEntity().getName() != "Snowball":
return
location = event.getEntity().getLocation()
for arena in arenas:
if arena.in_arena(location):
event.getEntity().getWorld().createExplosion(location.x, location.y, location.z, float(arena.get_explosion_damage()), False, False)
break
@hook.event("player.PlayerInteractEvent", "high")
def onClick(event):
if event.getPlayer().getWorld().getName() != "minigames":
return
if str(event.getAction()) != "RIGHT_CLICK_BLOCK":
return
block = event.getClickedBlock().getState()
if event.getClickedBlock().getType() == Material.SNOW_BLOCK:
for arena in arenas:
if arena.in_players(event.getPlayer()):
inv = event.getPlayer().getInventory()
inv.remove(Material.SNOW_BALL)
inv.setItemInHand(ItemStack(Material.SNOW_BALL, arena.get_refill()))
event.getPlayer().updateInventory()
break
elif isinstance(block, bukkit.block.Sign):
line = str(block.getLine(1))
if not event.getPlayer().hasPermission(join_perm):
msg(event.getPlayer(), "&a-&e You don't have permission to join snowbrawl matches")
return
#go through arenas, if name matches line then add player to it
for arena in arenas:
if line == arena.get_name():
for sign in arena.get_click_signs():
sign_loc = sign.get_location().get_location()
loc = block.getLocation()
if sign_loc.getWorld().getName() == loc.getWorld().getName() and sign_loc.x == loc.x and sign_loc.y == loc.y and sign_loc.z == loc.z:
if arena.add_player(event.getPlayer()):
msg(event.getPlayer(),"&a- &eYou have been added to the queue")
else:
msg(event.getPlayer(),"&a- &eYou are already in the queue")
break
return
@hook.event("player.PlayerQuitEvent", "normal")
def on_quit(event):
#remove the player from the queue
player = event.getPlayer().getName()
for arena in arenas:
if arena.in_queue(player):
arena.remove_player(player)
##############################################################################################
# Command handling
##############################################################################################
def create_arena(sender, args):
if len(args) == 0:
msg(sender, "&c/sb %s <name>" % create_command)
return
arena = Arena(args[0])
arenas.append(arena)
msg(sender, "&a-&e Arena %s created" % args[0])
def list_arenas(sender):
if len(arenas) == 0:
msg(sender, "&a-&e There are currently no arenas")
return
for arena in arenas:
msg(sender, "&a-&e %s" % arena.get_name())
def arena_info(sender, args):
if len(args) == 0:
msg(sender, "&a-&e /sb info <name>")
return
if len(arenas) == 0:
msg(sender, "&a-&e There are currently no arenas")
return
for arena in arenas:
if arena.get_name() == args[0]:
msg(sender, "&a-&e %s" % arena.get_name())
#msg(sender, "&ePlayers:&6 " + "&e,&6 ".join(arena.get_queue_contents()))
spawn_list = []
for spawn in arena.get_location("spawn"):
spawn_list.append(spawn.get_name())
msg(sender, "&eSpawns:&6 " + "&e,&6 ".join(spawn_list))
respawn_list = []
for respawn in arena.get_location("respawn"):
respawn_list.append(respawn.get_name())
msg(sender, "&eRespawns:&6 " + "&e,&6 ".join(respawn_list))
sign_list = []
for sign in arena.get_location("sign"):
sign_list.append(sign.get_name())
msg(sender, "&eSigns:&6 " + "&e,&6 ".join(sign_list))
break
def quit_match(sender):
for arena in arenas:
if arena.in_queue(sender):
arena.remove_player(sender)
msg(sender, "&a-&e Quit arena")
return
msg(sender, "&a-&e You're not in a queue")
def print_help(sender):
msg(sender, "&a-&e Alias: &6/sb")
if sender.hasPermission(teleport_perm):
msg(sender, "&a-&e /sb <name> Teleport to an arena")
if sender.hasPermission(quit_perm):
msg(sender, "&a-&e /sb %s Quit a queue" % quit_command)
if sender.hasPermission(list_perm):
msg(sender, "&a-&e /sb %s List all existing arenas" % list_command)
if sender.hasPermission(create_perm):
msg(sender, "&a-&e /sb %s Create an arena" % create_command)
if sender.hasPermission(info_perm):
msg(sender, "&a-&e /sb %s Show info about an arena" % info_command)
if sender.hasPermission(modify_perm):
msg(sender, "&a-&e /sb %s Deletes an arena" % del_command)
msg(sender, "&a-&e /sb %s Sets a teleport for an arena to a sign" % set_command)
msg(sender, "&a-&e /sb %s Renames an arena" % name_command)
msg(sender, "&a-&e /sb %s Sets the locations for an arena" % pos_command)
msg(sender, "&a-&e /sb %s Modifies the arena" % modify_command)
msg(sender, "&a-&e Modify Aliases: &6/sbm&e,&6 /sb %s" % modify_command_alias)
def set_location(sender, args):
if len(args) < 3:
msg(sender, "&c/sb pos <arena name> respawn/spawn/sign set/add/del <name>")
msg(sender, "&c/sb pos <arena name> bounds corner1/corner2")
return
if "bounds" not in args:
if len(args) < 4:
msg(sender, "&c/sb pos <arena name> respawn/spawn/sign set/add/del <name>")
msg(sender, "&c/sb pos <arena name> bounds corner1/corner2")
return
if len(arenas) == 0:
msg(sender, "&a-&e There are currently no arenas")
return
for arena in arenas:
if arena.get_name() == args[0]:
if args[1] == "respawn":
set_location_of_type(sender, args[2:], "respawn", arena)
elif args[1] == "spawn":
set_location_of_type(sender, args[2:], "spawn", arena)
elif args[1] == "sign":
set_location_of_type(sender, args[2:], "sign", arena)
elif args[1] == "bounds":
set_location_of_type(sender, args[2:], "bounds", arena)
break
def set_location_of_type(sender, args, type, arena):
if len(args) == 0:
msg(sender, "&c/sb pos <arena name> respawn/spawn/sign set/add/del <name>")
msg(sender, "&c/sb pos <arena name> bounds corner1/corner2")
return
location = sender.getLocation()
if args[0] == "set":
arena.change_location(args[1], location, type)
msg(sender, "&a-&e Location of name %s and type %s changed to your current location" % (args[1], type))
elif args[0] == "add":
arena.add_location(args[1], location, type)
msg(sender, "&a-&e Location of name %s and type %s created at your current location" % (args[1], type))
elif args[0] == "del":
arena.delete_location(args[1], type)
msg(sender, "&a-&e Location of name %s deleted" % args[1])
elif args[0] == "corner1":
arena.set_corner(sender, "1")
elif args[0] == "corner2":
arena.set_corner(sender, "2")
def rename_arena(sender, args):
if len(args) < 2:
msg(sender, "&c/sb name <name> <new name>")
return
for arena in arenas:
if arena.get_name() == args[0]:
arena.set_name(args[1])
msg(sender, "&a-&e Arena %s renamed to %s" % (args[0], args[1]))
return
msg(sender, "&a-&e Arena with this name doesn't exist")
def delete_arena(sender, args):
if len(args) == 0:
msg(sender, "&c/sb del <name>")
return
for arena in arenas:
if arena.get_name() == args[0]:
arenas.remove(arena)
msg(sender, "&a-&e Arena %s deleted" % arena.get_name())
return
msg(sender, "&a-&e Arena with this name doesn't exist")
def teleport_to_arena(sender, name, id):
try:
int(id)
except ValueError:
msg(sender, "&c/sb <name> <id of teleport>")
return
for arena in arenas:
if arena.get_name() == name:
i = 0
if int(id) > len(arena.get_tp_signs()):
msg(sender, "&cGiven tp id is out of range")
return
for sign in arena.get_tp_signs():
i += 1
if i == int(id):
loc = sign.get_location().get_location()
safetp(sender, loc.getWorld(), loc.x, loc.y, loc.z, loc.yaw, loc.pitch)
break
msg(sender, "&a-&e Teleporting to arena %s" % name)
return
msg(sender, "&a-&e Arena with this name doesn't exist")
def modify_arena(sender, args):
if len(args) < 3:
msg(sender, "&c/sb modify <arena name> limit/mode/players/explosion/refill <amount/mode (death/time)>")
return
for arena in arenas:
if arena.get_name() == args[0]:
if args[1] == "limit":
try:
int(args[2])
except ValueError:
msg(sender, "&cLast parameter has to be a number")
return
arena.set_end_goal(int(args[2]))
msg(sender, "&a-&e Set time/death limit to:&6 %s" % int(args[2]))
elif args[1] == "mode":
if args[2] == "time" or args[2] == "death":
arena.set_type(args[2])
msg(sender, "&a-&e Set mode to:&6 %s" % args[2])
else:
msg(sender, "&cInvalid mode (time, death)")
elif args[1] == "players":
try:
int(args[2])
except ValueError:
msg(sender, "&cLast parameter has to be a number")
return
arena.set_player_limit(int(args[2]))
msg(sender, "&a-&e Set player limit to:&6 %s" % int(args[2]))
elif args[1] == "explosion":
try:
float(args[2])
except ValueError:
msg(sender, "&cLast parameter has to be a number")
return
arena.set_explosion_damage(float(args[2]))
msg(sender, "&a-&e Set explosion power to:&6 %s" % float(args[2]))
elif args[1] == "refill":
try:
int(args[2])
except ValueError:
msg(sender, "&cLast parameter has to be a number")
return
arena.set_refill(int(args[2]))
msg(sender, "&a-&e Set snowball refill to:&6 %s" % int(args[2]))
return
msg(sender, "&a-&e Arena with this name doesn't exist")
def set_arena_sign(sender, args):
if len(args) < 3:
msg(sender, "&c/sb set <arena name> add/del <name>")
return
for arena in arenas:
if arena.get_name() == args[0]:
if args[1] == "add":
arena.add_sign(sender, args[2])
elif args[1] == "del":
arena.del_sign(sender, args[2])
@hook.command("snowbrawl")
def on_snowbrawl_command(sender, command, label, args):
if len(args) == 0:
#print help
plugin_header(sender, "Snowbrawl")
print_help(sender)
return True
elif args[0] == list_command:
if sender.hasPermission(list_perm):
#print the list of arenas
list_arenas(sender)
else:
noperm(sender)
return True
elif args[0] == del_command:
if sender.hasPermission(modify_perm):
#delete an arena
delete_arena(sender, args[1:])
save_snowbrawl()
else:
noperm(sender)
return True
elif args[0] == info_command:
if sender.hasPermission(info_perm):
#print info about an arena
arena_info(sender, args[1:])
else:
noperm(sender)
return True
elif args[0] == create_command:
if sender.hasPermission(create_perm):
#create an arena
create_arena(sender, args[1:])
save_snowbrawl()
else:
noperm(sender)
return True
elif args[0] == pos_command:
if sender.hasPermission(modify_perm):
#set arena spawn/respawn/sign tp locations
set_location(sender, args[1:])
save_snowbrawl()
else:
noperm(sender)
return True
elif args[0] == name_command:
if sender.hasPermission(modify_perm):
#rename an arena
rename_arena(sender, args[1:])
save_snowbrawl()
else:
noperm(sender)
return True
elif args[0] == set_command:
if sender.hasPermission(modify_perm):
#set an arena tp sign
set_arena_sign(sender, args[1:])
save_snowbrawl()
else:
noperm(sender)
return True
elif args[0] == modify_command or args[0] == modify_command_alias:
if sender.hasPermission(modify_perm):
#modify the arena
modify_arena(sender, args[1:])
save_snowbrawl()
else:
noperm(sender)
return True
elif args[0] == quit_command:
if sender.hasPermission(quit_perm):
#quit match
quit_match(sender)
else:
noperm(sender)
return True
else:
if sender.hasPermission(teleport_perm):
#try to tp to an arena
if len(args) > 1:
teleport_to_arena(sender, args[0], args[1])
else:
teleport_to_arena(sender, args[0], 1)
else:
noperm(sender)
return True
+7 -1
View File
@@ -1,3 +1,9 @@
"""
Code that was used once to create this awesome screenshot
- https://i.imgur.com/v4wg5kl.png
- https://i.imgur.com/tIZ3jmC.png
- https://www.reddit.com/r/Minecraft/comments/28le52/screenshot_of_all_players_that_joined_my_server/
"""
import net.minecraft.server.v1_7_R1.EntityPlayer as EntityPlayer import net.minecraft.server.v1_7_R1.EntityPlayer as EntityPlayer
import net.minecraft.server.v1_7_R1.PacketPlayOutNamedEntitySpawn as PacketPlayOutNamedEntitySpawn import net.minecraft.server.v1_7_R1.PacketPlayOutNamedEntitySpawn as PacketPlayOutNamedEntitySpawn
import net.minecraft.server.v1_7_R1.PlayerInteractManager as PlayerInteractManager import net.minecraft.server.v1_7_R1.PlayerInteractManager as PlayerInteractManager
@@ -32,7 +38,7 @@ def spawn(dispname, sender, x, y, z):
@hook.command("spawnplayer") @hook.command("spawnplayer")
def on_spawnplayer_command(sender, args): def on_spawnplayer_command(sender, command, label, args):
global amount, row, ground, goup global amount, row, ground, goup
# X and Z position # X and Z position
+112
View File
@@ -0,0 +1,112 @@
from helpers import *
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,
"trusted" : 8,
"helper" : 9,
"trainingmod" : 10,
"mod" : 4,
"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("-", "")
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):
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` = ? 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):
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute(query, (uuid,))
results = curs.fetchall()
curs.close()
conn.close()
return results
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()
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
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")
+3
View File
@@ -1,4 +1,7 @@
#pylint: disable = F0401 #pylint: disable = F0401
"""
A plugin that automatically tiles (stacks) blocks inside a selected region in configurable directions.
"""
import org.bukkit.event.block.BlockPlaceEvent as BlockPlaceEvent import org.bukkit.event.block.BlockPlaceEvent as BlockPlaceEvent
import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
import org.bukkit.event.player.PlayerInteractEvent as PlayerInteractEvent import org.bukkit.event.player.PlayerInteractEvent as PlayerInteractEvent
-4
View File
@@ -1,4 +0,0 @@
import glob
tools = []
for module_name in glob.glob("plugins/redstoner-utils.py.dir/toolbox/*.py"):
tools.append(__import__(module_name))
-42
View File
@@ -1,42 +0,0 @@
from helpers import *
gamemode_permission = {"self":"gamemode.self","other":"gamemode.other"}
# Helping functions
def setGamemode(sender, gmstring):
gmstring = gmstring.lower()
if is_player(sender):
if gmstring == "c" || gmstring == "creative" || gmstring == "1":
sender.setGameMode(GameMode.CREATIVE)
elif gmstring == "s" || gmstring == "survival" || gmstring == "0":
sender.setGameMode(GameMode.SURVIVAL)
elif gmstring == "a" || gmstring == "adventure" || gmstring == "2":
sender.setGameMode(GameMode.ADVENTURE)
else
msg(sender, "&c%s is no known gamemode (survival/creative/adventure)")
else
msg(sender, "&cYou have to be a valid player to perform this command. Try /gamemode <player> <gamemode>")
# /toolbox
@hook.command("toolbox", desc="The basic command of Toolbox")
def toolbox_command(sender, args):
msg(sender, "&6Toolbox&f is a command library written for Redstoner.com")
# /gamemode
@hook.command("gamemode", aliases=["gm"], desc="Change a player's gamemode")
def toolbox_gamemode_command(sender, args):
param1 = args[0].lower() if len(args)>0 else None
param2 = args[1] if len(args)>1 else None
if len(args) == 1:
if sender.hasPermission(gamemode_permission["self"]) || sender.hasPermission(gamemode_permission["other"]):
setGameMode(sender, param1)
else
noperm(sender)
elif len(args) == 2:
if sender.hasPermission(gamemode_permission["other"]):
if server.getPlayer(param) != None:
setGameMode(server.getPlayer(param), param2)
else
msg(sender, "&cThere's no online player called "+param)
+121
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
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)
+2 -2
View File
@@ -99,13 +99,13 @@ def tokengen_command(sender, args):
@hook.command("token") @hook.command("token")
def on_token_command(sender, args): def on_token_command(sender, command, label, args):
thread.start_new_thread(token_command, (sender,)) thread.start_new_thread(token_command, (sender,))
return True return True
@hook.command("gettoken") @hook.command("gettoken")
def on_gettoken_command(sender, args): def on_gettoken_command(sender, command, label, args):
thread.start_new_thread(tokengen_command, (sender, args)) thread.start_new_thread(tokengen_command, (sender, args))
return True return True