Compare commits

...
316 Commits
Author SHA1 Message Date
KennyTV 0c524b227a 3.0 Release 2019-02-17 09:22:12 +01:00
KennyTV 35deabf5a3 Version increase to 3.0 2019-02-17 09:21:51 +01:00
KennyTV 694cbb729f Update README 2019-02-15 11:16:14 +01:00
KennyTV 57047c519e Some last refactoring/fixes 2019-02-14 10:25:52 +01:00
KennyTV fc8018c530 Fix velocity update/dump messages 2019-02-12 19:12:27 +01:00
KennyTV 73707e2c3a Merge remote-tracking branch 'origin/v3' into v3 2019-02-12 13:30:12 +01:00
KennyTV ac92851e3d Minor refactoring and message changes 2019-02-12 13:30:01 +01:00
KennyTV 4e29a98a32 Merge pull request #25 from PSandro/patch
Patch
2019-02-12 10:06:47 +01:00
Sandro Pischinger 54d1c90795 fix typo "seperator" 2019-02-11 22:32:29 +01:00
Sandro Pischinger 6780914550 fix typo 'Intervalls' 2019-02-11 21:09:54 +01:00
KennyTV 5ab5d11aed Some message changes 2019-02-11 15:01:11 +01:00
KennyTV 94378ca1fa SLP actually has a repo 👀 2019-02-11 10:35:36 +01:00
KennyTV 4c0c425ba0 Fix 2019-02-11 08:50:04 +01:00
KennyTV efea58e665 Rename status perm 2019-02-10 11:55:35 +01:00
KennyTV e15a7dd0ed Let maintenance servers be removed, even if they don't exist on the proxy 2019-02-10 11:17:07 +01:00
KennyTV 2f327b9ce9 whoops 2019-02-09 16:12:02 +01:00
KennyTV 38d0f9de6d Rename some perms 2019-02-09 15:37:21 +01:00
KennyTV 75f7330cc3 Use maintenance.dump perm for dumpcommand 2019-02-09 15:21:37 +01:00
KennyTV 25bf7a3747 Update changelog 2019-02-09 15:02:53 +01:00
KennyTV f8f0a23ede Update README 2019-02-09 12:41:45 +01:00
KennyTV b4d7ed59de Fix update messages in Sponge and Velocity 2019-02-08 17:24:52 +01:00
KennyTV f64d07c1e8 Update README 2019-02-08 15:09:40 +01:00
KennyTV 4dc31a4635 Add beautiful changelog file 2019-02-08 15:03:22 +01:00
KennyTV cb243e1c04 whoops 2019-02-08 11:48:54 +01:00
KennyTV bb5bdfe0c7 Some fixes and changes to subcommand system 2019-02-08 11:46:24 +01:00
KennyTV be144df5de Make subcommand system to finally have that 💩 readable again
* Though it adds 100kb lolz
2019-02-07 19:02:45 +01:00
KennyTV a6f68810fc Add option to disable update checks 2019-02-07 13:30:11 +01:00
KennyTV 3ac01c9f1b Maybe hopefully get rid of the sl4j problem garbage? 2019-02-07 12:48:43 +01:00
KennyTV c9d496e251 Final fixes! (hopefully 👀) 2019-02-07 12:12:06 +01:00
KennyTV be31fdeb0a Config comment change 2019-02-07 11:50:25 +01:00
KennyTV 1ced445742 Move fields from SpigotServers file to config (+ automigration) 2019-02-07 11:43:28 +01:00
KennyTV e52fffbe75 Fixes! 2019-02-07 11:15:18 +01:00
KennyTV 25b4cfe3f2 slf4j sad 2019-02-07 10:45:16 +01:00
KennyTV bc8453a96e Fixes to fallback handling 2019-02-07 10:37:55 +01:00
KennyTV 0379b0c62c Fix error when connecting to fallbackserver 2019-02-07 10:33:34 +01:00
KennyTV cdf34b76b8 Fix typo 2019-02-07 10:25:37 +01:00
KennyTV d3cc9eb989 Do version check on startup async 2019-02-06 13:55:24 +01:00
KennyTV 3048483b0c Rename MaintenanceModePlugin to MaintenancePlugin 2019-02-04 17:09:04 +01:00
KennyTV f16a5800e5 Minor change 2019-02-04 15:39:46 +01:00
KennyTV 672f1f0ff3 Always check for maintenance.admin perm as well 2019-02-04 15:22:36 +01:00
KennyTV a3ddfbefe3 Add some aliases 2019-02-04 10:04:55 +01:00
KennyTV e548a9a94b Fix typo 2019-02-03 17:48:37 +01:00
KennyTV 80d3069ffb Fixes, dump changes 2019-02-03 15:06:55 +01:00
KennyTV fad9824e4d Actually, noone likes hastebin 2019-02-03 14:24:44 +01:00
KennyTV 2bb7e3023d One might say dumping a database's password isn't nice 🤔 2019-02-03 14:03:43 +01:00
KennyTV 105f76d8f4 Changes to config + small help fix 2019-02-03 13:29:51 +01:00
KennyTV 8e7874b691 Auto config migration + fixes 2019-02-02 20:10:49 +01:00
KennyTV 710a69543a Beautiful new config system (💛 PSandro) 2019-02-02 15:18:22 +01:00
KennyTV 8b180342d0 Do update checks async 2019-02-01 13:23:25 +01:00
KennyTV 1a62c596cb Dump command response changes 2019-02-01 11:40:27 +01:00
KennyTV 2b8e2c90c3 Fixes + dump command 2019-02-01 11:21:38 +01:00
KennyTV dcb9c97d0a Update issue template 2019-02-01 10:26:20 +01:00
KennyTV 74ed8783a8 Merge pull request #24 from KennyTV/issue-template
Update issue templates
2019-02-01 10:24:41 +01:00
KennyTV 0d07e6aed3 Update issue templates 2019-02-01 10:24:05 +01:00
KennyTV 49fa7a6ff7 Delete old issue template 2019-02-01 10:23:09 +01:00
KennyTV f40df14d03 Merge pull request #23 from PSandro/patch-1
fix typo
2019-02-01 10:20:03 +01:00
Sandro 6bc63e3fde fix typo 2019-01-31 21:59:43 +01:00
KennyTV c0b6e8ff40 Minor change 2019-01-31 20:27:55 +01:00
KennyTV 0a4a1ce0cf Whoops 2019-01-31 10:43:53 +01:00
KennyTV 35fd75aebb Minor refactoring 2019-01-31 10:42:37 +01:00
KennyTV 59e8dc057a Minor refactoring 2019-01-31 10:36:55 +01:00
KennyTV 91cd767dd7 Load maintenance-icon from plugin folder, not server directory
Some minor refactoring
2019-01-30 15:12:51 +01:00
KennyTV 57ca1ff88c Fix database value loading 2019-01-30 14:23:46 +01:00
KennyTV 15dd00fdcc Velocity should be done (theoretically 🤔) 2019-01-29 10:33:42 +01:00
KennyTV 10b14de218 Fixes to Velocity and Sponge 2019-01-28 22:13:47 +01:00
KennyTV 66899564e8 Update README 2019-01-28 20:30:20 +01:00
KennyTV 6e8d8319f7 Merge remote-tracking branch 'origin/v3' into v3 2019-01-28 20:24:59 +01:00
KennyTV 3ad8be9d3e Update API jar 2019-01-28 20:24:41 +01:00
KennyTV b7c175060d Merge pull request #22 from PSandro/fix-script
Fix script
2019-01-28 18:15:17 +01:00
KennyTV ba6043e654 Update README 2019-01-28 18:11:01 +01:00
Sandro 4bfd3339a2 run install script with skip-input arg on travis 2019-01-28 18:03:36 +01:00
Sandro c03d8d45e0 add skip-input arg 2019-01-28 18:03:36 +01:00
KennyTV b150db8047 Update README 2019-01-28 17:59:28 +01:00
KennyTV 197ff4f813 Update README 2019-01-28 17:52:42 +01:00
KennyTV fc6a5f8747 travis integration 2019-01-28 16:27:41 +01:00
KennyTV a4a37b39e5 Travis very sad :(( 2019-01-28 16:18:31 +01:00
KennyTV b057b88e26 Travis sad :( 2019-01-28 16:15:24 +01:00
KennyTV 2dd383a640 Test Travis integration 2019-01-28 16:12:32 +01:00
KennyTV d6526ae64e Some refactoring 2019-01-28 15:35:42 +01:00
KennyTV 8be8b831ba Add Maintenance-API.jar to ignored 2019-01-28 14:29:36 +01:00
KennyTV ff1ded1fda Actually get offline Sponge user 2019-01-26 20:59:40 +01:00
KennyTV bcc77cf3e0 Listen to global reload event 2019-01-26 13:29:26 +01:00
KennyTV 4213d0824f Merge branch 'master' of https://github.com/KennyTV/Maintenance into v3 2019-01-26 12:45:38 +01:00
KennyTV 729722259a Fix colors in messages in Sponge 2019-01-26 12:37:54 +01:00
KennyTV 6c408d823a Merge branch dev into master 2019-01-26 11:16:12 +01:00
KennyTV 9b7ec9d8bf Velocity startup fix 2019-01-25 15:39:08 +01:00
KennyTV 3cce54a62d Final touches to Sponge 2019-01-25 15:16:52 +01:00
KennyTV 40119254a7 Properly do the uuid remove thingy 2019-01-25 13:44:56 +01:00
KennyTV 4b33e69d11 Command to remove whitelisted players via their uuid... except on Bungee ;( 2019-01-25 13:15:00 +01:00
KennyTV 90d08d651e Velocity command 2019-01-25 12:35:54 +01:00
KennyTV 11b73a05c8 Start velocity
Some refactoring and minor improvements
2019-01-24 21:05:42 +01:00
KennyTV b68c8dd0d8 Use proper id when getting api instance 2019-01-23 17:10:29 +01:00
KennyTV 8933caa51f Single jars now work on their own as well
Minor cleanup
2019-01-23 16:18:59 +01:00
KennyTV e82b1f760a Create CONTRIBUTING.md
Create CONTRIBUTING.md
2019-01-23 10:50:41 +01:00
KennyTV dc97079967 Create CONTRIBUTING.md 2019-01-22 22:46:57 +01:00
KennyTV 2e44decaa9 That was a space 2019-01-22 22:32:21 +01:00
KennyTV 244f7efe21 Remove licence notice 2019-01-22 22:31:43 +01:00
KennyTV d299db678d It works! 2019-01-22 18:07:58 +01:00
KennyTV 0e558af1f1 Add copyright notice for funzees 2019-01-22 13:52:14 +01:00
KennyTV a6cd5978e3 Use YamlConfig (of Bungee) in every module
Fix tabcompletion on Bungee
Even if set to 0, make database calls 'only' every 500 milliseconds

Note that the configuration stuff might completely change again
2019-01-22 13:48:06 +01:00
KennyTV 24c893bb1d Small message change + merge dev 2019-01-21 14:54:46 +01:00
KennyTV 8a80446c8c Merge branch 'dev' of https://github.com/KennyTV/Maintenance into 3.0 2019-01-21 14:51:17 +01:00
KennyTV a88cc02f9a Fix NPE 2019-01-21 14:46:31 +01:00
KennyTV df442063ea Don't create a random UUIDs on each ping (to test) 2019-01-21 14:36:24 +01:00
KennyTV 40c49ba3ee Tabcompletion 2019-01-18 15:19:26 +01:00
KennyTV 9135f817d1 Add a small but nice warning 2019-01-17 12:04:55 +01:00
KennyTV 07fc9894b1 Remove slp reference from main class 2019-01-15 16:17:55 +01:00
KennyTV 930612b5bb nevermind still dumb i guess i think maybe 2019-01-14 18:23:11 +01:00
KennyTV 29a87c831a Scheduler fix 2019-01-14 15:25:51 +01:00
KennyTV 722340140a Some minor additions/changes 2019-01-14 15:11:54 +01:00
KennyTV 96d4834f83 ... because I'm an idiot, obviously 2019-01-14 14:48:47 +01:00
KennyTV 308b42948a Small message fix 2019-01-14 14:36:35 +01:00
KennyTV 8e304bb09d Javadoc 2019-01-14 14:32:07 +01:00
KennyTV 7f2c23e69e Refactoring and more Sponge stuff 2019-01-14 14:27:26 +01:00
KennyTV 1d68c4fee0 Refactoring 2019-01-13 20:05:48 +01:00
KennyTV 3d808ea718 Some ground work for the Sponge part 2019-01-13 15:47:11 +01:00
KennyTV 79f1933b9a Version increase to 3.0-SNAPSHOT 2019-01-13 12:14:07 +01:00
KennyTV 4089e75f2d Merge remote-tracking branch 'origin/master' into dev 2019-01-13 12:12:53 +01:00
KennyTV a2d4e12ca6 Write plugin name without variable 2019-01-11 15:17:49 +01:00
KennyTV 72e5d596fc Set build name again 2019-01-11 15:14:45 +01:00
KennyTV 4f2dea5036 Improve updater methods 2019-01-11 15:08:11 +01:00
KennyTV 915dc25284 Update README 2019-01-11 15:04:32 +01:00
KennyTV 13e4468e93 Merge pull request #17 from PSandro/maven-clean-clean
More maven cleanup
2019-01-09 21:29:14 +01:00
Sandro ca23f0d546 change parent.version to project.parent.version 2019-01-09 21:18:04 +01:00
Sandro 53c450170a rename directories to fit maven module name 2019-01-09 21:17:15 +01:00
Sandro 348521cc3e remove custom module names 2019-01-09 21:15:48 +01:00
Sandro f4ce887d24 add script -> install ServerListPlus to local repository 2019-01-09 21:15:21 +01:00
KennyTV 5e176dc10e Some minor refactoring 2019-01-07 20:28:12 +01:00
KennyTV 00cd9a8bb1 Minor change 2019-01-04 11:04:05 +01:00
KennyTV 0166aeadb2 Minor improvement 2018-12-29 21:41:06 +01:00
KennyTV 864c22c3ed Update README 2018-12-28 19:49:07 +01:00
KennyTV 910b88d663 Fix a typo 2018-12-26 12:16:38 +01:00
KennyTV 4a56c28a0d Improve isNumeric method 2018-12-21 18:07:30 +01:00
KennyTV 1c13465bf4 Some javadoc changes 2018-12-21 15:00:14 +01:00
KennyTV f4d46f03aa Pom clean up 2018-12-21 14:43:53 +01:00
KennyTV 5b3e3ef179 Set api version in plugin.yml 2018-12-19 10:28:51 +01:00
KennyTV 392b12e592 Version increase to 2.5.3-SNAPSHOT 2018-12-19 10:21:38 +01:00
KennyTV e99f7772e6 Language fix 2018-12-17 18:26:07 +01:00
KennyTV 54d20e9e50 2.5.2 Release 2018-12-17 10:10:56 +01:00
KennyTV fd0e361474 Version increase to 2.5.2 2018-12-16 18:16:28 +01:00
KennyTV 551e38f882 Small fix, whoopsie? 2018-12-16 18:14:32 +01:00
KennyTV d18f04c010 Added last Portuguese messages 2018-12-16 18:06:23 +01:00
KennyTV 3b7f3043f1 Add Portuguese translations 2018-12-12 10:41:23 +01:00
KennyTV faf2a8d083 Kick non permitted players when detecting server change from MySQL 2018-12-10 19:33:55 +01:00
KennyTV 42071e3bad Fix maintenance value with MySQL enabled not loading until the first ping 2018-12-10 19:20:06 +01:00
KennyTV 978d32e947 Make experimental MySQL stuff not so experimental anymore 2018-12-09 10:49:06 +01:00
KennyTV fe670cb3e2 Fix maintenance icon for 1.13+ servers 2018-12-08 18:39:40 +01:00
KennyTV d2f4a7d9a5 Experimental single server database stuff 2018-12-06 17:38:57 +01:00
KennyTV b162ce1825 pom 2018-12-06 11:58:20 +01:00
KennyTV fbdcce3c3b pom 2018-12-06 11:57:34 +01:00
KennyTV 2d939f095c Experimental single server database stuff 2018-12-06 11:47:43 +01:00
KennyTV 034e2f2b98 Change config header 2018-12-06 10:37:59 +01:00
KennyTV f429ab0a60 Remove some more unnecessary reloads 2018-12-06 10:32:08 +01:00
KennyTV 5578d0879b Properly fix the last thingy 2018-12-06 10:22:02 +01:00
KennyTV 8b1e6244ea Fix 2018-12-05 07:03:26 +01:00
KennyTV 49c7b9c775 Don't reload files when toggling maintenance
Update bStats, optimize it a bit... and fix it forgetting some config values, I guess 🤔
2018-12-03 16:58:05 +01:00
KennyTV da1c724464 Add debug mode 2018-11-25 16:47:58 +01:00
KennyTV de15150a04 Minor message change 2018-11-25 16:35:09 +01:00
KennyTV 0d1fb2b260 More french translations, thanks to Spigot user Zendrique 2018-11-23 19:58:17 +01:00
KennyTV 55d0779a33 Some tweaks to messages 2018-11-23 18:39:59 +01:00
KennyTV 8f41d464e1 Partially include french translations!
Thanks to Spigot user Zendrique
Still relies on 2.4 format, so some messages are missing and unsorted
2018-11-23 13:34:07 +01:00
KennyTV 1db2b6c934 Version increase to 2.5.2-SNAPSHOT 2018-11-20 15:56:35 +01:00
KennyTV aa58f76057 Hotfix 2.5.1 2018-11-17 16:57:11 +01:00
KennyTV 1def0a1061 File loading fix 2018-11-17 16:55:17 +01:00
KennyTV 3b4a66b04e 2.5 Release 2018-11-17 11:46:04 +01:00
KennyTV 7384b2e55c 2.5 API 2018-11-17 11:44:28 +01:00
KennyTV f8eaed445a Version increase to 2.5 2018-11-17 11:43:43 +01:00
KennyTV dfef9190ca Some final fixes and changes 2018-11-17 11:41:51 +01:00
KennyTV 7ce61834c2 Check for other kick reasons 2018-11-16 22:23:58 +01:00
KennyTV 240a7ab242 Message changes 2018-11-16 22:08:35 +01:00
KennyTV b3de59bfba API change 2018-11-10 22:08:29 +01:00
KennyTV 5d5de39845 Make the help message a little fancier 2018-11-10 17:38:41 +01:00
KennyTV 59af774d09 Some more fixes 2018-11-10 16:50:10 +01:00
KennyTV 18828207c0 Maintenance status command + some more minor changes 2018-11-10 15:08:32 +01:00
KennyTV 5c67922996 Some fixes and changes 2018-11-09 23:20:34 +01:00
KennyTV af50a45e65 Command 2018-11-09 21:14:32 +01:00
KennyTV 7ccd265a30 pom changes 2018-11-07 21:36:29 +01:00
KennyTV e76f22f071 Timer commands for single server maintenance 2018-11-07 21:32:08 +01:00
KennyTV 3c03b719d2 API changes 2018-11-07 21:31:49 +01:00
KennyTV cd71531766 Timers for single server maintenance
Todo: Implementation in command
2018-11-07 20:02:59 +01:00
KennyTV 282c116d02 Some improvements to messages and message handling 2018-11-06 11:01:04 +01:00
KennyTV 820171916b Improve version check handling 2018-11-05 23:02:46 +01:00
KennyTV 136fbb0ba8 Improve version check handling 2018-11-05 22:58:12 +01:00
KennyTV 4f0c05c357 Further single server maintenance stuff 2018-11-05 21:24:56 +01:00
KennyTV 0377838a26 Dont save and get Spigot maintenance servers from sql for now 2018-11-04 14:43:47 +01:00
KennyTV b72ff1b772 Some message changes 2018-10-19 14:21:21 +02:00
KennyTV 287488f1b6 Some single server maintenance stuff I did during a course at university ¯\_(ツ)_/¯ 2018-10-19 12:08:37 +02:00
KennyTV 9ffb67db1f WIP: Add possibility to set single servers to maintenance 2018-10-12 23:17:46 +02:00
KennyTV a563c0a8a8 Restructured language files 2018-10-02 12:15:08 +02:00
KennyTV 234086444f WIP: Add possibility to set single servers to maintenance 2018-10-02 11:56:30 +02:00
KennyTV a93b0834a2 Remove more or less deprecated Guava usages 2018-09-30 11:29:48 +02:00
KennyTV b5550dfe82 Add multiple language support 2018-09-28 13:22:55 +02:00
KennyTV d99300ecac Version increase to 2.5-SNAPSHOT
Increase from 2.4.1-SNAPSHOT as bigger feature updates are planned
2018-09-28 12:42:06 +02:00
KennyTV 1c0688a172 Add language-de 2018-09-28 12:00:40 +02:00
KennyTV ff3b117189 Make SenderInfo an interface instead of an abstract class 2018-09-27 10:14:29 +02:00
KennyTV aaed1b32cd Fix starttimer command not working
Remove slf4j shade for now
2018-09-27 09:57:56 +02:00
KennyTV 38c8e1d2c3 Shade slf4j to fix compatibility with plugins using older Hikari dependencies 2018-09-26 11:11:56 +02:00
KennyTV 1e1792d132 Version increase to 2.4.1-SNAPSHOT
Update ProtocolLib dependency to newest release
2018-09-22 19:20:55 +02:00
KennyTV b29462a5cb 2.4 Release 2018-09-17 10:21:17 +02:00
KennyTV c9161ebe24 2.4 Release API 2018-09-17 10:17:44 +02:00
KennyTV 8441c6a8bf Prepare for 2.4 Release 2018-09-17 10:16:23 +02:00
KennyTV 72c2ba77ee Some final fixes and changes
Move kickmessage back to config
2018-09-16 22:36:12 +02:00
KennyTV a097790b76 Update dependencies 2018-09-13 10:43:09 +02:00
KennyTV b7129e8aa8 Fix raw color saving in config when upgrading from a version lower than 2.3 2018-09-08 12:29:10 +02:00
KennyTV ab9c2b8be1 Spigot Runnable fix 2018-09-08 12:13:47 +02:00
KennyTV a9a37b8fc8 Fix Bungee config not updating 2018-09-08 12:00:21 +02:00
KennyTV d50cb67a26 Add timer variable for the pingmessage
Have broadcasts for timers be set for seconds instead of just minutes + better formatting
Some language fixes
2018-09-07 22:52:20 +02:00
KennyTV 5e42500308 WIP: Add timer variable for the pingmessage
WIP: Have broadcasts for timers be set for seconds instead of just minutes + better formatting
2018-08-29 00:42:00 +02:00
KennyTV 50997a847f Language fixes and changes 2018-08-26 17:56:31 +02:00
KennyTV 2305d85c01 Switch messages to language file + small fixes 2018-08-26 12:34:28 +02:00
KennyTV 33bbc35d88 Change javadoc message to read the new config field 2018-08-26 11:50:08 +02:00
KennyTV 28b3e100fb Switch some more messages to language file 2018-08-26 11:49:13 +02:00
KennyTV edae2d699b Switch some messages to language file 2018-08-25 12:37:23 +02:00
KennyTV 0cc477a769 Prepare new language file 2018-08-25 12:19:01 +02:00
KennyTV 53b84a999f Change helpmessage 2018-08-25 11:41:33 +02:00
KennyTV 49487c11ff Don't enable/disable maintenance mode if it's already in the goal's state 2018-08-25 11:39:49 +02:00
KennyTV 0c4070b7a7 Add possibility to show the default playercount 2018-08-22 20:11:24 +02:00
KennyTV 67909a4862 Relocate HikariCP dependency 2018-08-22 19:08:20 +02:00
KennyTV 28ee563083 Don't spam update notifications on every single join
Also, minor cleanup #3
2018-08-21 21:05:48 +02:00
KennyTV 28b2b528c1 Minor cleanup #2 2018-08-21 21:01:12 +02:00
KennyTV a53d9d0850 Minor cleanup 2018-08-21 20:58:59 +02:00
KennyTV 873a8812aa Add variables to show normal playercount 2018-08-21 20:53:15 +02:00
KennyTV 19ebc90963 Whoops 2018-08-17 12:37:49 +02:00
KennyTV dfbd1381de Version increase to 2.4-SNAPSHOT 2018-08-17 12:36:08 +02:00
KennyTV c9fe48a067 2.3.1 Release
Hotfix before the release
2018-08-17 12:30:01 +02:00
KennyTV 49b022b665 Quick hotfix for the 2.3.1 Release
When enabling maintenance on one proxy with MySQL enabled, the other ones will now also kick all non permitted players and switch their ServerListPlus state
2018-08-17 11:29:28 +02:00
KennyTV 86be23ae5f Minor changes 2018-08-16 19:05:44 +02:00
KennyTV 420412978e 2.3.1 Release 2018-08-16 17:56:28 +02:00
KennyTV 25e2f4dae2 2.3.1 Release 2018-08-16 17:54:57 +02:00
KennyTV d767be96b5 Fix 2018-08-15 11:54:35 +02:00
KennyTV 6d73acca9b Only check the mysql delay if it's at least a second 2018-08-15 11:11:25 +02:00
KennyTV 1f116374ad Fix permission checks for help page 2018-08-11 11:10:25 +02:00
KennyTV d0b7d96208 Fix updated config being overwritten again 2018-08-08 11:56:32 +02:00
KennyTV 16285d7064 Change some javadocs 2018-08-07 23:31:02 +02:00
KennyTV 1f27084fe1 Return empty string for pingmessages if config list is empty 2018-08-07 23:04:09 +02:00
KennyTV 261aace0db Remove unnecessary (second) result closing 2018-08-07 22:58:06 +02:00
KennyTV 344b910214 Remove unused method 2018-08-07 22:49:22 +02:00
KennyTV fbaa4896e1 Replace deprecated ProtocolLib packet 2018-08-07 14:55:19 +02:00
KennyTV 2f93064f60 Some pom changes 2018-08-07 13:51:59 +02:00
KennyTV 65b47c5e07 Only show the commands you have the permission to execute in the helppage 2018-08-06 21:12:36 +02:00
KennyTV d70d01f2d3 Fix config updating unnecessary value in Spigot version 2018-07-27 12:34:09 +02:00
KennyTV 769d7d3bcd Minor improvement 2018-07-27 12:28:07 +02:00
KennyTV a5f47688e0 Minor improvement 2018-07-27 11:50:19 +02:00
KennyTV 7d2e6a25a4 Move license and whitelistedplayers file to core module 2018-07-25 00:29:06 +02:00
KennyTV 69999b3b7a Fix MySQL millisecondsToCheck variable 2018-07-24 22:29:03 +02:00
KennyTV 94d1bd4eb9 Only make a request to the database at least x seconds after the last one 2018-07-23 11:52:30 +02:00
KennyTV c18e8b7ab7 Add warning and backup string if config value is null 2018-07-23 11:10:16 +02:00
KennyTV 9f45187300 Add warning and backup string if config value is null 2018-07-23 11:09:08 +02:00
KennyTV 0c6ba8a9b7 Updated BungeeCord dependency to 1.13-SNAPSHOT 2018-07-21 11:02:55 +02:00
KennyTV 1af69f2e8b Version increase to 2.3.1-SNAPSHOT 2018-07-18 15:50:35 +02:00
KennyTV a3b836b1c5 2.3 Release 2018-07-17 11:45:43 +02:00
KennyTV 1eca6c81ad Version increase for the 2.3 Release 2018-07-17 11:41:03 +02:00
KennyTV b9b4a78b5c Minor cleanup 2018-07-16 21:52:27 +02:00
KennyTV fda23c5539 The whitelist command now also shows the UUID of the player 2018-07-16 20:25:05 +02:00
KennyTV 8297321971 Changed help message order 2018-07-16 18:04:14 +02:00
KennyTV cfeaf00f26 Fixed wrong command descriptions 2018-07-16 13:22:46 +02:00
KennyTV 5ee1b32249 Uncommented new help messages 2018-07-16 13:07:59 +02:00
KennyTV b69f0dc90e Added missing motd command permission 2018-07-14 22:27:20 +02:00
KennyTV fe6cae4e47 Added motdlist command 2018-07-09 16:33:51 +02:00
KennyTV b494b5c23c Reworked setmotd command 2018-07-09 15:49:54 +02:00
KennyTV 3bd3395128 Removed setmotd command 2018-07-08 11:29:20 +02:00
KennyTV 3e3f63220d Config fix 2018-07-08 11:25:47 +02:00
KennyTV ccba0f042f Version increase to 2.3-SNAPSHOT 2018-07-08 11:20:18 +02:00
KennyTV abdd89259d Added multiple pingmessages + minor improvements 2018-07-08 10:54:51 +02:00
KennyTV 256f203c48 Minor code change 2018-06-18 11:17:47 +02:00
KennyTV 205412b02c Minor improvement 2018-06-18 11:17:06 +02:00
KennyTV 990289feb2 Fixed a problem with the setmotd command 2018-06-17 20:57:50 +02:00
KennyTV 44b1ff1a1f Fixed a typo 2018-06-17 20:27:01 +02:00
KennyTV f9e11bb9e5 Removed unused method 2018-06-17 19:58:21 +02:00
KennyTV eef1584b1c Small logic change 2018-06-17 18:51:35 +02:00
KennyTV 937dd84d1c Added permission per subcommand 2018-06-17 18:40:47 +02:00
KennyTV 80b9fe280b Message change 2018-06-17 18:29:58 +02:00
KennyTV 3892892792 Version increase to 2.2.3-SNAPSHOT 2018-06-17 18:06:59 +02:00
KennyTV 519551e76c Removed Spigot dependency from Core module 2018-06-17 14:36:18 +02:00
KennyTV b30476ae3f 2.2.2 Release 2018-06-17 11:24:35 +02:00
KennyTV 9d417a12f1 2.2.2 Release 2018-06-17 11:22:43 +02:00
KennyTV fd5406b95d 2.2.2 Release 2018-06-17 11:21:10 +02:00
KennyTV 0ef59e557d Maintenance icon fix and reload command message change 2018-06-14 12:35:10 +02:00
KennyTV 15ed1db347 Made the loading of the maintenance icon more structured 2018-06-14 12:10:33 +02:00
KennyTV 429d5b90d4 Api fix 2018-06-10 10:44:42 +02:00
KennyTV b3ab931aca Removed old config comment 2018-06-09 11:26:58 +02:00
KennyTV 21b42d0c72 Version increase to 2.2.2-SNAPSHOT
Some minor pom changes
2018-06-09 10:14:21 +02:00
KennyTV 7b1e1a27ba Merge remote-tracking branch 'origin/master' 2018-04-23 11:39:04 +02:00
KennyTV fb7b1e791f Some javadoc and comment changes 2018-04-23 11:38:51 +02:00
KennyTV eecd59b387 2.2.1 release 2018-04-17 04:46:22 +02:00
KennyTV ff7d8e0293 Project/pom changes 2018-04-16 20:54:21 +02:00
KennyTV 19c6d77a2c Updated API 2018-04-16 19:50:50 +02:00
KennyTV e002aa34e9 Comment line change 2018-04-16 16:35:13 +02:00
KennyTV 865e53a4a8 MySQL change 2018-04-16 15:31:50 +02:00
KennyTV b8c652b7fb MySQL fix 2018-04-16 14:39:40 +02:00
KennyTV c4080f82dc More cleanup 2018-04-16 14:18:19 +02:00
KennyTV 1a33497e8f Fixed doc typo 2018-04-15 15:07:19 +02:00
KennyTV f8353b8eda Various stuff 2018-04-15 13:53:42 +02:00
KennyTV 4980ad54ec Setmotd fixes 2018-04-15 13:38:21 +02:00
KennyTV 5363305411 Setmotd fixes 2018-04-15 13:37:07 +02:00
KennyTV 6ff47619ad Added setmotd command 2018-04-15 13:17:58 +02:00
KennyTV 69315a3f74 Create ISSUE_TEMPLATE.md 2018-04-14 19:09:34 +02:00
KennyTV 8b1ddba672 Added import 2018-04-14 18:46:24 +02:00
KennyTV bf63f0e209 MySQL improvements 2018-04-14 12:25:57 +02:00
KennyTV 450c923d24 Fixes 2018-04-14 12:06:29 +02:00
KennyTV 9a922a6df5 Small ServerListPlus integration and command fix 2018-04-14 12:00:46 +02:00
KennyTV 08a5a9a021 Fixes 2018-04-13 23:28:15 +02:00
KennyTV 61ad7d8533 Code cleanup 2018-04-13 22:56:41 +02:00
KennyTV 52d2b3c096 Automatically create sql table if non existing 2018-04-13 20:12:32 +02:00
KennyTV b0a69cc048 Moved resources 2018-04-13 19:26:45 +02:00
KennyTV 74e445a62e Added license and bumped version to 2.2.1-SNAPSHOT 2018-04-13 19:24:16 +02:00
KennyTV 91219202b2 Updated README 2018-04-05 23:50:36 +02:00
KennyTV a3545c83a0 Removed first commit errors 2018-04-05 23:45:39 +02:00
KennyTV 31baf91e8f Code commit 2018-04-05 23:43:25 +02:00
KennyTV 214cd53751 Update README.md 2018-03-17 11:43:36 +01:00
KennyTV 2be16882c7 Update README.md 2018-03-17 10:30:46 +01:00
KennyTV 75e2264b44 Update README.md 2018-03-06 21:53:08 +01:00
KennyTV fd7a0eb6a5 Update README.md 2018-03-06 21:52:14 +01:00
KennyTV 177115f144 Add files via upload 2018-03-06 21:39:49 +01:00
KennyTV edbe31dc9c Create README.md 2018-03-06 21:39:02 +01:00
KennyTV 21a2f9ef2f Init 2018-02-16 18:39:21 +01:00
144 changed files with 7869 additions and 2092 deletions

No files matched your search

+149
View File
@@ -0,0 +1,149 @@
# Maintenance Changelog
This file contains update logs for this project. The top may contain a `Unreleased` section, gathering update logs for a future update during development.
## 3.0 - February 17th 2019
### Changed
* This plugin now also supports the platforms Sponge and Velocity!
* Added tabcompletion for maintenance commands on all platforms
* This plugin now uses a custom config system, which means comments won't vanish after saving them and the different configs have been unified
* You can now also add and remove (offline) players to/from the maintenance whitelist by using their uuid (i.e. `/maintenance add <uuid>`)
* The %TIMER% variable can now also be used in the playercount-, playercounthover- and kickmessages
* To make life easier for people running on Bungee without an extra permission plugin: the `maintenance.admin` permission gives access to all subcommands
* Made bug reports a little easier with the new `/maintenance dump` command
* Added a config option to disable update checks (not recommended)
* Moved `kickmessage` field from config to language file and added its default translations
* Changed permissions nodes for the Bungee part (`from: to`):
* `maintenance.toggleserver`: `maintenance.singleserver.toggle`
* `maintenance.servertimer`: `maintenance.singleserver.timer`
* `maintenance.status`: `maintenance.singleserver.status`
* The command `/maintenance timer abort` has been renamed to `/maintenance aborttimer`
* Added additional aliases: `/maintenance end` for `/maintenance endtimer`, `start` for `starttimer`, `abort` for `aborttimer`
* On false command syntax usage, the reply will be the specific help message for that command, not the entire help window as it was before
* Improved update checks and updater
* Many many other runtime improvements and some major internal refactoring
### Fixed
* Fixed a startup issue with other plugins using the same MySQL library on Bungee (for example some versions of LuckPerms)
* Fixed an error on Bungee when single servers are set to maintenance with no fallbackserver set
* Fixed a rare problem with adding and removing players to/from the maintenance whitelist
* Fixed an issue with starting server timers while also running a global maintenance timer
* Fixed the `/maintenance status` not appearing in the help overview
---
## 2.5.2 - December 17th 2018
### Changed
* Added French `fr` (thanks to Zendrique) and Portuguese `pt` (thanks to JoaoPinto) translations!
* Improvements to MySQL stuff on the Bungee part
* If enabled, single servers (on the Bungee part) that are under maintenance are now saved into the given database as well!
### Fixed
* Fixed the maintenance value only loading on the first server ping, not on startup
* Fixed an error while setting maintenance to single servers, when the executor is something other than a player
* Fixed the maintenance-icon not loading on 1.13+ Spigot servers with ProtocolLib
* Some other general improvements and a small message fix
---
## 2.5.1 - November 17th 2018
### Fixed
* Fixed an occasional file loading error on startup
---
## 2.5 - November 17th 2018
### Changed
* Added the possibility on BungeeCord to also enable maintenance on Spigot servers managed by the proxy
* `/maintenance <on/off> <servername>` will now set maintenance to a proxied Spigot server
* `/maintenance <starttimer/endtimer> <server> <minutes>` works analog to the normal timer commands
* `/maintenance status` shows proxied servers that have maintenance enabled
* new permissions are `maintenance.toggleserver`, `maintenance.servertimer` and `maintenance.status`
* Added a multiple-language-support system! It's currently not that big tho, with the only language added being de/German
* If you like this plugin, know French or Spanish (or any other language that isn't yet supported by the plugin) and want to contribute a bit to it, translations of the default language.yml are greatly appreciated!
* Note: There will be a new 'language-en.yml' file created, so if you changed any messages before, you have to do it again in the new file
* Made the help message a little fancier
* Some API changes
### Fixed
* Fixed a bug with starttimers not being able to start properly
---
## 2.4 - September 17th 2018
### Changed
* Edit nearly every message to your hearts content with the now introduced language.yml file!
* Added `/maintenance removemotd <index>` command to remove a motd via an ingame command (if you have multiple ones)
* You can now include the `%TIMER%` variable into your maintenance motd - **If using the maintenance endtimer**, it will display the time left until maintenance will be disabled!
* Simply shows `-` if maintenance is on without any timer
* A nice integration could be `&cExpected to come back in: &6%TIMER%`
* You can now choose to show the normal playercount during maintenance instead of a custom message by changing the `enable-playercountmessage` value in the config
* You can also include the playercount in a custom playercountmessage by using the 2 variables `%ONLINE%` and `%MAX%`
* If there's a new update available, the update notification will no longer be sent on every single login, but rather just on the first one after startup
* Removing players from the maintenance whitelist now accepts uncapitalized names
---
## 2.3.1 - August 17th 2018
### Changed
* When a string in the config is missing, the plugin doesn't cancel the current process and throws an error anymore, but rather gives a soft warning in the console and returns a backup string
* If MySQL is enabled, the plugin will only make a database request at least x seconds after the last request, whereas you can define the value in the config under `mysql.update-interval`
* Example: If a first player pings the server after startup, the value will be updated -> No update in the next x seconds even if a player pings -> After elapsed, as soon as the next player pings the server again
* Especially helpful as well as recommended for servers with many players
* Another improvement for MySQL support: After enabling maintenance on one proxy, the other connected ones will then also kick all non permitted players and switch their ServerListPlus state!
* The `/maintenance` helppage now only shows the commands the player actually has permission to execute
---
## 2.3 - July 17th 2018
### Changed
* Added the possibility to have multiple pingmessages, of which one will be randomly chosen on each ping when maintenance is enabled (you can also just keep it at one)!
* Added permissions per subcommand
* `maintenance.command` required to use any of the commands
* `maintenance.toggle` to use /maintenance <on/off>
* `maintenance.reload` to use /maintenance reload
* `maintenance.update` to use /maintenance <update/forceupdate>
* `maintenance.timer` to use /maintenance <starttimer/endtimer> <minutes>
* `maintenance.whitelist.add` to use /maintenance add <player>
* `maintenance.whitelist.remove` to use /maintenance remove <player>
* `maintenance.whitelist.list` to use /maintenance whitelist
* `maintenance.setmotd` to use /maintenance setmotd <index> <1/2> <message>
* `maintenance.motd` to use /maintenance motd
* Added `/maintenance motd` command to list all set maintenance pingmessages
* `/maintenance whitelist` now also shows the UUID connected to each name
### Fixed
* Reworked/fixed the `/maintenance setmotd` command
* Some typo and description fixes
---
## 2.2.2 - June 17th 2018
### Changed
* Changed the loading of the maintenance icon to be more predictable: It will load directly on startup and can now be reloaded by using the `/maintenance reload` command as well
* Changed the reload message to read the proper reload changes
* Removed an obsolete config comment
* You can now hook into the plugin with the integrated API
---
## 2.2.1 - April 17th 2018
### Changed
* Added `/maintenance setmotd <1/2> <message>` command to edit the maintenance mode motd via a command
* The Bungee version of the plugin will now automatically create a MySQL table if it is enabled, so you won't have to manually create one anymore
### Fixed
* Fixed the ServerListPlus motd only changing on using the command, but not on the server startup
* Fixed an error with canceling the start-/endtimer in the Bungee version
* Fixed an error with removing players from the whitelist in the Spigot version
---
## 2.2 - March 17th 2018
### Changed
* Great update for the Spigot version of the plugin as well as performance improvements and bugfixes in both versions
* If you have ProtocolLib installed, you can set a custom server icon while maintenance is enabled, also the playercount-message and the playercount-hover-message are now available (as it has already been in the Bungee version)!
* In the BungeeCord version of the plugin, the `/maintenance remove <player>` command now also works for offline players
* Removed the plugin's prefix from some messages
* General performance improvements
### Fixed
* The Spigot version should be much more compatible with other motd-changing plugins, such as SexyMotd
* Fixed some other issues with the ProtocolLib integration
* Minor textfix for the updatemessage in the Spigot version
---
## 2.1 - February 17th 2018
### Changed
* Massive code cleanup for both the Bungee and Spigot version of the plugin
* Minor performance improvements
### Fixed
* Fixed start- and endtimers not being cancelled properly
* Fixed an error for the update command in the Spigot version
* Fixed an error regarding the ServerListPlus integration in the Spigot version
---
## 2.0 - February 15th 2018
### Changed
* You can now put the plugin not only inside your Bungee plugins folder, but also your Spigot/Bukkit one! Both will have the same feautures, but simply on their own platform. However, the Spigot version doesn't have MySQL support (as you would normally use BungeeCord for connecting multiple Spigot/Bukkit servers) and you can't use playercount-message, besides this, it has all its main features.
* On BungeeCord you can make your own custom messages for the playercount
* On Spigot you will see `N/0` (N being the actual count). If you also have ProtocolLib on your server, `0/0` will be displayed.
* As many of you asked me: Maintenance now supports the plugin ServerListPlus
* Performance improvements
### Fixed
* Fixed some permission and message bugs
* Fixed problems with adding and removing players from the maintenance whitelist
* Fixed update checks
+5
View File
@@ -0,0 +1,5 @@
# Contribution
As I'm just a random guy making this plugin as a fun side-project, it will never be "perfect".
Any improvement is welcome, as long as it fits with the general style of code, that should become apparent when looking at some of the other classes. :)
Generally, the used formatting is the default formatting of IntelliJ (Ctrl+Alt+L).
+14
View File
@@ -0,0 +1,14 @@
---
name: Bug report
about: Report a bug to have it fixed
---
## Bug reproducibility
**How does the problem occur/what are the steps to reproduce it?**
## Error
**Is there an error? Save it via https://pastebin.com/ and link paste the link.**
## Server information
**Type '/maintenance dump' and paste the given link here**
+2 -1
View File
@@ -91,4 +91,5 @@ $RECYCLE.BIN/
*.msi
*.msm
*.msp
*.lnk
*.lnk
!MaintenanceAPI.jar
+7
View File
@@ -0,0 +1,7 @@
language: java
jdk:
- oraclejdk8
cache:
directories:
- '$HOME/.m2'
+2 -2
View File
@@ -1,4 +1,4 @@
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
@@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
@@ -1,36 +0,0 @@
package eu.kennytv.maintenance.api;
public interface IMaintenance {
/**
* Enabled/disabled maintenance mode.
* If enabled, all non-permitted players will be kicked.
* <p>
* If using the BungeeCord version and MySQL is enabled,
* it will also be written into the database.
* </p>
*
* @param maintenance true to enable, false to disable maintenance mode
*/
void setMaintenance(boolean maintenance);
/**
* @return true if maintenance is enabled on the proxy
*/
boolean isMaintenance();
/**
* @return true if a timer task is currently running
*/
boolean isTaskRunning();
/**
* @return version of the plugin
*/
String getVersion();
/**
* @return {@link ISettings} for more options
*/
ISettings getSettings();
}
@@ -1,54 +0,0 @@
package eu.kennytv.maintenance.api;
import java.util.Map;
import java.util.UUID;
public interface ISettings {
/**
* @return true if maintenance is enabled on the proxy
*/
boolean isMaintenance();
/**
* @return true if "join-notification" is set to true in the config
*/
boolean isJoinNotifications();
/**
* @return true if "custom-maintenance-icon" is set to true in the config
*/
boolean hasCustomIcon();
/**
* The keyset of the map contains the uuids as a string, the values the names of the players.
*
* @return map of uuids of whitelisted players with their last seen names
*/
Map<UUID, String> getWhitelistedPlayers();
/**
* Removes a player from the maintenance whitelist.
*
* @param uuid uuid of the player to remove
* @return true if removing the player was successful
*/
boolean removeWhitelistedPlayer(UUID uuid);
/**
* Removes a player from the maintenance whitelist.
*
* @param name name of the player to remove in lowercase letters
* @return true if removing the player was successful
*/
boolean removeWhitelistedPlayer(String name);
/**
* Adds a player to the maintenance whitelist.
*
* @param uuid uuid of the player to add
* @param name of the player to add
* @return true if adding the player was successful
*/
boolean addWhitelistedPlayer(UUID uuid, String name);
}
@@ -1,29 +0,0 @@
package eu.kennytv.maintenance.api;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
/**
* Utility class to get the {@link IMaintenance} instance for the BungeeCord version of the plugin.
* <p>
* This class is NOT available for the Spigot version!
* </p>
*
* @author KennyTV
* @since 1.0
*/
public final class MaintenanceBungeeAPI {
/**
* Returns API instance of IMaintenance.
*
* @return {@link IMaintenance} instance
*/
public static IMaintenance getAPI() {
final Plugin maintenance = ProxyServer.getInstance().getPluginManager().getPlugin("MaintenanceBungee");
if (maintenance == null)
ProxyServer.getInstance().getLogger().warning("Could not get instance of MaintenanceBungee!");
return (IMaintenance) maintenance;
}
}
@@ -1,28 +0,0 @@
package eu.kennytv.maintenance.api;
import org.bukkit.Bukkit;
/**
* Utility class to get the {@link IMaintenance} instance for the Spigot/Bukkit version of the plugin.
* <p>
* This class is NOT available for the BungeeCord version!
* </p>
*
* @author KennyTV
* @since 1.0
*/
public final class MaintenanceSpigotAPI {
/**
* Returns API instance of IMaintenance.
*
* @return {@link IMaintenance} instance
*/
public static IMaintenance getAPI() {
final org.bukkit.plugin.Plugin maintenance = Bukkit.getPluginManager().getPlugin("MaintenanceSpigot");
if (maintenance == null)
Bukkit.getLogger().warning("Could not get instance of MaintenanceSpigot!");
return (IMaintenance) maintenance;
}
}
@@ -1,114 +0,0 @@
package eu.kennytv.maintenance.core;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public abstract class MaintenanceModePlugin {
protected final String version;
protected int taskId;
protected ServerListPlusHook serverListPlusHook;
private final String prefix;
private String newestVersion;
protected MaintenanceModePlugin(final String prefix, final String version) {
this.prefix = prefix;
this.version = version;
}
public abstract void onDisable();
public abstract void setMaintenance(boolean maintenance);
public String getVersion() {
return version;
}
public boolean isTaskRunning() {
return taskId != 0;
}
public void setTaskId(final int taskId) {
this.taskId = taskId;
}
public String getNewestVersion() {
return newestVersion;
}
public abstract int schedule(Runnable runnable);
public abstract void async(Runnable runnable);
public abstract void cancelTask();
public abstract File getPluginFile();
public abstract void broadcast(String message);
public String getPrefix() {
return prefix;
}
public boolean updateAvailable() {
try {
final HttpURLConnection c = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=40699").openConnection();
final String newVersion = new BufferedReader(new InputStreamReader(c.getInputStream())).readLine().replaceAll("[a-zA-Z ]", "");
final boolean available = !newVersion.equals(version);
if (available)
newestVersion = newVersion;
return available;
} catch (final Exception ignored) {
return false;
}
}
public boolean installUpdate() {
try {
URL url = null;
try {
url = new URL("https://github.com/KennyTV/Maintenance/releases/download/" + newestVersion + "/Maintenance.jar");
} catch (final MalformedURLException e) {
e.printStackTrace();
}
final URLConnection conn = url.openConnection();
final InputStream is = new BufferedInputStream(conn.getInputStream());
final OutputStream os = new BufferedOutputStream(new FileOutputStream("plugins/Maintenance.tmp"));
final byte[] chunk = new byte[1024];
int chunkSize;
while ((chunkSize = is.read(chunk)) != -1) {
os.write(chunk, 0, chunkSize);
}
os.close();
final File newfile = new File("plugins/Maintenance.tmp");
final long newlength = newfile.length();
if (newlength <= 10000) {
newfile.delete();
return false;
} else {
final FileInputStream is2 = new FileInputStream(new File("plugins/Maintenance.tmp"));
final OutputStream os2 = new BufferedOutputStream(new FileOutputStream(getPluginFile()));
final byte[] chunk2 = new byte[1024];
int chunkSize2;
while ((chunkSize2 = is2.read(chunk2)) != -1)
os2.write(chunk2, 0, chunkSize2);
is2.close();
os2.close();
final File tmp = new File("plugins/Maintenance.tmp");
tmp.delete();
return true;
}
} catch (final IOException e) {
e.printStackTrace();
return false;
}
}
}
@@ -1,156 +0,0 @@
package eu.kennytv.maintenance.core;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public abstract class Settings {
protected final Map<UUID, String> whitelistedPlayers = Maps.newHashMap();
protected boolean maintenance;
private Set<Integer> broadcastIntervalls;
private String timerBroadcastMessage;
private String endtimerBroadcastMessage;
private String pingMessage;
private String kickMessage;
private String joinNotification;
private String noPermMessage;
private String maintenanceActivated;
private String maintenanceDeactivated;
private String playerCountMessage;
private String playerCountHoverMessage;
private boolean joinNotifications;
private boolean customMaintenanceIcon;
protected void loadSettings() {
timerBroadcastMessage = getConfigString("starttimer-broadcast-mesage");
endtimerBroadcastMessage = getConfigString("endtimer-broadcast-mesage");
pingMessage = getConfigString("pingmessage");
kickMessage = getConfigString("kickmessage");
joinNotification = getConfigString("join-notification");
noPermMessage = getConfigString("no-permission");
maintenanceActivated = getConfigString("maintenance-activated");
maintenanceDeactivated = getConfigString("maintenance-deactivated");
maintenance = getConfigBoolean("enable-maintenance-mode");
joinNotifications = getConfigBoolean("send-join-notification");
customMaintenanceIcon = getConfigBoolean("custom-maintenance-icon");
broadcastIntervalls = Sets.newHashSet(getBroadcastIntervallList());
playerCountMessage = getConfigString("playercountmessage");
playerCountHoverMessage = getConfigString("playercounthovermessage");
loadExtraSettings();
}
public abstract void saveWhitelistedPlayers();
public abstract boolean createFiles();
public abstract String getConfigString(String path);
public abstract boolean getConfigBoolean(String path);
public abstract List<Integer> getBroadcastIntervallList();
public abstract void loadExtraSettings();
public abstract void setWhitelist(String uuid, String s);
public abstract void saveConfig();
public abstract void reloadConfigs();
public abstract void setConfigBoolean(String path, boolean boo);
public String getTimerBroadcastMessage() {
return timerBroadcastMessage;
}
public String getEndtimerBroadcastMessage() {
return endtimerBroadcastMessage;
}
public String getPingMessage() {
return pingMessage;
}
public String getKickMessage() {
return kickMessage;
}
public String getJoinNotification() {
return joinNotification;
}
public String getNoPermMessage() {
return noPermMessage;
}
public String getMaintenanceActivated() {
return maintenanceActivated;
}
public String getMaintenanceDeactivated() {
return maintenanceDeactivated;
}
public String getPlayerCountMessage() {
return playerCountMessage;
}
public String getPlayerCountHoverMessage() {
return playerCountHoverMessage;
}
public void setMaintenance(final boolean maintenance) {
this.maintenance = maintenance;
}
public boolean isMaintenance() {
return maintenance;
}
public boolean isJoinNotifications() {
return joinNotifications;
}
public boolean hasCustomIcon() {
return customMaintenanceIcon;
}
public Set<Integer> getBroadcastIntervalls() {
return broadcastIntervalls;
}
public Map<UUID, String> getWhitelistedPlayers() {
return whitelistedPlayers;
}
public boolean removeWhitelistedPlayer(final UUID uuid) {
if (!whitelistedPlayers.containsKey(uuid)) return false;
whitelistedPlayers.remove(uuid);
setWhitelist(uuid.toString(), null);
saveWhitelistedPlayers();
return true;
}
@Deprecated
public boolean removeWhitelistedPlayer(final String name) {
if (!whitelistedPlayers.containsValue(name)) return false;
final UUID uuid = whitelistedPlayers.entrySet().stream().filter(entry -> entry.getValue().equals(name)).findFirst().get().getKey();
whitelistedPlayers.remove(uuid);
setWhitelist(uuid.toString(), null);
saveWhitelistedPlayers();
return true;
}
public boolean addWhitelistedPlayer(final UUID uuid, final String name) {
final boolean contains = !whitelistedPlayers.containsKey(uuid);
whitelistedPlayers.put(uuid, name);
setWhitelist(uuid.toString(), name);
saveWhitelistedPlayers();
return contains;
}
}
@@ -1,15 +0,0 @@
package eu.kennytv.maintenance.core.hook;
import net.minecrell.serverlistplus.core.ServerListPlusCore;
public final class ServerListPlusHook {
private final ServerListPlusCore serverListPlusCore;
public ServerListPlusHook(final ServerListPlusCore serverListPlusCore) {
this.serverListPlusCore = serverListPlusCore;
}
public void setEnabled(final boolean enable) {
serverListPlusCore.getProfiles().setEnabled(enable);
}
}
@@ -1,34 +0,0 @@
package eu.kennytv.maintenance.core.runnable;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
public final class MaintenanceRunnable implements Runnable {
private final MaintenanceModePlugin plugin;
private final Settings settings;
private final boolean enable;
private int minutes;
public MaintenanceRunnable(final MaintenanceModePlugin plugin, final Settings settings, final int minutes, final boolean enable) {
this.plugin = plugin;
this.settings = settings;
this.minutes = minutes;
this.enable = enable;
}
@Override
public void run() {
if (minutes <= 0) {
plugin.setMaintenance(enable);
plugin.cancelTask();
} else if (settings.getBroadcastIntervalls().contains(minutes)) {
if (enable)
plugin.broadcast(settings.getTimerBroadcastMessage().replaceAll("%MINUTES%", String.valueOf(minutes)));
else
plugin.broadcast(settings.getEndtimerBroadcastMessage().replaceAll("%MINUTES%", String.valueOf(minutes)));
}
minutes--;
}
}
@@ -1,13 +0,0 @@
package eu.kennytv.maintenance.core.util;
public final class MessageUtil {
public static boolean isNumeric(final String string) {
try {
Integer.parseInt(string);
} catch (final NumberFormatException nfe) {
return false;
}
return true;
}
}
@@ -1 +0,0 @@
a8179ff3-c201-4a75-bdaa-9d14aca6f83f: KennyTV
Binary file not shown.
@@ -1,27 +0,0 @@
package eu.kennytv.maintenance.bungee;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.File;
/**
* @author KennyTV
* @since 2.1
*/
public final class MaintenanceBungeeBase extends Plugin {
private MaintenanceBungeePlugin plugin;
@Override
public void onEnable() {
plugin = new MaintenanceBungeePlugin(this);
}
@Override
public void onDisable() {
plugin.onDisable();
}
File getPluginFile() {
return getFile();
}
}
@@ -1,127 +0,0 @@
package eu.kennytv.maintenance.bungee;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.ISettings;
import eu.kennytv.maintenance.api.MaintenanceBungeeAPI;
import eu.kennytv.maintenance.bungee.command.MaintenanceBungeeCommand;
import eu.kennytv.maintenance.bungee.listener.PostLoginListener;
import eu.kennytv.maintenance.bungee.listener.ProxyPingListener;
import eu.kennytv.maintenance.bungee.metrics.MetricsLite;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;
import net.minecrell.serverlistplus.core.plugin.ServerListPlusPlugin;
import java.io.File;
import java.util.concurrent.TimeUnit;
/**
* @author KennyTV
* @since 1.0
*/
public final class MaintenanceBungeePlugin extends MaintenanceModePlugin implements IMaintenance {
private final MaintenanceBungeeBase plugin;
private final SettingsBungee settings;
MaintenanceBungeePlugin(final MaintenanceBungeeBase plugin) {
super("§8[§eMaintenanceBungee§8] ", plugin.getDescription().getVersion());
this.plugin = plugin;
plugin.getLogger().info("Plugin by KennyTV");
settings = new SettingsBungee(plugin);
final PluginManager pm = getProxy().getPluginManager();
pm.registerListener(plugin, new PostLoginListener(this, settings));
pm.registerListener(plugin, new ProxyPingListener(plugin, settings));
pm.registerCommand(plugin, new MaintenanceBungeeCommand(this, settings));
new MetricsLite(plugin);
// ServerListPlus integration
final Plugin serverListPlus = pm.getPlugin("ServerListPlus");
if (serverListPlus != null) {
serverListPlusHook = new ServerListPlusHook(((ServerListPlusPlugin) serverListPlus).getCore());
plugin.getLogger().info("Enabled ServerListPlus integration!");
}
}
@Override
public void onDisable() {
if (settings.getMySQL() != null)
settings.getMySQL().close();
}
@Override
public void setMaintenance(final boolean maintenance) {
if (settings.getMySQL() != null) {
settings.setMaintenanceToSQL(maintenance);
} else {
settings.setMaintenance(maintenance);
settings.setConfigBoolean("enable-maintenance-mode", maintenance);
settings.saveConfig();
settings.reloadConfigs();
}
if (serverListPlusHook != null)
serverListPlusHook.setEnabled(!maintenance);
if (isTaskRunning())
cancelTask();
if (maintenance) {
getProxy().getPlayers().stream()
.filter(p -> !p.hasPermission("maintenance.bypass") && !settings.getWhitelistedPlayers().containsKey(p.getUniqueId()))
.forEach(p -> p.disconnect(settings.getKickMessage().replace("%NEWLINE%", "\n")));
getProxy().broadcast(settings.getMaintenanceActivated());
} else
getProxy().broadcast(settings.getMaintenanceDeactivated());
}
@Override
public boolean isMaintenance() {
return settings.isMaintenance();
}
@Override
public int schedule(final Runnable runnable) {
return getProxy().getScheduler().schedule(plugin, runnable, 0, 1, TimeUnit.MINUTES).getId();
}
@Override
public void async(final Runnable runnable) {
getProxy().getScheduler().runAsync(plugin, runnable);
}
@Override
public void cancelTask() {
getProxy().getScheduler().cancel(taskId);
setTaskId(0);
}
@Override
public ISettings getSettings() {
return settings;
}
@Override
public File getPluginFile() {
return plugin.getPluginFile();
}
@Override
public void broadcast(final String message) {
getProxy().broadcast(message);
}
@Deprecated
public static IMaintenance getAPI() {
return MaintenanceBungeeAPI.getAPI();
}
public ProxyServer getProxy() {
return plugin.getProxy();
}
}
@@ -1,173 +0,0 @@
package eu.kennytv.maintenance.bungee;
import eu.kennytv.maintenance.api.ISettings;
import eu.kennytv.maintenance.bungee.mysql.MySQL;
import eu.kennytv.maintenance.core.Settings;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.YamlConfiguration;
import java.io.*;
import java.nio.file.Files;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
public final class SettingsBungee extends Settings implements ISettings {
private static final String UPDATE = "INSERT INTO %s (setting, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = ?";
private final MaintenanceBungeeBase plugin;
private final MySQL mySQL;
private final String mySQLTable;
private Configuration config;
private Configuration whitelist;
SettingsBungee(final MaintenanceBungeeBase plugin) {
this.plugin = plugin;
reloadConfigs(createFiles());
final Configuration mySQLSection = config.getSection("mysql");
if (mySQLSection.getBoolean("use-mysql", false)) {
// Needed: One column named "setting" (primary key), another named "value".
plugin.getLogger().info("Trying to open database connection...");
mySQL = new MySQL(mySQLSection.getString("host"),
mySQLSection.getInt("port"),
mySQLSection.getString("username"),
mySQLSection.getString("password"),
mySQLSection.getString("database"));
mySQLTable = mySQLSection.getString("table");
plugin.getLogger().info("Done!");
} else {
mySQL = null;
mySQLTable = null;
}
}
@Override
public void reloadConfigs() {
reloadConfigs(false);
}
@Override
public void saveConfig() {
final File file = new File(plugin.getDataFolder(), "bungee-config.yml");
try {
YamlConfiguration.getProvider(YamlConfiguration.class).save(config, new OutputStreamWriter(new FileOutputStream(file), "UTF8"));
} catch (final IOException e) {
throw new RuntimeException("Unable to save bungee-config.yml!", e);
}
}
@Override
public void saveWhitelistedPlayers() {
final File file = new File(plugin.getDataFolder(), "WhitelistedPlayers.yml");
try {
YamlConfiguration.getProvider(YamlConfiguration.class).save(whitelist, file);
} catch (final IOException e) {
throw new RuntimeException("Unable to save WhitelistedPlayers.yml!", e);
}
}
private void reloadConfigs(final boolean createdNewWhitelist) {
final File file = new File(plugin.getDataFolder(), "bungee-config.yml");
try {
config = YamlConfiguration.getProvider(YamlConfiguration.class).load(new InputStreamReader(new FileInputStream(file), "UTF8"));
whitelist = YamlConfiguration.getProvider(YamlConfiguration.class).load(new File(plugin.getDataFolder(), "WhitelistedPlayers.yml"));
} catch (final IOException e) {
throw new RuntimeException("Unable to load bungee-config.yml!", e);
}
if (createdNewWhitelist) {
whitelist.set("a8179ff3-c201-4a75-bdaa-9d14aca6f83f", "KennyTV");
saveWhitelistedPlayers();
}
loadSettings();
}
@Override
public void loadExtraSettings() {
whitelistedPlayers.clear();
whitelist.getKeys().forEach(key -> whitelistedPlayers.put(UUID.fromString(key), whitelist.getString(key)));
}
@Override
public void setWhitelist(final String uuid, final String s) {
whitelist.set(uuid, s);
}
@Override
public boolean createFiles() {
if (!plugin.getDataFolder().exists())
plugin.getDataFolder().mkdirs();
final File file = new File(plugin.getDataFolder(), "bungee-config.yml");
if (!file.exists()) {
try (final InputStream in = plugin.getResourceAsStream("bungee-config.yml")) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
throw new RuntimeException("Unable to create bungee-config.yml file for MaintenanceBungee", e);
}
}
boolean createdNewWhitelist = false;
final File whitelistFile = new File(plugin.getDataFolder(), "WhitelistedPlayers.yml");
if (!whitelistFile.exists()) {
createdNewWhitelist = true;
try {
whitelistFile.createNewFile();
} catch (final IOException e) {
throw new RuntimeException("Unable to create WhitelistedPlayers.yml file for MaintenanceBungee", e);
}
}
return createdNewWhitelist;
}
@Override
public String getConfigString(final String path) {
return ChatColor.translateAlternateColorCodes('&', config.getString(path));
}
@Override
public boolean getConfigBoolean(final String path) {
return config.getBoolean(path);
}
@Override
public List<Integer> getBroadcastIntervallList() {
return config.getIntList("timer-broadcasts-for-minutes");
}
@Override
public void setConfigBoolean(final String path, final boolean var) {
config.set(path, var);
}
@Override
public boolean isMaintenance() {
if (mySQL != null) {
mySQL.executeQuery("SELECT * FROM " + mySQLTable + " WHERE setting LIKE ?", rs -> {
try {
maintenance = rs.next() && Boolean.parseBoolean(rs.getString("value"));
} catch (final SQLException e) {
e.printStackTrace();
}
}, "maintenance");
}
return maintenance;
}
public void setMaintenanceToSQL(final boolean maintenance) {
plugin.getProxy().getScheduler().runAsync(plugin, () ->
mySQL.executeUpdate(String.format(UPDATE, mySQLTable), res -> {
}, "maintenance", String.valueOf(maintenance), String.valueOf(maintenance)));
this.maintenance = maintenance;
}
public MySQL getMySQL() {
return mySQL;
}
}
@@ -1,198 +0,0 @@
package eu.kennytv.maintenance.bungee.command;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.bungee.SettingsBungee;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
import eu.kennytv.maintenance.core.util.MessageUtil;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
import java.util.Map;
import java.util.UUID;
public final class MaintenanceBungeeCommand extends Command {
private final MaintenanceBungeePlugin plugin;
private final SettingsBungee settings;
public MaintenanceBungeeCommand(final MaintenanceBungeePlugin plugin, final SettingsBungee settings) {
super("maintenance", "", "maintenancebungee");
this.plugin = plugin;
this.settings = settings;
}
public void execute(final CommandSender sender, final String[] args) {
if (!sender.hasPermission("maintenance.admin")) {
sender.sendMessage(settings.getNoPermMessage());
return;
}
if (args.length == 1) {
if (args[0].equalsIgnoreCase("on")) {
plugin.setMaintenance(true);
} else if (args[0].equalsIgnoreCase("off")) {
plugin.setMaintenance(false);
} else if (args[0].equalsIgnoreCase("reload")) {
if (!sender.hasPermission("maintenance.reload")) {
sender.sendMessage(settings.getNoPermMessage());
return;
}
settings.reloadConfigs();
sender.sendMessage(plugin.getPrefix() + "§aReloaded config.yml");
} else if (args[0].equalsIgnoreCase("update")) {
if (!sender.hasPermission("maintenance.admin")) {
sender.sendMessage(settings.getNoPermMessage());
return;
}
checkForUpdate(sender);
} else if (args[0].equals("forceupdate")) {
if (!sender.hasPermission("maintenance.admin")) {
sender.sendMessage(settings.getNoPermMessage());
return;
}
sender.sendMessage(plugin.getPrefix() + "§c§lDownloading update...");
if (plugin.installUpdate())
sender.sendMessage(plugin.getPrefix() + "§a§lThe update was successful! To prevent issues with tasks and to complete the update, you have to restart the proxy!");
else
sender.sendMessage(plugin.getPrefix() + "§4Failed!");
} else if (args[0].equalsIgnoreCase("whitelist")) {
final Map<UUID, String> players = settings.getWhitelistedPlayers();
if (players.isEmpty()) {
sender.sendMessage(plugin.getPrefix() + "§cThe maintenance whitelist is empty! Use \"/maintenance add <player>\" to add someone!");
} else if (players.size() == 1 && players.containsKey(UUID.fromString("a8179ff3-c201-4a75-bdaa-9d14aca6f83f"))) {
sender.sendMessage(plugin.getPrefix() + "§cUse \"/maintenance add <player>\" to add someone. Alternatively, you can add the uuid of a player to the WhitelistedPlayers.yml as seen in the example in the file!");
} else {
sender.sendMessage("§6Whitelisted players for maintenance:");
players.forEach((key, value) -> sender.sendMessage("§8- §e" + value));
sender.sendMessage("");
}
} else
sendUsage(sender);
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("endtimer")) {
if (!MessageUtil.isNumeric(args[1])) {
sender.sendMessage(plugin.getPrefix() + "§6/maintenance timer endtimer <minutes>");
return;
}
if (plugin.isTaskRunning()) {
sender.sendMessage(plugin.getPrefix() + "§cThere's already a starttimer scheduled!");
return;
}
final int minutes = Integer.parseInt(args[1]);
if (minutes > 40320) {
sender.sendMessage(plugin.getPrefix() + "§cThe number has to be less than 40320 (28 days)!");
return;
}
if (minutes < 1) {
sender.sendMessage(plugin.getPrefix() + "§cThink about running a timer for a negative amount of minutes. Doesn't work §othat §r§cwell.");
return;
}
plugin.setMaintenance(true);
sender.sendMessage(plugin.getPrefix() + "§aStarted timer: §7Maintenance mode will be deactivated in §6" + minutes + " minutes§7.");
plugin.setTaskId(plugin.schedule(new MaintenanceRunnable(plugin, settings, minutes, false)));
} else if (args[0].equalsIgnoreCase("starttimer")) {
if (!MessageUtil.isNumeric(args[1])) {
sender.sendMessage(plugin.getPrefix() + "§6/maintenance timer starttimer <minutes>");
return;
}
if (plugin.isTaskRunning()) {
sender.sendMessage(plugin.getPrefix() + "§cThere's already running a timer!");
return;
}
final int minutes = Integer.parseInt(args[1]);
if (minutes > 40320) {
sender.sendMessage(plugin.getPrefix() + "§cThe number has to be less than 40320 (28 days)!");
return;
}
if (minutes < 1) {
sender.sendMessage(plugin.getPrefix() + "§cThink about running a timer for a negative amount of minutes. Doesn't work §othat §r§cwell.");
return;
}
sender.sendMessage(plugin.getPrefix() + "§aStarted timer: §7Maintenance mode will be activated in §6" + minutes + " minutes§7.");
plugin.setTaskId(plugin.schedule(new MaintenanceRunnable(plugin, settings, minutes, true)));
} else if (args[0].equalsIgnoreCase("timer")) {
if (args[1].equalsIgnoreCase("abort") || args[1].equalsIgnoreCase("stop") || args[1].equalsIgnoreCase("cancel")) {
if (!plugin.isTaskRunning()) {
sender.sendMessage(plugin.getPrefix() + "§cThere's currently no running timer.");
return;
}
plugin.cancelTask();
sender.sendMessage(plugin.getPrefix() + "§cThe timer has been disabled.");
} else
sendUsage(sender);
} else if (args[0].equalsIgnoreCase("add")) {
final ProxiedPlayer player = plugin.getProxy().getPlayer(args[1]);
if (player == null) {
sender.sendMessage(plugin.getPrefix() + "§cThere's no player online with that name.");
return;
}
if (settings.addWhitelistedPlayer(player.getUniqueId(), player.getName()))
sender.sendMessage(plugin.getPrefix() + "§aAdded §b" + player.getName() + " §ato the maintenance whitelist!");
else
sender.sendMessage(plugin.getPrefix() + "§b" + player.getName() + " §calready is in the maintenance whitelist!");
} else if (args[0].equalsIgnoreCase("remove")) {
final ProxiedPlayer player = plugin.getProxy().getPlayer(args[1]);
if (player == null) {
if (settings.removeWhitelistedPlayer(args[1].toLowerCase()))
sender.sendMessage(plugin.getPrefix() + "§aRemoved §b" + args[1].toLowerCase() + " §afrom the maintenance whitelist!");
else
sender.sendMessage(plugin.getPrefix() + "§cThere is no player with that name in the maintenance whitelist!");
return;
}
if (settings.removeWhitelistedPlayer(player.getUniqueId()))
sender.sendMessage(plugin.getPrefix() + "§aRemoved §b" + player.getName() + " §afrom the maintenance whitelist!");
else
sender.sendMessage(plugin.getPrefix() + "§cThis player is not in the maintenance whitelist!");
} else
sendUsage(sender);
} else
sendUsage(sender);
}
private void sendUsage(final CommandSender sender) {
sender.sendMessage("");
sender.sendMessage("§8===========[ §eMaintenanceBungee §8| §eVersion: §e" + plugin.getVersion() + " §8]===========");
sender.sendMessage("§6/maintenance reload §7(Reloads the config file)");
sender.sendMessage("§6/maintenance on §7(Enables maintenance mode");
sender.sendMessage("§6/maintenance off §7(Disables maintenance mode)");
sender.sendMessage("§6/maintenance starttimer <minutes> §7(After the given time in minutes, maintenance mode will be enabled. Broadcast settings for the timer can be found in the config)");
sender.sendMessage("§6/maintenance endtimer <minutes> §7(Enables maintenance mode. After the given time in minutes, maintenance mode will be disabled)");
sender.sendMessage("§6/maintenance timer abort §7(If running, the current timer will be aborted)");
sender.sendMessage("§6/maintenance add <player> §7(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)");
sender.sendMessage("§6/maintenance remove <player> §7(Removes the player from the maintenance whitelist)");
sender.sendMessage("§6/maintenance whitelist §7(Shows all whitelisted players for the maintenance mode)");
sender.sendMessage("§6/maintenance update §7(Remotely downloads the newest version of the plugin onto your server)");
sender.sendMessage("§9Created by: KennyTV");
sender.sendMessage("§8===========[ §eMaintenanceBungee §8| §eVersion: §e" + plugin.getVersion() + " §8]===========");
sender.sendMessage("");
}
private void checkForUpdate(final CommandSender sender) {
if (plugin.updateAvailable()) {
sender.sendMessage(plugin.getPrefix() + "§cNewest version available: §aVersion " + plugin.getNewestVersion() + "§c, you're still on §a" + plugin.getVersion());
sender.sendMessage(plugin.getPrefix() + "§c§lWARNING: §cYou will have to restart the proxy to prevent further issues and to complete the update!" +
" If you can't do that, don't update!");
final TextComponent tc = new TextComponent("§6× §8[§aUpdate§8]");
tc.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/maintenance forceupdate"));
tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText("§aClick here to update the plugin")));
tc.addExtra(" §8< §7Or use the command §c/maintenace forceupdate");
sender.sendMessage(tc);
} else
sender.sendMessage(plugin.getPrefix() + "§aYou already have the latest version of the plugin!");
}
}
@@ -1,58 +0,0 @@
package eu.kennytv.maintenance.bungee.listener;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.bungee.SettingsBungee;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
public final class PostLoginListener implements Listener {
private final MaintenanceBungeePlugin plugin;
private final SettingsBungee settings;
public PostLoginListener(final MaintenanceBungeePlugin plugin, final SettingsBungee settings) {
this.plugin = plugin;
this.settings = settings;
}
@EventHandler(priority = EventPriority.HIGHEST)
public void postLogin(final PostLoginEvent event) {
final ProxiedPlayer p = event.getPlayer();
if (p.getUniqueId().toString().equals("a8179ff3-c201-4a75-bdaa-9d14aca6f83f"))
p.sendMessage("§6MaintenanceBungee §aVersion " + plugin.getVersion());
else if (settings.isMaintenance()) {
if (!p.hasPermission("maintenance.bypass") && !settings.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
p.disconnect(settings.getKickMessage().replace("%NEWLINE%", "\n"));
if (settings.isJoinNotifications())
plugin.getProxy().getPlayers().stream().filter(player -> player.hasPermission("maintenance.joinnotification"))
.forEach(player -> player.sendMessage(settings.getJoinNotification().replace("%PLAYER%", p.getName())));
return;
}
}
if (!p.hasPermission("maintenance.admin")) return;
plugin.async(() -> {
if (plugin.updateAvailable()) {
p.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + plugin.getNewestVersion() + "§c, you're still on §a" + plugin.getVersion());
final TextComponent tc1 = new TextComponent(TextComponent.fromLegacyText(plugin.getPrefix() + " "));
final TextComponent tc2 = new TextComponent(TextComponent.fromLegacyText("§cDownload it at: §6https://www.spigotmc.org/resources/maintenancemode.40699/"));
final TextComponent click = new TextComponent(TextComponent.fromLegacyText(" §7§l§o(CLICK ME)"));
click.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/maintenancemode.40699/"));
click.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("§aDownload the latest version").create()));
tc1.addExtra(tc2);
tc1.addExtra(click);
p.sendMessage(tc1);
}
});
}
}
@@ -1,51 +0,0 @@
package eu.kennytv.maintenance.bungee.listener;
import eu.kennytv.maintenance.bungee.MaintenanceBungeeBase;
import eu.kennytv.maintenance.bungee.SettingsBungee;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
public final class ProxyPingListener implements Listener {
private final MaintenanceBungeeBase plugin;
private final SettingsBungee settings;
private final File icon;
private Favicon favicon;
public ProxyPingListener(final MaintenanceBungeeBase plugin, final SettingsBungee settings) {
this.plugin = plugin;
this.settings = settings;
icon = new File("maintenance-icon.png");
}
@EventHandler(priority = EventPriority.HIGHEST)
public void proxyPing(final ProxyPingEvent event) {
if (!settings.isMaintenance()) return;
final ServerPing ping = event.getResponse();
ping.setVersion(new ServerPing.Protocol(settings.getPlayerCountMessage(), 1));
ping.setDescription(settings.getPingMessage().replace("%NEWLINE%", "\n"));
ping.setPlayers(new ServerPing.Players(0, 0, new ServerPing.PlayerInfo[]{
new ServerPing.PlayerInfo(settings.getPlayerCountHoverMessage().replace("%NEWLINE%", "\n"), "")
}));
if (settings.hasCustomIcon()) {
if (favicon != null)
ping.setFavicon(favicon);
else {
try {
favicon = Favicon.create(ImageIO.read(icon));
} catch (IOException | IllegalArgumentException e) {
plugin.getLogger().warning("§4Could not load 'maintenance-icon.png' - did you create one in your Bungee folder (not the plugins folder)?");
}
}
}
}
}
@@ -1,49 +0,0 @@
# MaintenanceBungee Plugin by KennyTV
# Version ${project.version}
# Enables maintenance-mode.
enable-maintenance-mode: false
# The message shown in the multiplayer server list motd.
pingmessage: "&cMaintenance mode!%NEWLINE%&6We will be back soon!"
# Is shown at the top right corner of the server in the serverlist,
# where the playercount would normally be displayed.
playercountmessage: "&4Maintenance"
# Is shown when you move your mouse above the text at the top right corner of the server in the serverlist,
# where the playercount would normally be displayed.
playercounthovermessage: "&cCurrently under%NEWLINE%&cmaintenance"
# Will be shown, when a player tries to join on the server without the permission.
kickmessage: "&cThe server is currently under maintenance!%NEWLINE%Try again later!"
# Some self explanatory messages
no-permission: "&cYou do not have the permission to execute that command."
maintenance-activated: "&6Maintenance mode is now activated."
maintenance-deactivated: "&6Maintenance mode is now deactivated."
starttimer-broadcast-mesage: '&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%MINUTES% minutes&7.'
endtimer-broadcast-mesage: '&8[&eMaintenance&8] &7Maintenance mode will be disabled in &6%MINUTES% minutes&7.'
# If using the timer command: In what intervalls before enabling/disabling maintenance there will be a broadcast.
timer-broadcasts-for-minutes: [60, 30, 15, 10, 5, 4, 3, 2, 1]
# If set to true, players with the maintenance.joinnotification permission will receive a message,
# that a player tried to join the server while maintenance is enabled.
send-join-notification: false
join-notification: "&e%PLAYER% &ctried to join the server."
# If set to true, the server icon will be changed to maintenance-icon.png in the Bungee main/base-folder.
custom-maintenance-icon: false
# Only enable MySQL if you really know what you are doing.
# You need to have a table with the two following columns: 'setting' and 'value'.
mysql:
use-mysql: false
host: host
port: 3306
database: database
table: tablename
username: username
password: password
@@ -1,6 +0,0 @@
name: ${project.name}
version: ${project.version}
main: eu.kennytv.maintenance.bungee.MaintenanceBungeeBase
author: KennyTV
softDepends: [ServerListPlus]
website: https://www.spigotmc.org/resources/maintenancemode.40699/
-53
View File
@@ -1,53 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-base</artifactId>
<version>2.2</version>
</parent>
<artifactId>maintenancespigot</artifactId>
<name>MaintenanceSpigot</name>
<repositories>
<repository>
<id>spigotmc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/nexus/repository/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-core</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.minecrell</groupId>
<artifactId>ServerListPlus</artifactId>
<version>3.4.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-API</artifactId>
<version>4.3.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -1,27 +0,0 @@
package eu.kennytv.maintenance.spigot;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
/**
* @author KennyTV
* @since 2.1
*/
public final class MaintenanceSpigotBase extends JavaPlugin {
private MaintenanceSpigotPlugin plugin;
@Override
public void onEnable() {
plugin = new MaintenanceSpigotPlugin(this);
}
@Override
public void onDisable() {
plugin.onDisable();
}
File getPluginFile() {
return getFile();
}
}
@@ -1,135 +0,0 @@
package eu.kennytv.maintenance.spigot;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.ISettings;
import eu.kennytv.maintenance.api.MaintenanceSpigotAPI;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import eu.kennytv.maintenance.spigot.command.MaintenanceSpigotCommand;
import eu.kennytv.maintenance.spigot.listener.PacketListener;
import eu.kennytv.maintenance.spigot.listener.PlayerLoginListener;
import eu.kennytv.maintenance.spigot.listener.ServerListPingListener;
import eu.kennytv.maintenance.spigot.metrics.MetricsLite;
import net.minecrell.serverlistplus.core.plugin.ServerListPlusPlugin;
import org.bukkit.Server;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import java.io.File;
/**
* @author KennyTV
* @since 1.0
*/
public final class MaintenanceSpigotPlugin extends MaintenanceModePlugin implements IMaintenance {
private final MaintenanceSpigotBase plugin;
private final SettingsSpigot settings;
// Great update for the Spigot version of the plugin as well as performance improvements and bugfixes in both versions!
// If you have ProtocolLib installed, you can set a custom server icon while maintenance is enabled, also the playercount-message and the playercount-hover-message are now available (as it has already been in the Bungee version)!
// The Spigot version is now much more compatible with other motd-changing plugins, such as SexyMotd!
// In the BungeeCord version of the plugin, the "/maintenance remove <player>" command now also works for offline players
// Fixed some other issues with the ProtocolLib integration
// Minor textfix for the updatemessage in the Spigot version
// General performance improvements
MaintenanceSpigotPlugin(final MaintenanceSpigotBase plugin) {
super("§8[§eMaintenanceSpigot§8] ", plugin.getDescription().getVersion());
this.plugin = plugin;
settings = new SettingsSpigot(plugin);
plugin.getLogger().info("Plugin by KennyTV");
plugin.getCommand("maintenancespigot").setExecutor(new MaintenanceSpigotCommand(this, settings));
final PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new PlayerLoginListener(this, settings), plugin);
new MetricsLite(plugin);
if (pm.getPlugin("ProtocolLib") != null)
new PacketListener(this, plugin, settings);
else
pm.registerEvents(new ServerListPingListener(plugin, settings), plugin);
// ServerListPlus integration
final Plugin serverListPlus = pm.getPlugin("ServerListPlus");
if (serverListPlus != null) {
serverListPlusHook = new ServerListPlusHook(((ServerListPlusPlugin) serverListPlus).getCore());
plugin.getLogger().info("Enabled ServerListPlus integration!");
}
}
@Override
public void onDisable() {
if (!getServer().getOnlinePlayers().isEmpty())
plugin.getLogger().warning("This plugin does not fully support reloads, consider restarting the server as soon as possible.");
}
@Override
public void setMaintenance(final boolean maintenance) {
settings.setMaintenance(maintenance);
settings.setConfigBoolean("enable-maintenance-mode", maintenance);
settings.saveConfig();
settings.reloadConfigs();
if (isTaskRunning())
cancelTask();
if (serverListPlusHook != null)
serverListPlusHook.setEnabled(!maintenance);
if (maintenance) {
getServer().getOnlinePlayers().stream()
.filter(p -> !p.hasPermission("maintenance.bypass") && !settings.getWhitelistedPlayers().containsKey(p.getUniqueId()))
.forEach(p -> p.kickPlayer(settings.getKickMessage().replace("%NEWLINE%", "\n")));
getServer().broadcastMessage(settings.getMaintenanceActivated());
} else
getServer().broadcastMessage(settings.getMaintenanceDeactivated());
}
@Override
public boolean isMaintenance() {
return settings.isMaintenance();
}
@Override
public int schedule(final Runnable runnable) {
return getServer().getScheduler().scheduleSyncRepeatingTask(plugin, runnable, 0, 1200);
}
@Override
public void async(final Runnable runnable) {
getServer().getScheduler().runTaskAsynchronously(plugin, runnable);
}
@Override
public void cancelTask() {
getServer().getScheduler().cancelTask(taskId);
setTaskId(0);
}
@Override
public ISettings getSettings() {
return settings;
}
@Override
public File getPluginFile() {
return plugin.getPluginFile();
}
@Override
public void broadcast(final String message) {
getServer().broadcastMessage(message);
}
@Deprecated
public static IMaintenance getAPI() {
return MaintenanceSpigotAPI.getAPI();
}
public Server getServer() {
return plugin.getServer();
}
}
@@ -1,111 +0,0 @@
package eu.kennytv.maintenance.spigot;
import eu.kennytv.maintenance.api.ISettings;
import eu.kennytv.maintenance.core.Settings;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.*;
import java.nio.file.Files;
import java.util.List;
import java.util.UUID;
public final class SettingsSpigot extends Settings implements ISettings {
private final MaintenanceSpigotBase plugin;
private FileConfiguration config;
private FileConfiguration whitelist;
SettingsSpigot(final MaintenanceSpigotBase plugin) {
this.plugin = plugin;
createFiles();
reloadConfigs();
}
@Override
public void saveConfig() {
try {
config.save(new File(plugin.getDataFolder(), "spigot-config.yml"));
} catch (final IOException e) {
e.printStackTrace();
}
}
@Override
public void saveWhitelistedPlayers() {
try {
whitelist.save(new File(plugin.getDataFolder(), "WhitelistedPlayers.yml"));
} catch (final IOException e) {
e.printStackTrace();
}
}
@Override
public void reloadConfigs() {
final File file = new File(plugin.getDataFolder(), "spigot-config.yml");
try {
config = YamlConfiguration.loadConfiguration(new InputStreamReader(new FileInputStream(file), "UTF8"));
whitelist = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), "WhitelistedPlayers.yml"));
} catch (final IOException e) {
throw new RuntimeException("Unable to load spigot-config.yml!", e);
}
loadSettings();
}
@Override
public void loadExtraSettings() {
whitelistedPlayers.clear();
whitelist.getKeys(false).forEach(key -> whitelistedPlayers.put(UUID.fromString(key), whitelist.getString(key)));
}
@Override
public void setWhitelist(final String uuid, final String s) {
whitelist.set(uuid, s);
}
@Override
public boolean createFiles() {
if (!plugin.getDataFolder().exists())
plugin.getDataFolder().mkdirs();
final File file = new File(plugin.getDataFolder(), "spigot-config.yml");
if (!file.exists()) {
try (final InputStream in = plugin.getResource("spigot-config.yml")) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
throw new RuntimeException("Unable to create spigot-config.yml file for Maintenance!", e);
}
}
final File whitelistFile = new File(plugin.getDataFolder(), "WhitelistedPlayers.yml");
if (!whitelistFile.exists()) {
try (final InputStream in = plugin.getResource("WhitelistedPlayers.yml")) {
Files.copy(in, whitelistFile.toPath());
} catch (final IOException e) {
throw new RuntimeException("Unable to create WhitelistedPlayers.yml file for Maintenance!", e);
}
}
return true;
}
@Override
public String getConfigString(final String path) {
return ChatColor.translateAlternateColorCodes('&', config.getString(path));
}
@Override
public boolean getConfigBoolean(final String path) {
return config.getBoolean(path);
}
@Override
public List<Integer> getBroadcastIntervallList() {
return config.getIntegerList("timer-broadcasts-for-minutes");
}
@Override
public void setConfigBoolean(final String path, final boolean var) {
config.set(path, var);
}
}
@@ -1,206 +0,0 @@
package eu.kennytv.maintenance.spigot.command;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
import eu.kennytv.maintenance.core.util.MessageUtil;
import eu.kennytv.maintenance.spigot.MaintenanceSpigotPlugin;
import eu.kennytv.maintenance.spigot.SettingsSpigot;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Map;
import java.util.UUID;
public final class MaintenanceSpigotCommand implements CommandExecutor {
private final MaintenanceSpigotPlugin plugin;
private final SettingsSpigot settings;
public MaintenanceSpigotCommand(final MaintenanceSpigotPlugin plugin, final SettingsSpigot settings) {
this.plugin = plugin;
this.settings = settings;
}
@Override
public boolean onCommand(final CommandSender sender, final Command cmd, final String s, final String[] args) {
if (!sender.hasPermission("maintenance.admin")) {
sender.sendMessage(settings.getNoPermMessage());
return true;
}
if (args.length == 1) {
if (args[0].equalsIgnoreCase("on")) {
plugin.setMaintenance(true);
} else if (args[0].equalsIgnoreCase("off")) {
plugin.setMaintenance(false);
} else if (args[0].equalsIgnoreCase("reload")) {
if (!sender.hasPermission("maintenance.reload")) {
sender.sendMessage(settings.getNoPermMessage());
return true;
}
settings.reloadConfigs();
sender.sendMessage(plugin.getPrefix() + "§aReloaded spigot-config.yml");
} else if (args[0].equalsIgnoreCase("update")) {
if (!sender.hasPermission("maintenance.admin")) {
sender.sendMessage(settings.getNoPermMessage());
return true;
}
checkForUpdate(sender);
} else if (args[0].equals("forceupdate")) {
if (!sender.hasPermission("maintenance.admin")) {
sender.sendMessage(settings.getNoPermMessage());
return true;
}
sender.sendMessage(plugin.getPrefix() + "§c§lDownloading update...");
if (plugin.installUpdate())
sender.sendMessage(plugin.getPrefix() + "§a§lThe update was successful! To prevent issues with tasks and to complete the update, you have to restart the server!");
else
sender.sendMessage(plugin.getPrefix() + "§4Failed!");
} else if (args[0].equalsIgnoreCase("whitelist")) {
final Map<UUID, String> players = settings.getWhitelistedPlayers();
if (players.isEmpty()) {
sender.sendMessage(plugin.getPrefix() + "§cThe maintenance whitelist is empty! Use \"/maintenance add <player>\" to add someone!");
} else if (players.size() == 1 && players.containsKey(UUID.fromString("a8179ff3-c201-4a75-bdaa-9d14aca6f83f"))) {
sender.sendMessage(plugin.getPrefix() + "§cUse \"/maintenance add <player>\" to add someone. Alternatively, you can add the uuid of a player to the WhitelistedPlayers.yml as seen in the example in the file!");
} else {
sender.sendMessage("§6Whitelisted players for maintenance:");
players.forEach((key, value) -> sender.sendMessage("§8- §e" + value));
sender.sendMessage("");
}
} else
sendUsage(sender);
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("endtimer")) {
if (!MessageUtil.isNumeric(args[1])) {
sender.sendMessage(plugin.getPrefix() + "§6/maintenance timer endtimer <minutes>");
return true;
}
if (plugin.isTaskRunning()) {
sender.sendMessage(plugin.getPrefix() + "§cThere's already a starttimer scheduled!");
return true;
}
final int minutes = Integer.parseInt(args[1]);
if (minutes > 40320) {
sender.sendMessage(plugin.getPrefix() + "§cThe number has to be less than 40320 (28 days)!");
return true;
}
if (minutes < 1) {
sender.sendMessage(plugin.getPrefix() + "§cThink about running a timer for a negative amount of minutes. Doesn't work §othat §r§cwell.");
return true;
}
plugin.setMaintenance(true);
sender.sendMessage(plugin.getPrefix() + "§aStarted timer: §7Maintenance mode will be deactivated in §6" + minutes + " minutes§7.");
plugin.setTaskId(plugin.schedule(new MaintenanceRunnable(plugin, settings, minutes, false)));
} else if (args[0].equalsIgnoreCase("starttimer")) {
if (!MessageUtil.isNumeric(args[1])) {
sender.sendMessage(plugin.getPrefix() + "§6/maintenance timer starttimer <minutes>");
return true;
}
if (plugin.isTaskRunning()) {
sender.sendMessage(plugin.getPrefix() + "§cThere's already running a timer!");
return true;
}
final int minutes = Integer.parseInt(args[1]);
if (minutes > 40320) {
sender.sendMessage(plugin.getPrefix() + "§cThe number has to be less than 40320 (28 days)!");
return true;
}
if (minutes < 1) {
sender.sendMessage(plugin.getPrefix() + "§cThink about running a timer for a negative amount of minutes. Doesn't work §othat §r§cwell.");
return true;
}
sender.sendMessage(plugin.getPrefix() + "§aStarted timer: §7Maintenance mode will be activated in §6" + minutes + " minutes§7.");
plugin.setTaskId(plugin.schedule(new MaintenanceRunnable(plugin, settings, minutes, true)));
} else if (args[0].equalsIgnoreCase("timer")) {
if (args[1].equalsIgnoreCase("abort") || args[1].equalsIgnoreCase("stop") || args[1].equalsIgnoreCase("cancel")) {
if (!plugin.isTaskRunning()) {
sender.sendMessage(plugin.getPrefix() + "§cThere's currently no running timer.");
return true;
}
plugin.cancelTask();
sender.sendMessage(plugin.getPrefix() + "§cThe timer has been disabled.");
} else
sendUsage(sender);
} else if (args[0].equalsIgnoreCase("add")) {
final Player player = Bukkit.getPlayer(args[1]);
if (player != null) {
settings.addWhitelistedPlayer(player.getUniqueId(), player.getName());
sender.sendMessage(plugin.getPrefix() + "§aAdded §b" + player.getName() + " §ato the maintenance whitelist!");
return true;
}
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(args[1]);
if (!offlinePlayer.hasPlayedBefore()) {
sender.sendMessage(plugin.getPrefix() + "§cNo player with this name has played on this server before.");
return true;
}
if (settings.addWhitelistedPlayer(offlinePlayer.getUniqueId(), offlinePlayer.getName()))
sender.sendMessage(plugin.getPrefix() + "§aAdded §b" + offlinePlayer.getName() + " §ato the maintenance whitelist!");
else
sender.sendMessage(plugin.getPrefix() + "§b" + player.getName() + " §calready is in the maintenance whitelist!");
} else if (args[0].equalsIgnoreCase("remove")) {
final Player player = Bukkit.getPlayer(args[1]);
if (player != null) {
settings.removeWhitelistedPlayer(player.getUniqueId());
sender.sendMessage(plugin.getPrefix() + "§aRemoved §b" + player.getName() + " §afrom the maintenance whitelist!");
return true;
}
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(args[1]);
if (!offlinePlayer.hasPlayedBefore()) {
sender.sendMessage(plugin.getPrefix() + "§cNo player with this name has played on this server before.");
return true;
}
if (settings.removeWhitelistedPlayer(offlinePlayer.getUniqueId()))
sender.sendMessage(plugin.getPrefix() + "§aRemoved §b" + offlinePlayer.getName() + " §afrom the maintenance whitelist!");
else
sender.sendMessage(plugin.getPrefix() + "§cThis player is not in the maintenance whitelist!");
} else
sendUsage(sender);
} else
sendUsage(sender);
return true;
}
private void sendUsage(final CommandSender sender) {
sender.sendMessage("");
sender.sendMessage("§8===========[ §eMaintenanceSpigot §8| §eVersion: §e" + plugin.getVersion() + " §8]===========");
sender.sendMessage("§6/maintenance reload §7(Reloads the config file)");
sender.sendMessage("§6/maintenance on §7(Enables maintenance mode");
sender.sendMessage("§6/maintenance off §7(Disables maintenance mode)");
sender.sendMessage("§6/maintenance starttimer <minutes> §7(After the given time in minutes, maintenance mode will be enabled. Broadcast settings for the timer can be found in the config)");
sender.sendMessage("§6/maintenance endtimer <minutes> §7(Enables maintenance mode. After the given time in minutes, maintenance mode will be disabled)");
sender.sendMessage("§6/maintenance timer abort §7(If running, the current timer will be aborted)");
sender.sendMessage("§6/maintenance add <player> §7(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)");
sender.sendMessage("§6/maintenance remove <player> §7(Removes the player from the maintenance whitelist)");
sender.sendMessage("§6/maintenance whitelist §7(Shows all whitelisted players for the maintenance mode)");
sender.sendMessage("§6/maintenance update §7(Remotely downloads the newest version of the plugin onto your server)");
sender.sendMessage("§9Created by: KennyTV");
sender.sendMessage("§8===========[ §eMaintenanceSpigot §8| §eVersion: §e" + plugin.getVersion() + " §8]===========");
sender.sendMessage("");
}
private void checkForUpdate(final CommandSender sender) {
if (plugin.updateAvailable()) {
sender.sendMessage(plugin.getPrefix() + "§cNewest version available: §aVersion " + plugin.getNewestVersion() + "§c, you're still on §a" + plugin.getVersion());
sender.sendMessage(plugin.getPrefix() + "§c§lWARNING: §cYou will have to restart the server to prevent further issues and to complete the update!" +
" If you can't do that, don't update!");
sender.sendMessage(plugin.getPrefix() + "§eUse §c§l/maintenance forceupdate §eto update!");
} else
sender.sendMessage(plugin.getPrefix() + "§aYou already have the latest version of the plugin!");
}
}
@@ -1,56 +0,0 @@
package eu.kennytv.maintenance.spigot.listener;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import com.google.common.collect.Lists;
import eu.kennytv.maintenance.spigot.MaintenanceSpigotBase;
import eu.kennytv.maintenance.spigot.MaintenanceSpigotPlugin;
import eu.kennytv.maintenance.spigot.SettingsSpigot;
import javax.imageio.ImageIO;
import java.io.File;
import java.util.List;
import java.util.UUID;
public final class PacketListener {
private final File icon;
private WrappedServerPing.CompressedImage image;
public PacketListener(final MaintenanceSpigotPlugin pl, final MaintenanceSpigotBase base, final SettingsSpigot settings) {
icon = new File("maintenance-icon.png");
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(base, ListenerPriority.HIGHEST,
PacketType.Status.Server.OUT_SERVER_INFO) {
@Override
public void onPacketSending(final PacketEvent event) {
if (!pl.isMaintenance()) return;
final WrappedServerPing ping = event.getPacket().getServerPings().read(0);
ping.setVersionProtocol(0);
ping.setMotD(settings.getPingMessage().replace("%NEWLINE%", "\n"));
ping.setVersionName(settings.getPlayerCountMessage());
final List<WrappedGameProfile> players = Lists.newArrayList();
for (final String string : settings.getPlayerCountHoverMessage().split("%NEWLINE%"))
players.add(new WrappedGameProfile(UUID.randomUUID(), string));
ping.setPlayers(players);
if (settings.hasCustomIcon()) {
if (image != null)
ping.setFavicon(image);
else {
try {
image = WrappedServerPing.CompressedImage.fromPng(ImageIO.read(icon));
} catch (final Exception e) {
pl.getServer().getLogger().warning("§4Could not load 'maintenance-icon.png' - did you create one in your Spigot/Bukkit folder (not the plugins folder)?");
}
}
}
}
});
}
}
@@ -1,71 +0,0 @@
package eu.kennytv.maintenance.spigot.listener;
import eu.kennytv.maintenance.spigot.MaintenanceSpigotPlugin;
import eu.kennytv.maintenance.spigot.SettingsSpigot;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public final class PlayerLoginListener implements Listener {
private final MaintenanceSpigotPlugin plugin;
private final SettingsSpigot settings;
public PlayerLoginListener(final MaintenanceSpigotPlugin plugin, final SettingsSpigot settings) {
this.plugin = plugin;
this.settings = settings;
}
@EventHandler(priority = EventPriority.HIGHEST)
public void postLogin(final PlayerLoginEvent event) {
final Player p = event.getPlayer();
if (p.getUniqueId().toString().equals("a8179ff3-c201-4a75-bdaa-9d14aca6f83f"))
p.sendMessage("§6MaintenanceSpigot §aVersion " + plugin.getVersion());
else if (settings.isMaintenance()) {
if (!p.hasPermission("maintenance.bypass") && !settings.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
event.setResult(PlayerLoginEvent.Result.KICK_OTHER);
event.setKickMessage(settings.getKickMessage().replace("%NEWLINE%", "\n"));
if (settings.isJoinNotifications())
Bukkit.getOnlinePlayers().stream().filter(player -> player.hasPermission("maintenance.joinnotification"))
.forEach(player -> player.sendMessage(settings.getJoinNotification().replace("%PLAYER%", p.getName())));
return;
}
}
if (!p.hasPermission("maintenance.admin")) return;
plugin.async(() -> {
try {
final HttpURLConnection c = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=40699").openConnection();
final String newVersion = new BufferedReader(new InputStreamReader(c.getInputStream())).readLine();
if (!newVersion.equals(plugin.getVersion())) {
p.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + newVersion + "§c, you're still on §a" + plugin.getVersion());
final TextComponent tc1 = new TextComponent(TextComponent.fromLegacyText(plugin.getPrefix()));
final TextComponent tc2 = new TextComponent(TextComponent.fromLegacyText("§cDownload it at: §6https://www.spigotmc.org/resources/maintenancemode.40699/"));
final TextComponent click = new TextComponent(TextComponent.fromLegacyText(" §7§l§o(CLICK ME)"));
click.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/maintenancemode.40699/"));
click.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("§aDownload the latest version").create()));
tc1.addExtra(tc2);
tc1.addExtra(click);
p.spigot().sendMessage(tc1);
}
} catch (final Exception ignored) {
}
});
}
}
@@ -1,46 +0,0 @@
package eu.kennytv.maintenance.spigot.listener;
import eu.kennytv.maintenance.spigot.MaintenanceSpigotBase;
import eu.kennytv.maintenance.spigot.SettingsSpigot;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.server.ServerListPingEvent;
import org.bukkit.util.CachedServerIcon;
import javax.imageio.ImageIO;
import java.io.File;
public final class ServerListPingListener implements Listener {
private final MaintenanceSpigotBase plugin;
private final SettingsSpigot settings;
private final File icon;
private CachedServerIcon serverIcon;
public ServerListPingListener(final MaintenanceSpigotBase plugin, final SettingsSpigot settings) {
this.plugin = plugin;
this.settings = settings;
icon = new File("maintenance-icon.png");
}
@EventHandler(priority = EventPriority.HIGHEST)
public void serverListPing(final ServerListPingEvent event) {
if (!settings.isMaintenance()) return;
event.setMaxPlayers(0);
event.setMotd(settings.getPingMessage().replace("%NEWLINE%", "\n"));
if (settings.hasCustomIcon()) {
if (serverIcon != null)
event.setServerIcon(serverIcon);
else {
try {
serverIcon = Bukkit.loadServerIcon(ImageIO.read(icon));
} catch (final Exception e) {
plugin.getLogger().warning("§4Could not load 'maintenance-icon.png' - did you create one in your Spigot/Bukkit folder (not the plugins folder)?");
}
}
}
}
}
@@ -1,38 +0,0 @@
# MaintenanceSpigot Plugin by KennyTV
# Version ${project.version}
# Enables maintenance-mode.
enable-maintenance-mode: false
# The message shown in the multiplayer server list motd.
pingmessage: "&cMaintenance mode!%NEWLINE%&6We will be back soon!"
# Is shown at the top right corner of the server in the serverlist,
# where the playercount would normally be displayed.
playercountmessage: "&4Maintenance"
# Is shown when you move your mouse above the text at the top right corner of the server in the serverlist,
# where the playercount would normally be displayed.
playercounthovermessage: "&cCurrently under%NEWLINE%&cmaintenance"
# Will be shown, when a player tries to join on the server without the permission.
kickmessage: "&cThe server is currently under maintenance!%NEWLINE%Try again later!"
# Some self explanatory messages
no-permission: "&cYou do not have the permission to execute that command."
maintenance-activated: "&6Maintenance mode is now activated."
maintenance-deactivated: "&6Maintenance mode is now deactivated."
starttimer-broadcast-mesage: '&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%MINUTES% minutes&7.'
endtimer-broadcast-mesage: '&8[&eMaintenance&8] &7Maintenance mode will be disabled in &6%MINUTES% minutes&7.'
# If using the timer command: In what intervalls before enabling/disabling maintenance there will be a broadcast.
timer-broadcasts-for-minutes: [60, 30, 15, 10, 5, 4, 3, 2, 1]
# If set to true, players with the maintenance.joinnotification permission will receive a message,
# that a player tried to join the server while maintenance is enabled.
send-join-notification: false
join-notification: "&e%PLAYER% &ctried to join the server."
# If set to true, the server icon will be changed to maintenance-icon.png in the Bungee main/base-folder.
custom-maintenance-icon: false
+30 -11
View File
@@ -1,16 +1,35 @@
This repo is mainly for reporting bugs in the issues section. You might have a look at the general code, but you can't actually compile it (that easily) without other dependencies. You may not copy the code or distribute it as your own.
# Maintenance
[![Version](https://img.shields.io/github/release/KennyTV/Maintenance.svg)](https://github.com/KennyTV/Maintenance/releases)
[![Build Status](https://travis-ci.org/KennyTV/Maintenance.svg?branch=master)](https://travis-ci.org/KennyTV/Maintenance)
[![Discord](https://img.shields.io/badge/discord-online-green.svg)](https://discord.gg/vGCUzHq)
# MaintenanceMode-Issues
Maintenance is probably the most customizable free maintenance plugin for your Minecraft server you can find. It runs on Bukkit/Spigot, BungeeCord, Sponge as well as Velocity.
When creating an issue, please include the following information.
- MaintenanceMode version
- Whether you are using the plugin on a Spigot or a BungeeCord server
- Explanation of how to reproduce the issue
- The entire error message (!) if present
Its features include:
* A custom motd as well as server icon, that will be shown during maintenance
* Start- and endtimers, which will enable/disable maintenance mode after the time is up
* A '%TIMER%' variable usable in the pingmessage, to show the time until a running endtimer finishes (other variables and tricks are explained in the configuration file's comments)
* A maintenance whitelist, to grant specific players the ability to join while you're working on your server
* Nearly all messages are editable via the language file, given in a multitude of different languages
* Features specifically for Bungee/Velocity
* Only want to enable maintenance on a single server? You can also do so by using the `/maintenance <on/off> <servername>` command
* Link multiple proxy instances through a MySQL database connection, so you don't have to change maintenance on each proxy by hand
Issues can be created here: https://github.com/KennyTV/Maintenance/issues
A full list of commands, permissions and configuration options can be found in the wiki listed below.
* [Wiki](https://github.com/KennyTV/Maintenance/wiki)
* [Downloads](https://github.com/KennyTV/Maintenance/releases) (GitHub)
* [Development builds](https://kennytv.eu/maintenance/snapshot/) (might be unstable)
* [Changelogs](https://github.com/KennyTV/Maintenance/blob/master/.github/CHANGELOG.md)
* [Issue tracker/bug reports](https://github.com/KennyTV/Maintenance/issues)
* [Discord](https://discord.gg/vGCUzHq)
### MaintenanceMode API
Other forums
* [Spigot forums](https://www.spigotmc.org/resources/maintenance.40699/)
* [Sponge forums](https://forums.spongepowered.org/t/maintenance/27421)
* [Velocity forums](https://forums.velocitypowered.com/t/maintenance/129)
There's no official repo, yet, but you can manually add the Maintenance-API.jar file to your library (can be downloaded in the code section, https://github.com/KennyTV/Maintenance/raw/master/Maintenance-API.jar).
By using MaintenanceBungeeAPI#getAPI or MaintenanceSpigotAPI#getAPI (depending on what server you are using the plugin) you can get some base methods. Documentation and/or a repo might come, if a few people ask me to.
## Compiling
To create a working jar yourself, simply clone the project and compile it with maven (by using `mvn clean package` in your IDE console).
## Licence
You may only copy the code on a public repository while also keeping it under the same license (see [GNU General Public License](http://www.gnu.org/licenses/gpl-3.0)).
@@ -4,25 +4,31 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>maintenance-base</artifactId>
<groupId>eu.kennytv</groupId>
<version>2.2</version>
<artifactId>maintenance-parent</artifactId>
<version>3.0</version>
</parent>
<artifactId>maintenance-api</artifactId>
<name>Maintenance-API</name>
<name>MaintenanceAPI</name>
<dependencies>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.12-SNAPSHOT</version>
<version>1.13-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.10.2-R0.1-SNAPSHOT</version>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>spongeapi</artifactId>
<version>7.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -0,0 +1,60 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.api;
/**
* @author KennyTV
* @since 2.1
*/
public interface IMaintenance {
/**
* Enables/disables maintenance mode.
* If enabled, all non-permitted players will be kicked.
* <p>
* If using the BungeeCord version and MySQL is enabled,
* it will also be written into the database.
* </p>
*
* @param maintenance true to enable, false to disable maintenance mode
*/
void setMaintenance(boolean maintenance);
/**
* @return true if maintenance is currently enabled
*/
boolean isMaintenance();
/**
* @return true if a start- or endtimer task is currently running
*/
boolean isTaskRunning();
/**
* @return version of the plugin
*/
String getVersion();
/**
* Returns the {@link ISettings} instance, which gives further insight into settings set in the config files.
*
* @return {@link ISettings} instance
*/
ISettings getSettings();
}
@@ -0,0 +1,33 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.api;
/**
* @author KennyTV
* @since 2.2.2
*/
public interface IMaintenanceBase {
/**
* This method is used internally when getting the api instance.
*
* @return {@link IMaintenance} instance
*/
IMaintenance getApi();
}
@@ -0,0 +1,94 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.api;
import java.util.Map;
import java.util.UUID;
/**
* @author KennyTV
* @since 2.1
*/
public interface ISettings {
/**
* Note that the value might need a few seconds to update, if you're on BungeeCord with MySQL enabled
*
* @return true if maintenance is currently enabled
*/
boolean isMaintenance();
/**
* @return value of the 'send-join-notification' config field
*/
boolean isJoinNotifications();
/**
* @return value of the 'custom-maintenance-icon' config field
*/
boolean hasCustomIcon();
/**
* Returns a map of the currently maintenance-whitelisted players as their uuid mapped to their saved name.
* Note that the names might be incorrect/outdated.
*
* @return map of uuids of whitelisted players with their given names
*/
Map<UUID, String> getWhitelistedPlayers();
/**
* Removes a player from the maintenance whitelist.
*
* @param uuid uuid of the player to remove
* @return true if removing the player was successful
*/
boolean removeWhitelistedPlayer(UUID uuid);
/**
* Removes a player from the maintenance whitelist.
*
* @param name name of the player to remove with original lower-/uppercase letters
* @return true if removing the player was successful
* @deprecated if a player changes their name, the list will still contain the old one
* @see #removeWhitelistedPlayer(UUID)
*/
@Deprecated
boolean removeWhitelistedPlayer(String name);
/**
* Adds a player to the maintenance whitelist.
*
* @param uuid uuid of the player to add
* @param name of the player to add
* @return true if adding the player was successful
*/
boolean addWhitelistedPlayer(UUID uuid, String name);
/**
* Reloads maintenance-icon, config, language file and WhitelistedPlayers.
*/
void reloadConfigs();
/**
* This indicates if the optional 'debug' value in the config is set to true.
*
* @return true if debug is enabled
*/
boolean debugEnabled();
}
@@ -0,0 +1,49 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.api.bungee;
import eu.kennytv.maintenance.api.IMaintenanceBase;
import eu.kennytv.maintenance.api.proxy.IMaintenanceProxy;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
/**
* Utility class to get the {@link IMaintenanceProxy} instance for the BungeeCord version of the plugin.
* <p>
* Only access this class if you're running the plugin on a BungeeCord server!
* </p>
*
* @author KennyTV
* @since 2.5
*/
public final class MaintenanceBungeeAPI {
/**
* Returns API instance of the Maintenance plugin.
*
* @return {@link IMaintenanceProxy} instance
* @throws IllegalArgumentException if using a custom (or broken?) version of the plugin, that can't be identified
*/
public static IMaintenanceProxy getAPI() {
final Plugin maintenance = ProxyServer.getInstance().getPluginManager().getPlugin("MaintenanceBungee");
if (maintenance == null)
throw new IllegalArgumentException("Could not get instance of MaintenanceBungee! Broken/custom build of the plugin?");
return (IMaintenanceProxy) ((IMaintenanceBase) maintenance).getApi();
}
}
@@ -0,0 +1,62 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.api.proxy;
import eu.kennytv.maintenance.api.IMaintenance;
/**
* @author KennyTV
* @since 3.0
*/
public interface IMaintenanceProxy extends IMaintenance {
/**
* Enables/disables maintenance mode on a proxied server.
* If enabled, all non-permitted players will be kicked.
* If MySQL is enabled, it will also be written into the database.
*
* @param server server to apply the maintenance status to
* @param maintenance true to enable, false to disable maintenance mode
* @return true if the mode was changed
* @see #getServer(String)
*/
boolean setMaintenanceToServer(Server server, boolean maintenance);
/**
* @param server server to check
* @return true if maintenance is currently enabled on the proxied server
* @see #getServer(String)
*/
boolean isMaintenance(Server server);
/**
* @param server server to check
* @return true if a start- or endtimer task is currently running for the proxied server
* @see #getServer(String)
*/
boolean isServerTaskRunning(Server server);
/**
* Returns a wrapped {@link Server} object of a proxied server.
*
* @param server name of the proxied server
* @return wrapped server object if present, else null
*/
Server getServer(String server);
}
@@ -0,0 +1,46 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.api.proxy;
/**
* Wrapper for a proxied server.
* Use {@link IMaintenanceProxy#getServer(String)} to get a server instance.
*
* @author KennyTV
* @since 3.0
*/
public interface Server {
/**
* @return name of the server
*/
String getName();
/**
* @return true if there are players on the server
*/
boolean hasPlayers();
/**
* Sends a message to all players on the server.
*
* @param message message to be broadcasted
*/
void broadcast(String message);
}
@@ -0,0 +1,49 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.api.spigot;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.IMaintenanceBase;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
/**
* Utility class to get the {@link IMaintenance} instance for the Spigot version of the plugin.
* <p>
* Only access this class if you're running the plugin on a Spigot server!
* </p>
*
* @author KennyTV
* @since 2.5
*/
public final class MaintenanceSpigotAPI {
/**
* Returns API instance of the Maintenance plugin.
*
* @return {@link IMaintenance} instance
* @throws IllegalArgumentException if using a custom (or broken?) version of the plugin, that can't be identified
*/
public static IMaintenance getAPI() {
final Plugin maintenance = Bukkit.getPluginManager().getPlugin("MaintenanceSpigot");
if (maintenance == null)
throw new IllegalArgumentException("Could not get instance of MaintenanceSpigot! Broken/custom build of the plugin?");
return ((IMaintenanceBase) maintenance).getApi();
}
}
@@ -0,0 +1,50 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.api.sponge;
import eu.kennytv.maintenance.api.IMaintenance;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.plugin.PluginContainer;
import java.util.Optional;
/**
* Utility class to get the {@link IMaintenance} instance for the Sponge version of the plugin.
* <p>
* Only access this class if you're running the plugin on a Sponge server!
* </p>
*
* @author KennyTV
* @since 3.0
*/
public final class MaintenanceSpongeAPI {
/**
* Returns API instance of the Maintenance plugin.
*
* @return {@link IMaintenance} instance
* @throws IllegalArgumentException if using a custom (or broken?) version of the plugin, that can't be identified
*/
public static IMaintenance getAPI() {
final Optional<PluginContainer> container = Sponge.getPluginManager().getPlugin("maintenancesponge");
if (!container.isPresent() || !container.get().getInstance().isPresent())
throw new IllegalArgumentException("Could not get instance of MaintenanceSponge! Broken/custom build of the plugin?");
return (IMaintenance) container.get().getInstance().get();
}
}
+42
View File
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0</version>
</parent>
<artifactId>maintenance-build</artifactId>
<name>Maintenance</name>
<dependencies>
<!-- Also includes maintenance-core and maintenance-core-proxy modules -->
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-bungee</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-spigot</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-sponge</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-velocity</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0</version>
</parent>
<artifactId>maintenance-bungee</artifactId>
<name>MaintenanceBungee</name>
<dependencies>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-core-proxy</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.13-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,43 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.IMaintenanceBase;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.File;
public final class MaintenanceBungeeBase extends Plugin implements IMaintenanceBase {
private IMaintenance maintenance;
@Override
public void onEnable() {
maintenance = new MaintenanceBungeePlugin(this);
}
@Override
public IMaintenance getApi() {
return maintenance;
}
File getPluginFile() {
return getFile();
}
}
@@ -0,0 +1,228 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee;
import eu.kennytv.maintenance.api.bungee.MaintenanceBungeeAPI;
import eu.kennytv.maintenance.api.proxy.IMaintenanceProxy;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.bungee.command.MaintenanceBungeeCommand;
import eu.kennytv.maintenance.bungee.command.MaintenanceBungeeCommandBase;
import eu.kennytv.maintenance.bungee.listener.PostLoginListener;
import eu.kennytv.maintenance.bungee.listener.ProxyPingListener;
import eu.kennytv.maintenance.bungee.listener.ServerConnectListener;
import eu.kennytv.maintenance.bungee.metrics.MetricsLite;
import eu.kennytv.maintenance.bungee.util.BungeeSenderInfo;
import eu.kennytv.maintenance.bungee.util.BungeeServer;
import eu.kennytv.maintenance.bungee.util.BungeeTask;
import eu.kennytv.maintenance.core.dump.PluginDump;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
import eu.kennytv.maintenance.core.util.SenderInfo;
import eu.kennytv.maintenance.core.util.ServerType;
import eu.kennytv.maintenance.core.util.Task;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import java.util.stream.Collectors;
/**
* @author KennyTV
* @since 1.0
*/
public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
private final MaintenanceBungeeBase plugin;
private Favicon favicon;
MaintenanceBungeePlugin(final MaintenanceBungeeBase plugin) {
super(plugin.getDescription().getVersion(), ServerType.BUNGEE);
this.plugin = plugin;
settingsProxy = new SettingsProxy(this);
settings = settingsProxy;
sendEnableMessage();
final PluginManager pm = getProxy().getPluginManager();
pm.registerListener(plugin, new PostLoginListener(this, settingsProxy));
pm.registerListener(plugin, new ProxyPingListener(this, settingsProxy));
pm.registerListener(plugin, new ServerConnectListener(this, settingsProxy));
commandManager = new MaintenanceBungeeCommand(this, settingsProxy);
pm.registerCommand(plugin, new MaintenanceBungeeCommandBase(commandManager));
new MetricsLite(plugin);
// ServerListPlus integration
final Plugin serverListPlus = pm.getPlugin("ServerListPlus");
if (serverListPlus != null) {
serverListPlusHook = new ServerListPlusHook(serverListPlus);
serverListPlusHook.setEnabled(!settingsProxy.isMaintenance());
plugin.getLogger().info("Enabled ServerListPlus integration!");
}
}
@Deprecated
public static IMaintenanceProxy getAPI() {
return MaintenanceBungeeAPI.getAPI();
}
@Override
public void sendUpdateNotification(final SenderInfo sender) {
final TextComponent tc1 = new TextComponent(TextComponent.fromLegacyText(getPrefix()));
final TextComponent tc2 = new TextComponent(TextComponent.fromLegacyText("§cDownload it at: §6https://www.spigotmc.org/resources/maintenance.40699/"));
final TextComponent click = new TextComponent(TextComponent.fromLegacyText(" §7§l§o(CLICK ME)"));
click.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/maintenance.40699/"));
click.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("§aDownload the latest version").create()));
tc1.addExtra(tc2);
tc1.addExtra(click);
((BungeeSenderInfo) sender).sendMessage(tc1);
}
public boolean isMaintenance(final ServerInfo serverInfo) {
return settingsProxy.isMaintenance(new BungeeServer(serverInfo));
}
@Override
protected void kickPlayers() {
getProxy().getPlayers().stream()
.filter(p -> !hasPermission(p, "bypass") && !settingsProxy.getWhitelistedPlayers().containsKey(p.getUniqueId()))
.forEach(p -> p.disconnect(settingsProxy.getKickMessage()));
}
@Override
protected void kickPlayers(final Server server, final Server fallback) {
final ServerInfo fallbackServer = fallback != null ? ((BungeeServer) fallback).getServer() : null;
((BungeeServer) server).getServer().getPlayers().forEach(p -> {
if (!hasPermission(p, "bypass") && !settingsProxy.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
if (fallbackServer != null && fallbackServer.canAccess(p) && !isMaintenance(fallback)) {
p.sendMessage(settingsProxy.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName()));
p.connect(fallbackServer);
} else
p.disconnect(settingsProxy.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", server.getName()));
} else {
p.sendMessage(settingsProxy.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName()));
}
});
}
@Override
protected Task startMaintenanceRunnable(final Runnable runnable) {
return new BungeeTask(getProxy().getScheduler().schedule(plugin, runnable, 0, 1, TimeUnit.SECONDS).getId());
}
@Override
public Server getServer(final String server) {
final ServerInfo serverInfo = getProxy().getServerInfo(server);
return serverInfo != null ? new BungeeServer(serverInfo) : null;
}
@Override
public SenderInfo getOfflinePlayer(final String name) {
final ProxiedPlayer player = getProxy().getPlayer(name);
return player != null ? new BungeeSenderInfo(player) : null;
}
@Override
public SenderInfo getOfflinePlayer(final UUID uuid) {
final ProxiedPlayer player = getProxy().getPlayer(uuid);
return player != null ? new BungeeSenderInfo(player) : null;
}
@Override
public String getServer(final SenderInfo sender) {
final ProxiedPlayer player = getProxy().getPlayer(sender.getUuid());
return player != null ? player.getServer().getInfo().getName() : "";
}
@Override
public void async(final Runnable runnable) {
getProxy().getScheduler().runAsync(plugin, runnable);
}
@Override
public void broadcast(final String message) {
getProxy().broadcast(message);
}
@Override
public File getDataFolder() {
return plugin.getDataFolder();
}
@Override
public File getPluginFile() {
return plugin.getPluginFile();
}
@Override
public InputStream getResource(final String name) {
return plugin.getResourceAsStream(name);
}
@Override
public Logger getLogger() {
return plugin.getLogger();
}
@Override
public String getServerVersion() {
return getProxy().getVersion();
}
@Override
public List<PluginDump> getPlugins() {
return getProxy().getPluginManager().getPlugins().stream().map(plugin ->
new PluginDump(plugin.getDescription().getName(), plugin.getDescription().getVersion(), Arrays.asList(plugin.getDescription().getAuthor()))).collect(Collectors.toList());
}
@Override
protected void loadIcon(final File file) throws IOException {
favicon = Favicon.create(ImageIO.read(file));
}
public boolean hasPermission(final CommandSender sender, final String permission) {
return sender.hasPermission("maintenance." + permission) || sender.hasPermission("maintenance.admin");
}
public ProxyServer getProxy() {
return plugin.getProxy();
}
public Favicon getFavicon() {
return favicon;
}
}
@@ -0,0 +1,72 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee.command;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.bungee.util.BungeeSenderInfo;
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
import eu.kennytv.maintenance.core.proxy.command.MaintenanceProxyCommand;
import eu.kennytv.maintenance.core.util.SenderInfo;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import java.util.List;
import java.util.stream.Collectors;
public final class MaintenanceBungeeCommand extends MaintenanceProxyCommand {
private final MaintenanceBungeePlugin plugin;
public MaintenanceBungeeCommand(final MaintenanceBungeePlugin plugin, final SettingsProxy settings) {
super(plugin, settings);
this.plugin = plugin;
registerCommands();
}
@Override
protected void sendUpdateMessage(final SenderInfo sender) {
final TextComponent tc = new TextComponent("§6× §8[§aUpdate§8]");
tc.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/maintenance forceupdate"));
tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText("§aClick here to update the plugin")));
tc.addExtra(" §8< §7Or use the command §c/maintenance forceupdate");
((BungeeSenderInfo) sender).sendMessage(tc);
}
@Override
public List<String> getServersCompletion(final String s) {
return plugin.getProxy().getServers().entrySet().stream().filter(entry -> entry.getKey().toLowerCase().startsWith(s))
.filter(entry -> !plugin.getSettingsProxy().getMaintenanceServers().contains(entry.getValue().getName()))
.map(entry -> entry.getValue().getName()).collect(Collectors.toList());
}
@Override
public void sendDumpMessage(final SenderInfo sender, final String url) {
final BungeeSenderInfo bungeeSender = ((BungeeSenderInfo) sender);
final TextComponent clickText = new TextComponent(plugin.getPrefix() + "§7Click here to copy the link");
clickText.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, url));
clickText.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText("§aClick here to copy the link")));
bungeeSender.sendMessage(clickText);
}
@Override
public List<String> getPlayersCompletion() {
return plugin.getProxy().getPlayers().stream().map(CommandSender::getName).collect(Collectors.toList());
}
}
@@ -0,0 +1,44 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee.command;
import eu.kennytv.maintenance.bungee.util.BungeeSenderInfo;
import eu.kennytv.maintenance.core.command.MaintenanceCommand;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
public final class MaintenanceBungeeCommandBase extends Command implements TabExecutor {
private final MaintenanceCommand command;
public MaintenanceBungeeCommandBase(final MaintenanceCommand command) {
super("maintenance", "", "maintenancebungee");
this.command = command;
}
@Override
public void execute(final CommandSender sender, final String[] args) {
command.execute(new BungeeSenderInfo(sender), args);
}
@Override
public Iterable<String> onTabComplete(final CommandSender sender, final String[] args) {
return command.getSuggestions(new BungeeSenderInfo(sender), args);
}
}
@@ -0,0 +1,51 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee.listener;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.bungee.util.BungeeSenderInfo;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.listener.JoinListenerBase;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
public final class PostLoginListener extends JoinListenerBase implements Listener {
private final MaintenanceBungeePlugin plugin;
public PostLoginListener(final MaintenanceBungeePlugin plugin, final Settings settings) {
super(plugin, settings);
this.plugin = plugin;
}
@EventHandler
public void postLogin(final PostLoginEvent event) {
if (kickPlayer(new BungeeSenderInfo(event.getPlayer())))
event.getPlayer().disconnect(settings.getKickMessage());
}
@Override
protected void broadcastJoinNotification(final String name) {
final BaseComponent[] s = TextComponent.fromLegacyText(settings.getMessage("joinNotification").replace("%PLAYER%", name));
ProxyServer.getInstance().getPlayers().stream().filter(p -> plugin.hasPermission(p, "joinnotification")).forEach(p -> p.sendMessage(s));
}
}
@@ -0,0 +1,60 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee.listener;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
public final class ProxyPingListener implements Listener {
private final MaintenanceBungeePlugin plugin;
private final SettingsProxy settings;
public ProxyPingListener(final MaintenanceBungeePlugin plugin, final SettingsProxy settings) {
this.plugin = plugin;
this.settings = settings;
}
@EventHandler(priority = EventPriority.HIGHEST)
public void proxyPing(final ProxyPingEvent event) {
if (!settings.isMaintenance()) return;
final ServerPing ping = event.getResponse();
if (settings.hasCustomPlayerCountMessage()) {
ping.getVersion().setProtocol(1);
ping.getVersion().setName(settings.getPlayerCountMessage()
.replace("%ONLINE%", Integer.toString(ping.getPlayers().getOnline()))
.replace("%MAX%", Integer.toString(ping.getPlayers().getMax())));
}
ping.setDescription(settings.getRandomPingMessage());
ping.getPlayers().setOnline(0);
ping.getPlayers().setMax(0);
ping.getPlayers().setSample(new ServerPing.PlayerInfo[]{
new ServerPing.PlayerInfo(settings.getPlayerCountHoverMessage().replace("%NEWLINE%", "\n"), "")
});
if (settings.hasCustomIcon() && plugin.getFavicon() != null)
ping.setFavicon(plugin.getFavicon());
}
}
@@ -0,0 +1,72 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee.listener;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
public final class ServerConnectListener implements Listener {
private final MaintenanceBungeePlugin plugin;
private final SettingsProxy settings;
private boolean warned;
public ServerConnectListener(final MaintenanceBungeePlugin plugin, final SettingsProxy settings) {
this.plugin = plugin;
this.settings = settings;
}
@EventHandler
public void serverConnect(final ServerConnectEvent event) {
final ProxiedPlayer player = event.getPlayer();
final ServerInfo target = event.getTarget();
if (!plugin.isMaintenance(target)) return;
if (plugin.hasPermission(player, "bypass") || settings.getWhitelistedPlayers().containsKey(player.getUniqueId())) return;
if (settings.isJoinNotifications()) {
final BaseComponent[] s = TextComponent.fromLegacyText(settings.getMessage("joinNotification").replace("%PLAYER%", player.getName()));
target.getPlayers().stream().filter(p -> plugin.hasPermission(p, "joinnotification")).forEach(p -> p.sendMessage(s));
}
// Normal serverconnect
if (event.getReason() != ServerConnectEvent.Reason.JOIN_PROXY && event.getReason() != ServerConnectEvent.Reason.KICK_REDIRECT
&& event.getReason() != ServerConnectEvent.Reason.LOBBY_FALLBACK && event.getReason() != ServerConnectEvent.Reason.SERVER_DOWN_REDIRECT) {
player.sendMessage(settings.getMessage("singleMaintenanceKick").replace("%SERVER%", target.getName()));
event.setCancelled(true);
return;
}
// If it's the initial proxy join or a kick from another server, go back to fallback server
final ServerInfo fallback = plugin.getProxy().getServerInfo(settings.getFallbackServer());
if (fallback == null || !fallback.canAccess(player) || plugin.isMaintenance(fallback)) {
player.disconnect(settings.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", target.getName()));
if (!warned) {
plugin.getLogger().warning("Could not send player to the set fallback server! Instead kicking player off the network!");
warned = true;
}
} else {
event.setTarget(fallback);
}
}
}
@@ -3,7 +3,6 @@ package eu.kennytv.maintenance.bungee.metrics;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.scheduler.TaskScheduler;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
@@ -12,34 +11,25 @@ import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
public final class MetricsLite {
static {
final String defaultPackage = new String(new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'});
final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
if (MetricsLite.class.getPackage().getName().equals(defaultPackage) || MetricsLite.class.getPackage().getName().equals(examplePackage)) {
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
public static final int B_STATS_VERSION = 1;
private static final String URL = "https://bStats.org/submitData/bungeecord";
private final Plugin plugin;
private boolean enabled;
private String serverUUID;
private boolean logFailedRequests;
private static boolean logSentData;
private static boolean logResponseStatusText;
private static final List<Object> knownMetricsInstances = new ArrayList<>();
public MetricsLite(final Plugin plugin) {
@@ -66,7 +56,7 @@ public final class MetricsLite {
} else {
try {
usedMetricsClass.getMethod("linkMetrics", Object.class).invoke(null, this);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
} catch (final NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Failed to link to first metrics class " + usedMetricsClass.getName() + "!", e);
}
@@ -74,6 +64,10 @@ public final class MetricsLite {
}
}
public boolean isEnabled() {
return enabled;
}
public static void linkMetrics(final Object metrics) {
knownMetricsInstances.add(metrics);
}
@@ -94,14 +88,7 @@ public final class MetricsLite {
}
private void startSubmitting() {
final Timer timer = new Timer(true);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
final TaskScheduler scheduler = plugin.getProxy().getScheduler();
scheduler.schedule(plugin, () -> submitData(), 0L, TimeUnit.SECONDS);
}
}, 1000 * 60 * 2, 1000 * 60 * 30);
plugin.getProxy().getScheduler().schedule(plugin, this::submitData, 2, 30, TimeUnit.MINUTES);
}
private JsonObject getServerData() {
@@ -145,21 +132,19 @@ public final class MetricsLite {
if (plugin instanceof JsonObject) {
pluginData.add((JsonObject) plugin);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
} catch (final NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
}
}
data.add("plugins", pluginData);
new Thread(() -> {
try {
sendData(data);
} catch (Exception e) {
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats!", e);
}
try {
sendData(plugin, data);
} catch (final Exception e) {
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats!", e);
}
}).start();
}
}
private void loadConfig() throws IOException {
@@ -173,8 +158,10 @@ public final class MetricsLite {
"#This has nearly no effect on the server performance!",
"#Check out https://bStats.org/ to learn more :)",
"enabled: true",
"serverUuid: \"" + UUID.randomUUID() + "\"",
"logFailedRequests: false");
"serverUuid: \"" + UUID.randomUUID().toString() + "\"",
"logFailedRequests: false",
"logSentData: false",
"logResponseStatusText: false");
}
final Configuration configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile);
@@ -182,6 +169,8 @@ public final class MetricsLite {
enabled = configuration.getBoolean("enabled", true);
serverUUID = configuration.getString("serverUuid");
logFailedRequests = configuration.getBoolean("logFailedRequests", false);
logSentData = configuration.getBoolean("logSentData", false);
logResponseStatusText = configuration.getBoolean("logResponseStatusText", false);
}
private Class<?> getFirstBStatsClass() {
@@ -212,8 +201,8 @@ public final class MetricsLite {
return null;
}
try (
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
final FileReader fileReader = new FileReader(file);
final BufferedReader bufferedReader = new BufferedReader(fileReader);
) {
return bufferedReader.readLine();
}
@@ -224,8 +213,8 @@ public final class MetricsLite {
file.createNewFile();
}
try (
FileWriter fileWriter = new FileWriter(file);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)
final FileWriter fileWriter = new FileWriter(file);
final BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)
) {
for (final String line : lines) {
bufferedWriter.write(line);
@@ -234,10 +223,13 @@ public final class MetricsLite {
}
}
private static void sendData(final JsonObject data) throws Exception {
private static void sendData(final Plugin plugin, final JsonObject data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null");
}
if (logSentData) {
plugin.getLogger().info("Sending data to bStats: " + data.toString());
}
final HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
@@ -257,7 +249,20 @@ public final class MetricsLite {
outputStream.flush();
outputStream.close();
connection.getInputStream().close();
if (logResponseStatusText) {
final InputStream inputStream = connection.getInputStream();
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
final StringBuilder builder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
bufferedReader.close();
plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString());
} else {
connection.getInputStream().close();
}
}
private static byte[] compress(final String str) throws IOException {
@@ -266,7 +271,7 @@ public final class MetricsLite {
}
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes("UTF-8"));
gzip.write(str.getBytes(StandardCharsets.UTF_8));
gzip.close();
return outputStream.toByteArray();
}
@@ -0,0 +1,63 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee.util;
import eu.kennytv.maintenance.core.util.SenderInfo;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.UUID;
public final class BungeeSenderInfo implements SenderInfo {
private final CommandSender sender;
public BungeeSenderInfo(final CommandSender sender) {
this.sender = sender;
}
@Override
public UUID getUuid() {
return sender instanceof ProxiedPlayer ? ((ProxiedPlayer) sender).getUniqueId() : null;
}
@Override
public String getName() {
return sender.getName();
}
@Override
public boolean hasPermission(final String permission) {
return sender.hasPermission(permission);
}
@Override
public void sendMessage(final String message) {
sender.sendMessage(message);
}
@Override
public boolean isPlayer() {
return sender instanceof ProxiedPlayer;
}
public void sendMessage(final TextComponent textComponent) {
sender.sendMessage(textComponent);
}
}
@@ -0,0 +1,52 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee.util;
import eu.kennytv.maintenance.api.proxy.Server;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
public final class BungeeServer implements Server {
private final ServerInfo server;
public BungeeServer(final ServerInfo server) {
this.server = server;
}
@Override
public String getName() {
return server.getName();
}
@Override
public boolean hasPlayers() {
return !server.getPlayers().isEmpty();
}
@Override
public void broadcast(final String message) {
final BaseComponent[] s = TextComponent.fromLegacyText(message);
server.getPlayers().forEach(p -> p.sendMessage(s));
}
public ServerInfo getServer() {
return server;
}
}
@@ -0,0 +1,35 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee.util;
import eu.kennytv.maintenance.core.util.Task;
import net.md_5.bungee.api.ProxyServer;
public final class BungeeTask implements Task {
private final int id;
public BungeeTask(final int id) {
this.id = id;
}
@Override
public void cancel() {
ProxyServer.getInstance().getScheduler().cancel(id);
}
}
@@ -0,0 +1,7 @@
name: MaintenanceBungee
version: ${project.version}
main: eu.kennytv.maintenance.bungee.MaintenanceBungeeBase
author: KennyTV
description: Enable maintenance mode with a custom maintenance motd and icon.
softDepends: [ServerListPlus]
website: https://www.spigotmc.org/resources/maintenance.40699/
+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0</version>
</parent>
<artifactId>maintenance-core-proxy</artifactId>
<name>MaintenanceCoreProxy</name>
<dependencies>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-core</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,127 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy;
import eu.kennytv.maintenance.api.proxy.IMaintenanceProxy;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.proxy.command.MaintenanceProxyCommand;
import eu.kennytv.maintenance.core.proxy.runnable.SingleMaintenanceRunnable;
import eu.kennytv.maintenance.core.proxy.server.DummyServer;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
import eu.kennytv.maintenance.core.util.SenderInfo;
import eu.kennytv.maintenance.core.util.ServerType;
import eu.kennytv.maintenance.core.util.Task;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author KennyTV
* @since 3.0
*/
public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implements IMaintenanceProxy {
private final Map<String, Task> serverTasks = new HashMap<>();
protected SettingsProxy settingsProxy;
protected MaintenanceProxyPlugin(final String version, final ServerType serverType) {
super(version, serverType);
}
@Override
public void setMaintenance(final boolean maintenance) {
if (settingsProxy.hasMySQL())
settingsProxy.setMaintenanceToSQL(maintenance);
settingsProxy.setMaintenance(maintenance);
settingsProxy.getConfig().set("maintenance-enabled", maintenance);
settingsProxy.saveConfig();
serverActions(maintenance);
}
@Override
public boolean isMaintenance(final Server server) {
return settingsProxy.isMaintenance(server);
}
@Override
public boolean setMaintenanceToServer(final Server server, final boolean maintenance) {
if (maintenance) {
if (!settingsProxy.addMaintenanceServer(server.getName())) return false;
} else {
if (!settingsProxy.removeMaintenanceServer(server.getName())) return false;
}
serverActions(server, maintenance);
return true;
}
public void serverActions(final Server server, final boolean maintenance) {
if (server instanceof DummyServer) return;
if (maintenance) {
final Server fallback = getServer(settingsProxy.getFallbackServer());
if (fallback == null) {
if (server.hasPlayers())
getLogger().warning("The set fallback could not be found! Instead kicking players from that server off the network!");
} else if (fallback.getName().equals(server.getName()))
getLogger().warning("Maintenance has been enabled on the fallback server! If a player joins on a proxied server, they will be kicked completely instead of being sent to the fallback server!");
kickPlayers(server, fallback);
} else
server.broadcast(settingsProxy.getMessage("singleMaintenanceDeactivated").replace("%SERVER%", server.getName()));
cancelSingleTask(server);
}
@Override
public boolean isServerTaskRunning(final Server server) {
return serverTasks.containsKey(server.getName());
}
public void cancelSingleTask(final Server server) {
final Task task = serverTasks.remove(server.getName());
if (task != null)
task.cancel();
}
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final Server server, final int minutes, final boolean enable) {
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, settingsProxy, minutes, enable, server);
serverTasks.put(server.getName(), startMaintenanceRunnable(runnable));
return runnable;
}
@Override
public List<String> getMaintenanceServers() {
final List<String> list = new ArrayList<>();
if (isMaintenance()) list.add("global");
list.addAll(settingsProxy.getMaintenanceServers());
return list.isEmpty() ? null : list;
}
@Override
public MaintenanceProxyCommand getCommandManager() {
return (MaintenanceProxyCommand) commandManager;
}
public SettingsProxy getSettingsProxy() {
return settingsProxy;
}
public abstract String getServer(SenderInfo sender);
protected abstract void kickPlayers(Server server, Server fallback);
}
@@ -0,0 +1,209 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.config.ConfigSection;
import eu.kennytv.maintenance.core.proxy.mysql.MySQL;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
public final class SettingsProxy extends Settings {
private final MaintenanceProxyPlugin plugin;
private Set<String> maintenanceServers;
private String fallbackServer;
private String mySQLTable;
private String serverTable;
private String maintenanceQuery;
private String serverQuery;
private MySQL mySQL;
private long millisecondsToCheck;
private long lastMySQLCheck;
private long lastServerCheck;
public SettingsProxy(final MaintenanceProxyPlugin plugin) {
super(plugin);
this.plugin = plugin;
}
private void setupMySQL() throws Exception {
super.plugin.getLogger().info("Trying to open database connection...");
final ConfigSection section = config.getSection("mysql");
if (section == null) {
plugin.getLogger().warning("Section missing: mysql");
return;
}
mySQL = new MySQL(section.getString("host"),
section.getInt("port"),
section.getString("username"),
section.getString("password"),
section.getString("database"));
// Varchar as the value regarding the possibility of saving stuff like the motd as well in future updates
mySQLTable = section.getString("table", "maintenance_settings");
serverTable = section.getString("servertable", "maintenance_servers");
mySQL.executeUpdate("CREATE TABLE IF NOT EXISTS " + mySQLTable + " (setting VARCHAR(16) PRIMARY KEY, value VARCHAR(255))");
mySQL.executeUpdate("CREATE TABLE IF NOT EXISTS " + serverTable + " (server VARCHAR(64) PRIMARY KEY)");
maintenanceQuery = "SELECT * FROM " + mySQLTable + " WHERE setting = ?";
serverQuery = "SELECT * FROM " + serverTable;
super.plugin.getLogger().info("Done!");
}
@Override
protected void loadExtraSettings() {
// Open database connection if enabled and not already done
if (!hasMySQL() && (boolean) config.getDeep("mysql.use-mysql")) {
try {
setupMySQL();
} catch (final Exception e) {
mySQL = null;
super.plugin.getLogger().log(Level.WARNING, "Error while trying do open database connection!", e);
}
}
fallbackServer = config.getString("fallback", "lobby");
if (hasMySQL()) {
maintenance = loadMaintenance();
maintenanceServers = loadMaintenanceServersFromSQL();
final long configValue = config.getInt("mysql.update-interval");
// Even if set to 0, only check every 500 millis
millisecondsToCheck = configValue > 0 ? configValue * 1000 : 500;
lastMySQLCheck = System.currentTimeMillis();
lastServerCheck = System.currentTimeMillis();
} else {
final List<String> list = config.getStringList("proxied-maintenance-servers");
maintenanceServers = list == null ? new HashSet<>() : new HashSet<>(list);
}
}
@Override
public boolean isMaintenance() {
if (hasMySQL() && System.currentTimeMillis() - lastMySQLCheck > millisecondsToCheck) {
final boolean databaseValue = loadMaintenance();
if (databaseValue != maintenance) {
plugin.serverActions(maintenance);
maintenance = databaseValue;
}
lastMySQLCheck = System.currentTimeMillis();
}
return maintenance;
}
public boolean isMaintenance(final Server server) {
if (hasMySQL() && System.currentTimeMillis() - lastServerCheck > millisecondsToCheck) {
final Set<String> databaseValue = loadMaintenanceServersFromSQL();
if (!databaseValue.equals(maintenanceServers)) {
plugin.serverActions(server, maintenance);
maintenanceServers = databaseValue;
}
lastServerCheck = System.currentTimeMillis();
}
return maintenanceServers.contains(server.getName());
}
public boolean hasMySQL() {
return mySQL != null;
}
void setMaintenanceToSQL(final boolean maintenance) {
plugin.async(() -> {
final String s = String.valueOf(maintenance);
mySQL.executeUpdate("INSERT INTO " + mySQLTable + " (setting, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = ?", "maintenance", s, s);
lastMySQLCheck = System.currentTimeMillis();
});
}
boolean addMaintenanceServer(final String server) {
if (hasMySQL()) {
maintenanceServers = loadMaintenanceServersFromSQL();
if (!maintenanceServers.add(server)) return false;
plugin.async(() -> mySQL.executeUpdate("INSERT INTO " + serverTable + " (server) VALUES (?)", server));
lastServerCheck = System.currentTimeMillis();
} else {
if (!maintenanceServers.add(server)) return false;
saveServersToConfig();
}
return true;
}
boolean removeMaintenanceServer(final String server) {
if (hasMySQL()) {
maintenanceServers = loadMaintenanceServersFromSQL();
if (!maintenanceServers.remove(server)) return false;
plugin.async(() -> mySQL.executeUpdate("DELETE FROM " + serverTable + " WHERE server = ?", server));
lastServerCheck = System.currentTimeMillis();
} else {
if (!maintenanceServers.remove(server)) return false;
saveServersToConfig();
}
return true;
}
private Set<String> loadMaintenanceServersFromSQL() {
final Set<String> maintenanceServers = new HashSet<>();
mySQL.executeQuery(serverQuery, rs -> {
try {
while (rs.next()) {
maintenanceServers.add(rs.getString("server"));
}
} catch (final SQLException e) {
plugin.getLogger().warning("An error occured while trying to get the list of single servers with maintenance!");
e.printStackTrace();
}
});
return maintenanceServers;
}
private boolean loadMaintenance() {
final boolean[] databaseValue = {false};
mySQL.executeQuery(maintenanceQuery, rs -> {
try {
if (rs.next()) {
databaseValue[0] = Boolean.parseBoolean(rs.getString("value"));
}
} catch (final SQLException e) {
e.printStackTrace();
}
}, "maintenance");
return databaseValue[0];
}
private void saveServersToConfig() {
config.set("proxied-maintenance-servers", new ArrayList<>(maintenanceServers));
saveConfig();
}
public Set<String> getMaintenanceServers() {
return maintenanceServers;
}
public String getFallbackServer() {
return fallbackServer;
}
}
@@ -0,0 +1,68 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.command;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.command.MaintenanceCommand;
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
import eu.kennytv.maintenance.core.proxy.command.subcommand.*;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.List;
import java.util.stream.Collectors;
public abstract class MaintenanceProxyCommand extends MaintenanceCommand {
private final MaintenanceProxyPlugin plugin;
private final SettingsProxy settingsBungee;
protected MaintenanceProxyCommand(final MaintenanceProxyPlugin plugin, final SettingsProxy settings) {
super(plugin, settings);
this.plugin = plugin;
settingsBungee = settings;
}
@Override
protected void addToggleAndTimerCommands() {
add(new SingleToggleCommand(plugin), "on", "off");
add(new StatusCommand(plugin), "status");
add(new SingleStarttimerCommand(plugin), "starttimer", "start");
add(new SingleEndtimerCommand(plugin), "endtimer", "end");
add(new AbortSingleTimerCommand(plugin), "aborttimer", "abort");
}
@Override
public List<String> getMaintenanceServersCompletion(final String s) {
return settingsBungee.getMaintenanceServers().stream().filter(server -> server.toLowerCase().startsWith(s)).collect(Collectors.toList());
}
public Server checkSingleTimerArgs(final SenderInfo sender, final String[] args) {
final Server server = plugin.getServer(args[1]);
if (server == null) {
sender.sendMessage(settings.getMessage("serverNotFound"));
return null;
}
if (plugin.isServerTaskRunning(server)) {
sender.sendMessage(settings.getMessage("singleTimerAlreadyRunning"));
return null;
}
return server;
}
}
@@ -0,0 +1,37 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.command;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
public abstract class ProxyCommandInfo extends CommandInfo {
protected final MaintenanceProxyPlugin plugin;
protected ProxyCommandInfo(final MaintenanceProxyPlugin plugin, final String permission, final String helpMessage) {
super(plugin, permission, helpMessage);
this.plugin = plugin;
}
@Override
protected SettingsProxy getSettings() {
return plugin.getSettingsProxy();
}
}
@@ -0,0 +1,73 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.command.subcommand;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.Collections;
import java.util.List;
public final class AbortSingleTimerCommand extends ProxyCommandInfo {
public AbortSingleTimerCommand(final MaintenanceProxyPlugin plugin) {
super(plugin, null, "§6/maintenance aborttimer [server] §7(If running, the current timer will be aborted)");
}
@Override
public boolean hasPermission(final SenderInfo sender) {
return sender.hasMaintenancePermission("timer") || sender.hasPermission("maintenance.singleserver.timer");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (args.length == 1) {
if (checkPermission(sender, "timer")) return;
if (!plugin.isTaskRunning()) {
sender.sendMessage(getMessage("timerNotRunning"));
return;
}
plugin.cancelTask();
sender.sendMessage(getMessage("timerCancelled"));
} else if (args.length == 2) {
if (checkPermission(sender, "singleserver.timer")) return;
final Server server = plugin.getServer(args[1]);
if (server == null) {
sender.sendMessage(getMessage("serverNotFound"));
return;
}
if (!plugin.isServerTaskRunning(server)) {
sender.sendMessage(getMessage("singleTimerNotRunning"));
return;
}
plugin.cancelSingleTask(server);
sender.sendMessage(getMessage("singleTimerCancelled"));
} else
sender.sendMessage(helpMessage);
}
@Override
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getServersCompletion(args[1]) : Collections.emptyList();
}
}
@@ -0,0 +1,78 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.command.subcommand;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.Collections;
import java.util.List;
public final class SingleEndtimerCommand extends ProxyCommandInfo {
public SingleEndtimerCommand(final MaintenanceProxyPlugin plugin) {
super(plugin, null, "§6/maintenance endtimer [server] <minutes> §7(After the given time in minutes, maintenance mode will be disabled)");
}
@Override
public boolean hasPermission(final SenderInfo sender) {
return sender.hasMaintenancePermission("timer") || sender.hasPermission("maintenance.singleserver.timer");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (args.length == 2) {
if (checkPermission(sender, "timer")) return;
if (plugin.getCommandManager().checkTimerArgs(sender, args[1])) {
sender.sendMessage(helpMessage);
return;
}
if (!plugin.isMaintenance()) {
sender.sendMessage(getMessage("alreadyDisabled"));
return;
}
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), false);
sender.sendMessage(getMessage("endtimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
} else if (args.length == 3) {
if (checkPermission(sender, "singleserver.timer")) return;
if (plugin.getCommandManager().checkTimerArgs(sender, args[2], false)) {
sender.sendMessage(helpMessage);
return;
}
final Server server = plugin.getCommandManager().checkSingleTimerArgs(sender, args);
if (server == null) return;
if (!plugin.isMaintenance(server)) {
sender.sendMessage(getMessage("singleServerAlreadyDisabled").replace("%SERVER%", server.getName()));
return;
}
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, Integer.parseInt(args[2]), false);
sender.sendMessage(getMessage("endtimerStarted").replace("%TIME%", runnable.getTime()));
} else
sender.sendMessage(helpMessage);
}
@Override
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getMaintenanceServersCompletion(args[1].toLowerCase()) : Collections.emptyList();
}
}
@@ -0,0 +1,80 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.command.subcommand;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.Collections;
import java.util.List;
public final class SingleStarttimerCommand extends ProxyCommandInfo {
public SingleStarttimerCommand(final MaintenanceProxyPlugin plugin) {
super(plugin, null, "§6/maintenance starttimer [server] <minutes> §7(After the given time in minutes, maintenance mode will be enabled)");
}
@Override
public boolean hasPermission(final SenderInfo sender) {
return sender.hasMaintenancePermission("timer") || sender.hasPermission("maintenance.singleserver.timer");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (args.length == 2) {
if (checkPermission(sender, "timer")) return;
if (plugin.getCommandManager().checkTimerArgs(sender, args[1])) {
sender.sendMessage(helpMessage);
return;
}
if (plugin.isMaintenance()) {
sender.sendMessage(getMessage("alreadyEnabled"));
return;
}
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), true);
sender.sendMessage(getMessage("starttimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
} else if (args.length == 3) {
if (checkPermission(sender, "singleserver.timer")) return;
if (plugin.getCommandManager().checkTimerArgs(sender, args[2], false)) {
sender.sendMessage(helpMessage);
return;
}
final Server server = plugin.getCommandManager().checkSingleTimerArgs(sender, args);
if (server == null) return;
if (plugin.isMaintenance(server)) {
sender.sendMessage(getMessage("singleServerAlreadyEnabled").replace("%SERVER%", server.getName()));
return;
}
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, Integer.parseInt(args[2]), true);
sender.sendMessage(getMessage("starttimerStarted").replace("%TIME%", runnable.getTime()));
} else
sender.sendMessage(helpMessage);
}
@Override
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getServersCompletion(args[1].toLowerCase()) : Collections.emptyList();
}
}
@@ -0,0 +1,84 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.command.subcommand;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
import eu.kennytv.maintenance.core.proxy.server.DummyServer;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.Collections;
import java.util.List;
public final class SingleToggleCommand extends ProxyCommandInfo {
public SingleToggleCommand(final MaintenanceProxyPlugin plugin) {
super(plugin, null, "§6/maintenance <on/off> [server] §7(Enables/disables maintenance mode)");
}
@Override
public boolean hasPermission(final SenderInfo sender) {
return sender.hasMaintenancePermission("toggle") || sender.hasPermission("maintenance.singleserver.toggle");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (args.length == 1) {
if (checkPermission(sender, "toggle")) return;
final boolean maintenance = args[0].equalsIgnoreCase("on");
if (maintenance == plugin.isMaintenance()) {
sender.sendMessage(getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
return;
}
plugin.setMaintenance(maintenance);
} else if (args.length == 2) {
if (checkPermission(sender, "singleserver.toggle")) return;
final boolean maintenance = args[0].equalsIgnoreCase("on");
Server server = plugin.getServer(args[1]);
if (server == null) {
if (maintenance) {
sender.sendMessage(getMessage("serverNotFound"));
return;
}
// Let servers be removed from the maintenance list, even if they don't exist on the proxy
server = new DummyServer(args[1]);
if (!plugin.isMaintenance(server)) {
sender.sendMessage(getMessage("serverNotFound"));
return;
}
}
if (plugin.setMaintenanceToServer(server, maintenance)) {
if (!sender.isPlayer() || !plugin.getServer(sender).equals(server.getName()))
sender.sendMessage(getMessage(maintenance ? "singleMaintenanceActivated" : "singleMaintenanceDeactivated").replace("%SERVER%", server.getName()));
} else
sender.sendMessage(getMessage(maintenance ? "singleServerAlreadyEnabled" : "singleServerAlreadyDisabled").replace("%SERVER%", server.getName()));
} else
sender.sendMessage(helpMessage);
}
@Override
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
if (args.length != 2 || !sender.hasMaintenancePermission("singleserver.toggle")) return Collections.emptyList();
return args[0].equalsIgnoreCase("off") ? plugin.getCommandManager().getMaintenanceServersCompletion(args[1].toLowerCase())
: plugin.getCommandManager().getServersCompletion(args[1].toLowerCase());
}
}
@@ -0,0 +1,40 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.command.subcommand;
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
public final class StatusCommand extends ProxyCommandInfo {
public StatusCommand(final MaintenanceProxyPlugin plugin) {
super(plugin, "singleserver.status", "§6/maintenance status §7(Lists all proxied servers, that are currently under maintenance)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (getSettings().getMaintenanceServers().isEmpty()) {
sender.sendMessage(getMessage("singleServerMaintenanceListEmpty"));
} else {
sender.sendMessage(getMessage("singleServerMaintenanceList"));
getSettings().getMaintenanceServers().forEach(server -> sender.sendMessage("§8- §b" + server));
}
}
}
@@ -1,4 +1,4 @@
package eu.kennytv.maintenance.bungee.mysql;
package eu.kennytv.maintenance.core.proxy.mysql;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
@@ -12,6 +12,7 @@ import java.util.function.Consumer;
public final class MySQL {
private final HikariDataSource hikariDataSource;
// Excuse me and everything to do with the MySQL stuff, I have little to no idea of how to use databases
public MySQL(final String hostname, final int port, final String username, final String password, final String database) {
final HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setMaximumPoolSize(10);
@@ -60,8 +61,8 @@ public final class MySQL {
}
}
public void close() {
if (hikariDataSource != null && !hikariDataSource.isClosed())
hikariDataSource.close();
public void executeUpdate(final String query, final Object... objects) {
executeUpdate(query, res -> {
}, objects);
}
}
@@ -0,0 +1,49 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.runnable;
import eu.kennytv.maintenance.api.proxy.IMaintenanceProxy;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
public final class SingleMaintenanceRunnable extends MaintenanceRunnableBase {
private final Server server;
public SingleMaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int minutes, final boolean enable, final Server server) {
super(plugin, settings, minutes, enable);
this.server = server;
}
@Override
protected void finish() {
((IMaintenanceProxy) plugin).setMaintenanceToServer(server, enable);
}
@Override
protected String startMessageKey() {
return settings.getMessage("singleStarttimerBroadcast").replace("%TIME%", getTime()).replace("%SERVER%", server.getName());
}
@Override
protected String endMessageKey() {
return settings.getMessage("singleEndtimerBroadcast").replace("%TIME%", getTime()).replace("%SERVER%", server.getName());
}
}
@@ -0,0 +1,43 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.server;
import eu.kennytv.maintenance.api.proxy.Server;
public final class DummyServer implements Server {
private final String name;
public DummyServer(final String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public boolean hasPlayers() {
return false;
}
@Override
public void broadcast(String s) {
}
}
@@ -3,47 +3,45 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-base</artifactId>
<version>2.2</version>
<artifactId>maintenance-parent</artifactId>
<version>3.0</version>
</parent>
<artifactId>maintenancebungee</artifactId>
<name>MaintenanceBungee</name>
<repositories>
<repository>
<id>bungeecord-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
<artifactId>maintenance-core</artifactId>
<name>MaintenanceCore</name>
<dependencies>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-core</artifactId>
<version>2.2</version>
<scope>provided</scope>
<artifactId>maintenance-api</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.12-SNAPSHOT</version>
<scope>provided</scope>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.23</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.minecrell</groupId>
<artifactId>ServerListPlus</artifactId>
<version>3.4.8</version>
<version>3.4.9-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.7.8</version>
<scope>compile</scope>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
</project>
@@ -0,0 +1,6 @@
package eu.kennytv.maintenance.core.util;
public final class MaintenanceVersion {
public static final String VERSION = "${project.version}";
}
@@ -0,0 +1,313 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core;
import com.google.common.io.CharStreams;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.core.command.MaintenanceCommand;
import eu.kennytv.maintenance.core.dump.MaintenanceDump;
import eu.kennytv.maintenance.core.dump.PluginDump;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
import eu.kennytv.maintenance.core.util.SenderInfo;
import eu.kennytv.maintenance.core.util.ServerType;
import eu.kennytv.maintenance.core.util.Task;
import eu.kennytv.maintenance.core.util.Version;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class MaintenancePlugin implements IMaintenance {
protected final Version version;
protected Settings settings;
protected ServerListPlusHook serverListPlusHook;
protected MaintenanceRunnable runnable;
protected MaintenanceCommand commandManager;
private final String prefix;
private final ServerType serverType;
private Version newestVersion;
private Task task;
protected MaintenancePlugin(final String version, final ServerType serverType) {
this.version = new Version(version);
this.serverType = serverType;
this.prefix = "§8[§eMaintenance" + serverType + "§8] ";
}
@Override
public void setMaintenance(final boolean maintenance) {
settings.setMaintenance(maintenance);
settings.getConfig().set("maintenance-enabled", maintenance);
settings.saveConfig();
serverActions(maintenance);
}
public void serverActions(final boolean maintenance) {
if (isTaskRunning())
cancelTask();
if (serverListPlusHook != null)
serverListPlusHook.setEnabled(!maintenance);
if (maintenance) {
kickPlayers();
broadcast(settings.getMessage("maintenanceActivated"));
} else
broadcast(settings.getMessage("maintenanceDeactivated"));
}
public String formatedTimer() {
if (!isTaskRunning()) return "-";
final int preHours = runnable.getSecondsLeft() / 60;
final int minutes = preHours % 60;
final int seconds = runnable.getSecondsLeft() % 60;
return String.format("%02d:%02d:%02d", preHours / 60, minutes, seconds);
}
public void startMaintenanceRunnable(final int minutes, final boolean enable) {
runnable = new MaintenanceRunnable(this, settings, minutes, enable);
task = startMaintenanceRunnable(runnable);
}
public boolean updateAvailable() {
checkNewestVersion();
return version.compareTo(newestVersion) == -1;
}
protected void sendEnableMessage() {
getLogger().info("Plugin by KennyTV");
if (!settings.hasUpdateChecks()) return;
async(() -> {
checkNewestVersion();
final int compare = version.compareTo(newestVersion);
if (compare == -1) {
getLogger().info("§cNewest version available: §aVersion " + newestVersion + "§c, you're on §a" + version);
} else if (compare == 1) {
if (version.getTag().equalsIgnoreCase("snapshot")) {
getLogger().info("§cYou're running a development version, please report bugs on the Discord server (https://kennytv.eu/discord) or the GitHub issue tracker (https://kennytv.eu/maintenance/issues)");
} else {
getLogger().info("§cYou're running a version, that doesn't exist! §cN§ai§dc§ee§5!");
}
}
});
}
public boolean installUpdate() {
try {
final URLConnection conn = new URL("https://github.com/KennyTV/Maintenance/releases/download/" + newestVersion + "/Maintenance.jar").openConnection();
writeFile(new BufferedInputStream(conn.getInputStream()), new BufferedOutputStream(new FileOutputStream(getPluginFolder() + "Maintenance.tmp")));
final File file = new File(getPluginFolder() + "Maintenance.tmp");
final long newlength = file.length();
if (newlength < 10000) {
file.delete();
return false;
}
writeFile(new FileInputStream(file), new BufferedOutputStream(new FileOutputStream(getPluginFile())));
file.delete();
return true;
} catch (final Exception e) {
e.printStackTrace();
return false;
}
}
private void writeFile(final InputStream is, final OutputStream os) throws IOException {
final byte[] chunk = new byte[1024];
int chunkSize;
while ((chunkSize = is.read(chunk)) != -1) {
os.write(chunk, 0, chunkSize);
}
is.close();
os.close();
}
private void checkNewestVersion() {
try {
final HttpURLConnection c = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=40699").openConnection();
final BufferedReader reader = new BufferedReader(new InputStreamReader(c.getInputStream()));
final String newVersionString = reader.readLine();
reader.close();
final Version newVersion = new Version(newVersionString);
if (!newVersion.equals(version))
newestVersion = newVersion;
} catch (final Exception ignored) {
}
}
public String pasteDump() {
final MaintenanceDump dump = new MaintenanceDump(this, settings);
try {
final HttpURLConnection connection = (HttpURLConnection) new URL("https://hasteb.in/documents").openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("User-Agent", "Maintenance/" + getVersion());
connection.setRequestProperty("Content-Type", "text/plain");
final GsonBuilder gsonBuilder = new GsonBuilder();
final byte[] bytes = gsonBuilder.setPrettyPrinting().create().toJson(dump).getBytes(StandardCharsets.UTF_8);
connection.setRequestProperty("Content-Length", Integer.toString(bytes.length));
final OutputStream out = connection.getOutputStream();
out.write(bytes);
out.close();
if (connection.getResponseCode() == 503) {
getLogger().warning("Could not paste dump, hasteb.in down?");
return null;
}
final InputStream in = connection.getInputStream();
final String output = CharStreams.toString(new InputStreamReader(in));
in.close();
final JsonObject jsonOutput = gsonBuilder.create().fromJson(output, JsonObject.class);
if (!jsonOutput.has("key")) {
getLogger().log(Level.WARNING, "Could not paste dump, there was no key returned :(");
return null;
}
return jsonOutput.get("key").getAsString();
} catch (final IOException e) {
getLogger().log(Level.WARNING, "Could not paste dump :(", e);
return null;
}
}
public void loadMaintenanceIcon() {
final File file = new File(getDataFolder(), "maintenance-icon.png");
if (!file.exists()) {
getLogger().warning("Could not find a 'maintenance-icon.png' file - did you create one in the plugin's folder?");
return;
}
try {
loadIcon(file);
} catch (final Exception e) {
getLogger().log(Level.WARNING, "Could not load the 'maintenance-icon.png' file!", e);
e.printStackTrace();
}
}
public void cancelTask() {
task.cancel();
runnable = null;
task = null;
}
public UUID checkUUID(final SenderInfo sender, final String s) {
final UUID uuid;
try {
uuid = UUID.fromString(s);
} catch (final Exception e) {
sender.sendMessage(settings.getMessage("invalidUuid"));
return null;
}
return uuid;
}
public boolean isNumeric(final String string) {
return string.matches("[0-9]+");
}
@Override
public boolean isMaintenance() {
return settings.isMaintenance();
}
@Override
public boolean isTaskRunning() {
return task != null && runnable != null;
}
@Override
public Settings getSettings() {
return settings;
}
@Override
public String getVersion() {
return version.toString();
}
public List<String> getMaintenanceServers() {
return isMaintenance() ? Arrays.asList("global") : null;
}
public Version getNewestVersion() {
return newestVersion;
}
public String getPrefix() {
return prefix;
}
public MaintenanceRunnable getRunnable() {
return runnable;
}
public MaintenanceCommand getCommandManager() {
return commandManager;
}
public ServerType getServerType() {
return serverType;
}
protected String getPluginFolder() {
return "plugins/";
}
public abstract void async(Runnable runnable);
public abstract void broadcast(String message);
public abstract void sendUpdateNotification(SenderInfo sender);
public abstract SenderInfo getOfflinePlayer(String name);
public abstract SenderInfo getOfflinePlayer(UUID uuid);
public abstract File getDataFolder();
public abstract InputStream getResource(String name);
public abstract Logger getLogger();
public abstract String getServerVersion();
public abstract List<PluginDump> getPlugins();
protected abstract void loadIcon(File file) throws Exception;
protected abstract void kickPlayers();
protected abstract Task startMaintenanceRunnable(Runnable runnable);
protected abstract File getPluginFile();
}
@@ -0,0 +1,396 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core;
import eu.kennytv.maintenance.api.ISettings;
import eu.kennytv.maintenance.core.config.Config;
import eu.kennytv.maintenance.core.util.ServerType;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.*;
import java.util.logging.Level;
public class Settings implements ISettings {
private static final Random RANDOM = new Random();
protected final MaintenancePlugin plugin;
private final Map<UUID, String> whitelistedPlayers = new HashMap<>();
private final String[] unsupportedFields;
protected boolean maintenance;
private Set<Integer> broadcastIntervals;
private List<String> pingMessages;
private String playerCountMessage;
private String playerCountHoverMessage;
private String languageName;
private boolean customPlayerCountMessage;
private boolean customMaintenanceIcon;
private boolean joinNotifications;
private boolean updateChecks;
private boolean debug;
protected Config config;
protected Config language;
protected Config whitelist;
public Settings(final MaintenancePlugin plugin, final String... unsupportedFields) {
this.plugin = plugin;
this.unsupportedFields = unsupportedFields;
if (!plugin.getDataFolder().exists())
plugin.getDataFolder().mkdirs();
createFile("config.yml");
createFile("WhitelistedPlayers.yml");
reloadConfigs();
}
@Override
public void reloadConfigs() {
try {
config = new Config(new File(plugin.getDataFolder(), "config.yml"), unsupportedFields);
config.load();
config.resetAwesomeHeader();
whitelist = new Config(new File(plugin.getDataFolder(), "WhitelistedPlayers.yml"));
whitelist.load();
} catch (final IOException e) {
throw new RuntimeException("Unable to load Maintenance files!", e);
}
loadSettings();
createLanguageFile();
try {
language = new Config(new File(plugin.getDataFolder(), "language-" + languageName + ".yml"));
language.load();
} catch (final IOException e) {
throw new RuntimeException("Unable to load Maintenance language file!", e);
}
// Directly save colored messages
for (final Map.Entry<String, Object> entry : language.getValues().entrySet()) {
if (!(entry.getValue() instanceof String)) continue;
entry.setValue(getColoredString((String) entry.getValue()));
}
}
public void saveConfig() {
try {
config.save();
} catch (final IOException e) {
e.printStackTrace();
}
}
protected void createFile(final String name) {
final File file = new File(plugin.getDataFolder(), name);
if (!file.exists()) {
try (final InputStream in = plugin.getResource(name)) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
throw new RuntimeException("Unable to create " + name + " file for Maintenance!", e);
}
}
}
private void saveWhitelistedPlayers() {
try {
whitelist.save();
} catch (final IOException e) {
e.printStackTrace();
}
}
private void createLanguageFile() {
final File file = new File(plugin.getDataFolder(), "language-" + languageName + ".yml");
if (!file.exists()) {
try (final InputStream in = plugin.getResource("language-" + languageName + ".yml")) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
plugin.getLogger().warning("Unable to provide language " + languageName);
if (!languageName.equals("en")) {
plugin.getLogger().warning("Falling back to default language: en");
languageName = "en";
createLanguageFile();
}
}
}
}
private void loadSettings() {
updateConfig();
pingMessages = config.getStringList("pingmessages");
maintenance = config.getBoolean("maintenance-enabled");
customPlayerCountMessage = config.getBoolean("enable-playercountmessage");
customMaintenanceIcon = config.getBoolean("custom-maintenance-icon");
joinNotifications = config.getBoolean("send-join-notification");
broadcastIntervals = new HashSet<>(config.getIntList("timer-broadcast-for-seconds"));
if (plugin.getServerType() != ServerType.SPONGE)
playerCountMessage = getColoredString(getConfigString("playercountmessage"));
playerCountHoverMessage = getColoredString(getConfigString("playercounthovermessage"));
languageName = getConfigString("language").toLowerCase();
updateChecks = config.getBoolean("update-checks", true);
debug = config.getBoolean("debug");
if (customMaintenanceIcon) {
plugin.loadMaintenanceIcon();
}
whitelistedPlayers.clear();
whitelist.getValues().forEach((key, value) -> {
try {
whitelistedPlayers.put(UUID.fromString(key), (String) value);
} catch (final Exception e) {
plugin.getLogger().warning("invalid WhitelistedPlayers entry: " + key);
}
});
loadExtraSettings();
}
private void updateConfig() {
boolean changed = false;
// 3.0 - update config format from 2.5
if (migrateConfig(new File(plugin.getDataFolder(), "bungee-config.yml"))
|| migrateConfig(new File(plugin.getDataFolder(), "spigot-config.yml"))) {
// Also rename old language file
final File file = new File(plugin.getDataFolder(), "language-" + languageName + ".yml");
if (file.exists()) {
if (file.renameTo(new File(plugin.getDataFolder(), "language-" + languageName + ".old")))
plugin.getLogger().info("Renamed old language file!");
else
plugin.getLogger().warning("Could not rename old language file! Please rename/delete it yourself as soon as possible!");
}
changed = true;
}
// 3.0 - move SpigotServer.yml fields to config
if (plugin.getServerType() == ServerType.BUNGEE && migrateSpigotServersFile()) {
changed = true;
}
// 3.0 - move maintenace-icon from server to plugin directory
final File icon = new File("maintenance-icon.png");
if (icon.exists()) {
if (icon.renameTo(new File(plugin.getDataFolder(), "maintenance-icon.png")))
plugin.getLogger().info("Moved maintenance-icon from server directory to the plugin's directory!");
else
plugin.getLogger().warning("Could not move maintenance-icon from server directory to the plugin's directory! Please do so yourself!");
}
if (changed) {
saveConfig();
plugin.getLogger().info("Done! Updated all configs to the new format!");
}
}
private boolean migrateConfig(final File file) {
if (!file.exists()) return false;
plugin.getLogger().info("Migrating old config to new format...");
final Config oldConfig = new Config(file);
try {
oldConfig.load();
} catch (final IOException e) {
plugin.getLogger().log(Level.WARNING, "Error while trying to migrate old config file", e);
return false;
}
if (oldConfig.contains("pingmessage"))
config.set("pingmessages", Arrays.asList(oldConfig.getString("pingmessage")));
if (oldConfig.contains("enable-maintenance-mode"))
config.set("maintenance-enabled", oldConfig.getBoolean("enable-maintenance-mode"));
config.getValues().entrySet().forEach(entry -> {
if (!oldConfig.contains(entry.getKey())) return;
entry.setValue(oldConfig.get(entry.getKey()));
});
oldConfig.clear();
if (!file.delete())
plugin.getLogger().warning("Could not delete old config file! Please delete it as soon as possible.");
else
plugin.getLogger().info("Updated to new config file!");
return true;
}
private boolean migrateSpigotServersFile() {
final File file = new File(plugin.getDataFolder(), "SpigotServers.yml");
if (!file.exists()) return false;
final Config oldFile = new Config(file);
try {
oldFile.load();
} catch (final IOException e) {
plugin.getLogger().log(Level.WARNING, "Error while trying to migrate old SpigotServers file", e);
return false;
}
if (oldFile.contains("maintenance-on"))
config.set("proxied-maintenance-servers", oldFile.getStringList("maintenance-on"));
if (oldFile.contains("fallback"))
config.set("fallback", oldFile.getString("fallback"));
oldFile.clear();
if (!file.delete())
plugin.getLogger().warning("Could not delete old SpigotServers.yml file! Please delete it as soon as possible.");
else
plugin.getLogger().info("Deleted old SpigotServers.yml file!");
return true;
}
private static final String ALL_CODES = "0123456789AaBbCcDdEeFfKkLlMmNnOoRr";
public String getColoredString(final String s) {
// Method taken from Bungee
final char[] b = s.toCharArray();
for (int i = 0; i < b.length - 1; i++) {
if (b[i] == '&' && ALL_CODES.indexOf(b[i + 1]) > -1) {
b[i] = '§';
b[i + 1] = Character.toLowerCase(b[i + 1]);
}
}
return new String(b);
}
public String getConfigString(final String path) {
if (!config.contains(path)) {
plugin.getLogger().warning("The config is missing the following string: " + path);
return "null";
}
return config.getString(path);
}
public String getMessage(final String path) {
return getMessage(path, "null");
}
public String getMessage(final String path, final String def) {
if (!language.contains(path)) {
plugin.getLogger().warning("The language file is missing the following string: " + path);
return def;
}
return language.getString(path);
}
public String getRandomPingMessage() {
if (pingMessages.isEmpty()) return "";
final String s = pingMessages.size() > 1 ? pingMessages.get(RANDOM.nextInt(pingMessages.size())) : pingMessages.get(0);
return getColoredString(s.replace("%NEWLINE%", "\n").replace("%TIMER%", plugin.formatedTimer()));
}
@Override
public boolean removeWhitelistedPlayer(final UUID uuid) {
if (!whitelistedPlayers.containsKey(uuid)) return false;
whitelistedPlayers.remove(uuid);
whitelist.remove(uuid.toString());
saveWhitelistedPlayers();
return true;
}
@Deprecated
@Override
public boolean removeWhitelistedPlayer(final String name) {
final Map.Entry<UUID, String> entry = whitelistedPlayers.entrySet().stream().filter(e -> e.getValue().equalsIgnoreCase(name)).findAny().orElse(null);
if (entry == null) return false;
final UUID uuid = entry.getKey();
whitelistedPlayers.remove(uuid);
whitelist.remove(uuid.toString());
saveWhitelistedPlayers();
return true;
}
@Override
public boolean addWhitelistedPlayer(final UUID uuid, final String name) {
final boolean contains = !whitelistedPlayers.containsKey(uuid);
whitelistedPlayers.put(uuid, name);
whitelist.set(uuid.toString(), name);
saveWhitelistedPlayers();
return contains;
}
@Override
public Map<UUID, String> getWhitelistedPlayers() {
return whitelistedPlayers;
}
@Override
public boolean isMaintenance() {
return maintenance;
}
public void setMaintenance(final boolean maintenance) {
this.maintenance = maintenance;
}
@Override
public boolean isJoinNotifications() {
return joinNotifications;
}
@Override
public boolean hasCustomIcon() {
return customMaintenanceIcon;
}
@Override
public boolean debugEnabled() {
return debug;
}
public boolean hasUpdateChecks() {
return updateChecks;
}
public Config getConfig() {
return config;
}
public List<String> getPingMessages() {
return pingMessages;
}
public Set<Integer> getBroadcastIntervals() {
return broadcastIntervals;
}
public String getPlayerCountMessage() {
return playerCountMessage.replace("%TIMER%", plugin.formatedTimer());
}
public String getPlayerCountHoverMessage() {
return playerCountHoverMessage.replace("%TIMER%", plugin.formatedTimer());
}
public String getKickMessage() {
return getMessage("kickmessage", "§cThe server is currently under maintenance!%NEWLINE%§cTry again later!")
.replace("%NEWLINE%", "\n").replace("%TIMER%", plugin.formatedTimer());
}
public String getLanguage() {
return languageName;
}
public boolean hasCustomPlayerCountMessage() {
return customPlayerCountMessage;
}
protected void loadExtraSettings() {
}
}
@@ -0,0 +1,76 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.Collections;
import java.util.List;
public abstract class CommandInfo {
protected final MaintenancePlugin plugin;
protected final String helpMessage;
private final String permission;
protected CommandInfo(final MaintenancePlugin plugin, final String permission, final String helpMessage) {
this.plugin = plugin;
this.permission = permission;
this.helpMessage = helpMessage;
}
public boolean hasPermission(final SenderInfo sender) {
return sender.hasMaintenancePermission(permission);
}
public String getHelpMessage() {
return helpMessage;
}
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
return Collections.emptyList();
}
public abstract void execute(SenderInfo sender, String[] args);
protected boolean checkPermission(final SenderInfo sender, final String permission) {
if (!sender.hasMaintenancePermission(permission)) {
sender.sendMessage(getMessage("noPermission"));
return true;
}
return false;
}
protected boolean checkArgs(final SenderInfo sender, final String[] args, final int length) {
if (args.length != length) {
sender.sendMessage(helpMessage);
return true;
}
return false;
}
protected String getMessage(final String s) {
return plugin.getSettings().getMessage(s);
}
protected Settings getSettings() {
return plugin.getSettings();
}
}
@@ -0,0 +1,162 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.command.subcommand.*;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.*;
import java.util.stream.Collectors;
public abstract class MaintenanceCommand {
protected final MaintenancePlugin plugin;
protected final Settings settings;
private final Map<String, CommandInfo> commandExecutors = new LinkedHashMap<>();
private final List<CommandInfo> commands = new ArrayList<>();
private final HelpCommand help;
protected MaintenanceCommand(final MaintenancePlugin plugin, final Settings settings) {
this.plugin = plugin;
this.settings = settings;
help = new HelpCommand(plugin);
}
protected void registerCommands() {
add(help, "help");
add(new ReloadCommand(plugin), "reload");
addToggleAndTimerCommands();
add(new WhitelistCommand(plugin), "whitelist");
add(new WhitelistAddCommand(plugin), "add");
add(new WhitelistRemoveCommand(plugin), "remove");
add(new SetMotdCommand(plugin), "setmotd");
add(new RemoveMotdCommand(plugin), "removemotd");
add(new MotdCommand(plugin), "motd");
add(new UpdateCommand(plugin), "update", "forceupdate");
add(new DumpCommand(plugin), "dump");
}
protected void add(final CommandInfo command, final String... aliases) {
commands.add(command);
for (final String alias : aliases) {
commandExecutors.put(alias, command);
}
}
public void execute(final SenderInfo sender, final String[] args) {
if (!sender.hasMaintenancePermission("command")) {
sender.sendMessage(settings.getMessage("noPermission"));
return;
}
if (args.length == 0) {
help.sendUsage(sender);
return;
}
final CommandInfo command = commandExecutors.get(args[0].toLowerCase());
if (command == null) {
help.sendUsage(sender);
return;
}
if (!command.hasPermission(sender)) {
sender.sendMessage(settings.getMessage("noPermission"));
return;
}
command.execute(sender, args);
}
public List<String> getSuggestions(final SenderInfo sender, final String[] args) {
if (!sender.hasMaintenancePermission("command") || args.length == 0) return Collections.emptyList();
final String s = args[0].toLowerCase();
if (args.length == 1)
return commandExecutors.entrySet().stream().filter(entry -> entry.getKey().startsWith(s) && entry.getValue().hasPermission(sender)).map(Map.Entry::getKey).collect(Collectors.toList());
final CommandInfo info = commandExecutors.get(args[0]);
return info != null && info.hasPermission(sender) ? info.getTabCompletion(sender, args) : Collections.emptyList();
}
public boolean checkTimerArgs(final SenderInfo sender, final String time, final boolean taskCheck) {
if (!plugin.isNumeric(time)) return true;
if (taskCheck) {
if (plugin.isTaskRunning()) {
sender.sendMessage(settings.getMessage("timerAlreadyRunning"));
return true;
}
}
final int minutes = Integer.parseInt(time);
if (minutes > 40320) {
sender.sendMessage(settings.getMessage("timerTooLong"));
return true;
}
if (minutes < 1) {
sender.sendMessage("§8§o[KennyTV whispers to you] §7§oThink about running a timer for a negative amount of minutes. Doesn't work §lthat §7§owell.");
return true;
}
return false;
}
public boolean checkTimerArgs(final SenderInfo sender, final String time) {
return checkTimerArgs(sender, time, true);
}
protected void addToggleAndTimerCommands() {
add(new ToggleCommand(plugin), "on", "off");
add(new StarttimerCommand(plugin), "starttimer", "start");
add(new EndtimerCommand(plugin), "endtimer", "end");
add(new AbortTimerCommand(plugin), "aborttimer", "abort");
}
public void checkForUpdate(final SenderInfo sender) {
if (plugin.updateAvailable()) {
sender.sendMessage(plugin.getPrefix() + "§cNewest version available: §aVersion " + plugin.getNewestVersion() + "§c, you're on §a" + plugin.getVersion());
sender.sendMessage(plugin.getPrefix() + "§c§lWARNING: §cYou will have to restart the server to prevent further issues and to complete the update! If you can't do that, don't update!");
sendUpdateMessage(sender);
} else
sender.sendMessage(plugin.getPrefix() + "§aYou already have the latest version of the plugin!");
}
protected void sendUpdateMessage(final SenderInfo sender) {
sender.sendMessage(plugin.getPrefix() + "§eUse §c§l/maintenance forceupdate §eto update!");
}
public List<String> getServersCompletion(final String s) {
return null;
}
public List<String> getMaintenanceServersCompletion(final String s) {
return null;
}
public List<String> getPlayersCompletion() {
return null;
}
public abstract void sendDumpMessage(final SenderInfo sender, final String url);
public List<CommandInfo> getCommands() {
return commands;
}
}
@@ -0,0 +1,46 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
public final class AbortTimerCommand extends CommandInfo {
public AbortTimerCommand(final MaintenancePlugin plugin) {
super(plugin, "timer", "§6/maintenance aborttimer §7(If running, the current timer will be aborted)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (args.length != 1) {
sender.sendMessage(helpMessage);
return;
}
if (!plugin.isTaskRunning()) {
sender.sendMessage(getMessage("timerNotRunning"));
return;
}
plugin.cancelTask();
sender.sendMessage(getMessage("timerCancelled"));
}
}
@@ -0,0 +1,58 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.concurrent.TimeUnit;
public final class DumpCommand extends CommandInfo {
private long lastDump;
public DumpCommand(final MaintenancePlugin plugin) {
super(plugin, "dump", "§6/maintenance dump §7(Dumps some server information, used for bug reports)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 1)) return;
if (System.currentTimeMillis() - lastDump < TimeUnit.MINUTES.toMillis(5)) {
sender.sendMessage(plugin.getPrefix() + "§cYou can only create a dump every 5 minutes!");
return;
}
lastDump = System.currentTimeMillis();
sender.sendMessage(plugin.getPrefix() + "§7The dump is being created, this might take a moment.");
plugin.async(() -> {
final String key = plugin.pasteDump();
if (key == null) {
if (sender.isPlayer())
sender.sendMessage(plugin.getPrefix() + "§cCould not paste dump (see the console for details)");
return;
}
final String url = "https://hasteb.in/" + key;
sender.sendMessage(plugin.getPrefix() + "§c" + url);
if (sender.isPlayer())
plugin.getCommandManager().sendDumpMessage(sender, url);
});
}
}
@@ -0,0 +1,46 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
public final class EndtimerCommand extends CommandInfo {
public EndtimerCommand(final MaintenancePlugin plugin) {
super(plugin, "timer", "§6/maintenance endtimer <minutes> §7(After the given time in minutes, maintenance mode will be disabled)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 2)) return;
if (plugin.getCommandManager().checkTimerArgs(sender, args[1])) {
sender.sendMessage(helpMessage);
return;
}
if (!plugin.isMaintenance()) {
sender.sendMessage(getMessage("alreadyDisabled"));
return;
}
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), false);
sender.sendMessage(getMessage("endtimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
}
}
@@ -0,0 +1,90 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import com.google.common.base.Preconditions;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.List;
import java.util.stream.Collectors;
public final class HelpCommand extends CommandInfo {
private static final int COMMANDS_PER_PAGE = 8;
public HelpCommand(final MaintenancePlugin plugin) {
super(plugin, null, "§6/maintenance help [page] §7(Shows this beautiful help window)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (args.length > 2) {
sender.sendMessage(helpMessage);
return;
}
if (args.length == 1) {
sendUsage(sender);
} else {
if (!plugin.isNumeric(args[1])) {
sender.sendMessage(helpMessage);
return;
}
final int page = Integer.parseInt(args[1]);
sendUsage(sender, page == 0 ? 1 : page);
}
}
public void sendUsage(final SenderInfo sender) {
sendUsage(sender, 1);
}
public void sendUsage(final SenderInfo sender, final int page) {
Preconditions.checkArgument(page > 0);
final List<String> commands = plugin.getCommandManager().getCommands().stream().filter(cmd -> cmd.hasPermission(sender)).map(CommandInfo::getHelpMessage).collect(Collectors.toList());
if ((page - 1) * COMMANDS_PER_PAGE >= commands.size()) {
sender.sendMessage(getMessage("helpPageNotFound"));
return;
}
final List<String> filteredCommands;
if (page * COMMANDS_PER_PAGE >= commands.size())
filteredCommands = commands.subList((page - 1) * COMMANDS_PER_PAGE, commands.size());
else
filteredCommands = commands.subList((page - 1) * COMMANDS_PER_PAGE, page * COMMANDS_PER_PAGE);
final String header = "§8========[ §eMaintenance" + plugin.getServerType() + " §8| §e" + page + "/" + ((commands.size() + getDivide(commands.size())) / COMMANDS_PER_PAGE) + " §8]========";
sender.sendMessage("");
sender.sendMessage(header);
filteredCommands.forEach(sender::sendMessage);
if (page * COMMANDS_PER_PAGE < commands.size())
sender.sendMessage("§7Use §b/maintenance help " + (page + 1) + " §7to get to the next help window.");
else
sender.sendMessage("§8× §eVersion " + plugin.getVersion() + " §7by §bKennyTV");
sender.sendMessage(header);
sender.sendMessage("");
}
private int getDivide(final int size) {
final int commandSize = size % COMMANDS_PER_PAGE;
return commandSize > 0 ? COMMANDS_PER_PAGE - commandSize : 0;
}
}
@@ -0,0 +1,43 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
public final class MotdCommand extends CommandInfo {
public MotdCommand(final MaintenancePlugin plugin) {
super(plugin, "motd", "§6/maintenance motd §7(Lists the currently set maintenance motds)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 1)) return;
sender.sendMessage(getMessage("motdList"));
for (int i = 0; i < getSettings().getPingMessages().size(); i++) {
sender.sendMessage("§b" + (i + 1) + "§8§m---------");
for (final String motd : getSettings().getColoredString(getSettings().getPingMessages().get(i)).split("%NEWLINE%")) {
sender.sendMessage(motd);
}
}
sender.sendMessage("§8§m----------");
}
}
@@ -0,0 +1,37 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
public final class ReloadCommand extends CommandInfo {
public ReloadCommand(final MaintenancePlugin plugin) {
super(plugin, "reload", "§6/maintenance reload §7(Reloads the config file, whitelist file and the server-icon)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 1)) return;
getSettings().reloadConfigs();
sender.sendMessage(getMessage("reload"));
}
}
@@ -0,0 +1,73 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class RemoveMotdCommand extends CommandInfo {
public RemoveMotdCommand(final MaintenancePlugin plugin) {
super(plugin, "setmotd", "§6/maintenance removemotd <index> §7(Removes a maintenance motd)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 2)) return;
if (!plugin.isNumeric(args[1])) {
sender.sendMessage(helpMessage);
return;
}
final Settings settings = getSettings();
if (settings.getPingMessages().size() < 2) {
sender.sendMessage(getMessage("removeMotdError"));
return;
}
final int index = Integer.parseInt(args[1]);
if (index == 0 || index > settings.getPingMessages().size()) {
sender.sendMessage(getMessage("setMotdIndexError").replace("%MOTDS%", Integer.toString(settings.getPingMessages().size()))
.replace("%NEWAMOUNT%", Integer.toString(settings.getPingMessages().size())));
return;
}
settings.getPingMessages().remove(index - 1);
settings.getConfig().set("pingmessages", settings.getPingMessages());
settings.saveConfig();
sender.sendMessage(getMessage("removedMotd").replace("%INDEX%", args[1]));
}
@Override
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
if (args.length != 2) return Collections.emptyList();
final int size = plugin.getSettings().getPingMessages().size();
final List<String> list = new ArrayList<>(size);
for (int i = 1; i <= size; i++) {
list.add(String.valueOf(i));
}
return list;
}
}
@@ -0,0 +1,95 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public final class SetMotdCommand extends CommandInfo {
public SetMotdCommand(final MaintenancePlugin plugin) {
super(plugin, "setmotd", "§6/maintenance setmotd <index> <1/2> <message> §7(Sets a motd for maintenance mode)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (args.length < 4 || !plugin.isNumeric(args[1])) {
sender.sendMessage(helpMessage);
return;
}
final Settings settings = getSettings();
final int index = Integer.parseInt(args[1]);
if (index == 0 || index > settings.getPingMessages().size() + 1) {
sender.sendMessage(getMessage("setMotdIndexError").replace("%MOTDS%", Integer.toString(settings.getPingMessages().size()))
.replace("%NEWAMOUNT%", Integer.toString(settings.getPingMessages().size() + 1)));
return;
}
if (!plugin.isNumeric(args[2])) {
sender.sendMessage(getMessage("setMotdLineError"));
return;
}
final int line = Integer.parseInt(args[2]);
if (line != 1 && line != 2) {
sender.sendMessage(getMessage("setMotdLineError"));
return;
}
final String message = String.join(" ", Arrays.copyOfRange(args, 3, args.length));
final String oldMessage = index > settings.getPingMessages().size() ? "" : settings.getPingMessages().get(index - 1);
final String newMessage;
if (line == 1)
newMessage = oldMessage.contains("%NEWLINE%") ?
message + "%NEWLINE%" + oldMessage.split("%NEWLINE%", 2)[1] : message;
else
newMessage = oldMessage.contains("%NEWLINE%") ?
oldMessage.split("%NEWLINE%", 2)[0] + "%NEWLINE%" + message : oldMessage + "%NEWLINE%" + message;
if (index > settings.getPingMessages().size())
settings.getPingMessages().add(newMessage);
else
settings.getPingMessages().set(index - 1, newMessage);
settings.getConfig().set("pingmessages", settings.getPingMessages());
settings.saveConfig();
sender.sendMessage(settings.getMessage("setMotd").replace("%LINE%", args[2]).replace("%INDEX%", args[1])
.replace("%MOTD%", "§f" + settings.getColoredString(message)));
}
@Override
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
if (args.length == 3) return Arrays.asList("1", "2");
if (args.length == 2) {
final List<String> list = new ArrayList<>();
for (int i = 1; i <= getSettings().getPingMessages().size() + 1; i++) {
list.add(String.valueOf(i));
}
return list;
}
return Collections.emptyList();
}
}
@@ -0,0 +1,46 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
public final class StarttimerCommand extends CommandInfo {
public StarttimerCommand(final MaintenancePlugin plugin) {
super(plugin, "timer", "§6/maintenance starttimer <minutes> §7(After the given time in minutes, maintenance mode will be enabled)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 2)) return;
if (plugin.getCommandManager().checkTimerArgs(sender, args[1])) {
sender.sendMessage(helpMessage);
return;
}
if (plugin.isMaintenance()) {
sender.sendMessage(getMessage("alreadyEnabled"));
return;
}
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), true);
sender.sendMessage(getMessage("starttimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
}
}
@@ -0,0 +1,43 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
public final class ToggleCommand extends CommandInfo {
public ToggleCommand(final MaintenancePlugin plugin) {
super(plugin, "toggle", "§6/maintenance <on/off> §7(Enables/disables maintenance mode)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 1)) return;
final boolean maintenance = args[0].equalsIgnoreCase("on");
if (maintenance == plugin.isMaintenance()) {
sender.sendMessage(getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
return;
}
plugin.setMaintenance(maintenance);
}
}
@@ -0,0 +1,49 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
public final class UpdateCommand extends CommandInfo {
public UpdateCommand(final MaintenancePlugin plugin) {
super(plugin, "update", "§6/maintenance update §7(Remotely downloads the newest version of the plugin onto your server)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 1)) return;
if (args[0].equalsIgnoreCase("update")) {
plugin.async(() -> plugin.getCommandManager().checkForUpdate(sender));
} else {
if (!plugin.updateAvailable()) {
sender.sendMessage(plugin.getPrefix() + "§aYou already have the latest version of the plugin!");
return;
}
sender.sendMessage(getMessage("updateDownloading"));
if (plugin.installUpdate())
sender.sendMessage(getMessage("updateFinished"));
else
sender.sendMessage(getMessage("updateFailed"));
}
}
}
@@ -0,0 +1,77 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
public final class WhitelistAddCommand extends CommandInfo {
public WhitelistAddCommand(final MaintenancePlugin plugin) {
super(plugin, "whitelist.add", "§6/maintenance add <name/uuid> §7(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 2)) return;
if (args[1].length() == 36) {
final UUID uuid = plugin.checkUUID(sender, args[1]);
if (uuid != null)
addPlayerToWhitelist(sender, uuid);
} else
addPlayerToWhitelist(sender, args[1]);
}
@Override
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
return args.length == 2 ? plugin.getCommandManager().getPlayersCompletion() : Collections.emptyList();
}
private void addPlayerToWhitelist(final SenderInfo sender, final String name) {
final SenderInfo selected = plugin.getOfflinePlayer(name);
if (selected == null) {
sender.sendMessage(getMessage("playerNotOnline"));
return;
}
whitelistAddMessage(sender, selected);
}
private void addPlayerToWhitelist(final SenderInfo sender, final UUID uuid) {
final SenderInfo selected = plugin.getOfflinePlayer(uuid);
if (selected == null) {
sender.sendMessage(getMessage("playerNotFoundUuid"));
return;
}
whitelistAddMessage(sender, selected);
}
private void whitelistAddMessage(final SenderInfo sender, final SenderInfo selected) {
if (getSettings().addWhitelistedPlayer(selected.getUuid(), selected.getName()))
sender.sendMessage(getMessage("whitelistAdded").replace("%PLAYER%", selected.getName()));
else
sender.sendMessage(getMessage("whitelistAlreadyAdded").replace("%PLAYER%", selected.getName()));
}
}
@@ -0,0 +1,48 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.Map;
import java.util.UUID;
public final class WhitelistCommand extends CommandInfo {
public WhitelistCommand(final MaintenancePlugin plugin) {
super(plugin, "whitelist.list", "§6/maintenance whitelist §7(Shows all whitelisted players for the maintenance mode)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 1)) return;
final Map<UUID, String> players = getSettings().getWhitelistedPlayers();
if (players.isEmpty()) {
sender.sendMessage(getMessage("whitelistEmpty"));
} else {
sender.sendMessage(getMessage("whitelistedPlayers"));
final String format = getMessage("whitelistedPlayersFormat");
players.forEach((key, value) -> sender.sendMessage(format.replace("%NAME%", value).replace("%UUID%", key.toString())));
sender.sendMessage("");
}
}
}
@@ -0,0 +1,80 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
public final class WhitelistRemoveCommand extends CommandInfo {
public WhitelistRemoveCommand(final MaintenancePlugin plugin) {
super(plugin, "whitelist.remove", "§6/maintenance remove <name/uuid> §7(Removes the player from the maintenance whitelist)");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 2)) return;
if (args[1].length() == 36) {
final UUID uuid = plugin.checkUUID(sender, args[1]);
if (uuid != null)
removePlayerFromWhitelist(sender, uuid);
} else
removePlayerFromWhitelist(sender, args[1]);
}
@Override
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
return args.length == 2 ? getSettings().getWhitelistedPlayers().values().stream()
.filter(name -> name.toLowerCase().startsWith(args[1])).collect(Collectors.toList()) : Collections.emptyList();
}
private void removePlayerFromWhitelist(final SenderInfo sender, final String name) {
final SenderInfo selected = plugin.getOfflinePlayer(name);
if (selected == null) {
if (getSettings().removeWhitelistedPlayer(name))
sender.sendMessage(getMessage("whitelistRemoved").replace("%PLAYER%", name));
else
sender.sendMessage(getMessage("whitelistNotFound"));
return;
}
whitelistRemoveMessage(sender, selected.getUuid(), selected.getName());
}
private void removePlayerFromWhitelist(final SenderInfo sender, final UUID uuid) {
final SenderInfo selected = plugin.getOfflinePlayer(uuid);
if (selected == null)
whitelistRemoveMessage(sender, uuid, uuid.toString());
else
whitelistRemoveMessage(sender, selected.getUuid(), selected.getName());
}
private void whitelistRemoveMessage(final SenderInfo sender, final UUID uuid, final String toReplace) {
if (getSettings().removeWhitelistedPlayer(uuid))
sender.sendMessage(getMessage("whitelistRemoved").replace("%PLAYER%", toReplace));
else
sender.sendMessage(getMessage("whitelistNotFound"));
}
}
@@ -0,0 +1,172 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.config;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
/**
* Further modified version of the SimpleConfig project of PSandro (https://github.com/PSandro/SimpleConfig).
*
* @author PSandro on 26.01.19
* @author KennyTV
*/
public final class Config extends ConfigSection {
private static final String AWESOME_HEADER =
"#######################################################################################################################\n" +
"# __ __ _ _ _ _ __ _______ __ #\n" +
"# | \\/ | __ _(_)_ __ | |_ ___ _ __ __ _ _ __ ___ ___ | |__ _ _ | |/ /___ _ __ _ __ _ |_ _\\ \\ / / #\n" +
"# | |\\/| |/ _` | | '_ \\| __/ _ \\ '_ \\ / _` | '_ \\ / __/ _ \\ | '_ \\| | | | | ' // _ \\ '_ \\| '_ \\| | | || | \\ \\ / / #\n" +
"# | | | | (_| | | | | | || __/ | | | (_| | | | | (_| __/ | |_) | |_| | | . \\ __/ | | | | | | |_| || | \\ V / #\n" +
"# |_| |_|\\__,_|_|_| |_|\\__\\___|_| |_|\\__,_|_| |_|\\___\\___| |_.__/ \\__, | |_|\\_\\___|_| |_|_| |_|\\__, ||_| \\_/ #\n" +
"# |___/ |___/ #\n" +
"#######################################################################################################################\n" +
"# You can report bugs here: https://github.com/KennyTV/Maintenance/issues\n" +
"# If you need any other help/support, you can also join my Discord server: https://discord.gg/vGCUzHq\n";
private final Yaml yaml = createYaml();
private final File file;
private final Set<String> unsupportedFields;
private Map<String, String[]> comments = new HashMap<>();
private String header;
public Config(final File file, final String... unsupportedFields) {
this.file = file;
this.unsupportedFields = new HashSet<>(Arrays.asList(unsupportedFields));
}
public void load() throws IOException {
final String data = new String(Files.readAllBytes(this.file.toPath()), StandardCharsets.UTF_8);
final Map<String, Object> map = yaml.load(data);
this.values = map != null ? map : new LinkedHashMap<>();
this.comments = ConfigSerializer.deserializeComments(data);
if (comments.containsKey(".header"))
this.header = String.join("\n", comments.remove(".header"));
final boolean removedFields = values.keySet().removeIf(key -> {
final String[] split = key.split("\\.");
String splitKey = "";
boolean remove = false;
for (final String s : split) {
splitKey += s;
if (!unsupportedFields.contains(splitKey)) {
splitKey += ".";
continue;
}
remove = true;
break;
}
if (remove)
comments.remove(key);
return remove;
});
if (removedFields) {
save();
}
}
public void save() throws IOException {
final byte[] bytes = this.saveConfigToString().getBytes(StandardCharsets.UTF_8);
this.file.getParentFile().mkdirs();
this.file.createNewFile();
Files.write(this.file.toPath(), bytes);
}
@Override
public void set(final String key, final Object value, final String... comments) {
if (value == null) {
remove(key);
} else {
this.values.put(key, value);
this.comments.put(key, comments);
}
}
@Override
public void remove(final String key) {
this.values.remove(key);
this.comments.remove(key);
}
/**
* Convenience method, not further established as currently not necessary.
*
* @see #getSection(String)
* @deprecated this config is only made for a quite simple use, only goes one level deeper
*/
@Deprecated
public Object getDeep(final String key) {
final String[] split = key.split("\\.", 2);
if (split.length != 2) return get(key);
final Object o = getObject(split[0]);
if (!(o instanceof Map)) return null;
final Map<String, Object> map = (Map<String, Object>) o;
return map.get(split[1]);
}
public ConfigSection getSection(final String key) {
final Object o = getObject(key);
return o instanceof Map ? new ConfigSection((Map<String, Object>) o) : null;
}
private static Yaml createYaml() {
final DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
options.setPrettyFlow(false);
options.setIndent(2);
return new Yaml(options);
}
public String saveConfigToString() {
return ConfigSerializer.serialize(this.header, this.values, this.comments, this.yaml);
}
public void clear() {
this.values.clear();
this.comments.clear();
this.header = null;
}
public Map<String, String[]> getComments() {
return comments;
}
public Set<String> getUnsupportedFields() {
return unsupportedFields;
}
public String getHeader() {
return header;
}
public void resetAwesomeHeader() {
this.header = AWESOME_HEADER;
}
}
@@ -0,0 +1,141 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.config;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Further modified version of the SimpleConfig project of PSandro (https://github.com/PSandro/SimpleConfig).
*
* @author KennyTV
*/
public class ConfigSection {
protected Map<String, Object> values;
ConfigSection() {
this(new HashMap<>());
}
ConfigSection(final Map<String, Object> values) {
this.values = values;
}
public <E> E get(final String key) {
return (E) this.values.get(key);
}
public Object getObject(final String key) {
return this.values.get(key);
}
public <E> E getOrSet(final String key, final E def) {
if (this.values.containsKey(key)) {
return (E) this.values.get(key);
} else {
this.set(key, def);
return def;
}
}
public boolean contains(final String key) {
return this.values.containsKey(key);
}
public void set(final String key, final Object value) {
if (value == null) {
remove(key);
} else
this.values.put(key, value);
}
public void set(final String key, final Object value, final String... comments) {
if (value == null) {
remove(key);
} else {
this.values.put(key, value);
}
}
public void remove(final String key) {
this.values.remove(key);
}
public Set<String> getKeys() {
return this.values.keySet();
}
public Map<String, Object> getValues() {
return this.values;
}
public boolean getBoolean(final String key) {
final Object o = values.get(key);
return o instanceof Boolean && (boolean) o;
}
public boolean getBoolean(final String key, final boolean def) {
return values.containsKey(key) ? get(key) : def;
}
public String getString(final String key) {
return get(key);
}
public String getString(final String key, final String def) {
return values.containsKey(key) ? get(key) : def;
}
public int getInt(final String key) {
final Object o = values.get(key);
return o instanceof Number ? ((Number) o).intValue() : 0;
}
public int getInt(final String key, final int def) {
return values.containsKey(key) ? get(key) : def;
}
public double getDouble(final String key) {
final Object o = values.get(key);
return o instanceof Number ? ((Number) o).doubleValue() : 0;
}
public double getDouble(final String key, final double def) {
return values.containsKey(key) ? get(key) : def;
}
public List<String> getStringList(final String key) {
return get(key);
}
public List<String> getStringList(final String key, final List<String> def) {
return values.containsKey(key) ? get(key) : def;
}
public List<Integer> getIntList(final String key) {
return get(key);
}
public List<Integer> getIntList(final String key, final List<Integer> def) {
return values.containsKey(key) ? get(key) : def;
}
}
@@ -0,0 +1,143 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.config;
import org.yaml.snakeyaml.Yaml;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Further modified version of the SimpleConfig project of PSandro (https://github.com/PSandro/SimpleConfig).
*
* @author PSandro on 26.01.19
* @author KennyTV
*/
public final class ConfigSerializer {
private static final String[] EMPTY = new String[0];
private static final int INDENT_UNIT = 2;
private static final String PATH_SEPARATOR_STRING = ".";
private static final String PATH_SEPARATOR_QUOTED = Pattern.quote(PATH_SEPARATOR_STRING);
public static String serialize(final String header, final Map<String, Object> data, final Map<String, String[]> comments, final Yaml yaml) {
if (data.isEmpty()) return yaml.dump(null);
final String rawYaml = yaml.dump(data);
final StringBuilder fileData = new StringBuilder();
int currentIndents = 0;
String key = "";
for (final String line : rawYaml.split("\n")) {
if (line.isEmpty()) continue;
final int indent = getIndents(line);
final int indents = indent / INDENT_UNIT;
final String indentText = indent > 0 ? line.substring(0, indent) : "";
if (indents <= currentIndents) {
final String[] array = key.split(PATH_SEPARATOR_QUOTED);
final int backspace = currentIndents - indents + 1;
key = join(array, array.length - backspace);
}
final String separator = key.isEmpty() ? "" : PATH_SEPARATOR_STRING;
final String lineKey = line.contains(":") ? line.split(Pattern.quote(":"))[0] : line;
key += separator + lineKey.substring(indent);
currentIndents = indents;
final String[] strings = comments.get(key);
if (strings != null) {
for (final String comment : strings) {
if (comment.isEmpty())
fileData.append('\n');
else
fileData.append(indentText).append(comment).append('\n');
}
}
fileData.append(line).append('\n');
}
return header != null && !header.isEmpty() ? header + fileData : fileData.toString();
}
public static Map<String, String[]> deserializeComments(final String data) {
final Map<String, String[]> comments = new HashMap<>();
final List<String> currentComments = new ArrayList<>();
boolean header = true;
int currentIndents = 0;
String key = "";
for (final String line : data.split("\n")) {
final String s = line.trim();
if (s.startsWith("#")) {
currentComments.add(s);
continue;
}
if (header) {
if (!currentComments.isEmpty()) {
currentComments.add("");
comments.put(".header", currentComments.toArray(EMPTY));
currentComments.clear();
}
header = false;
}
if (s.isEmpty()) {
currentComments.add(s);
continue;
}
final int indent = getIndents(line);
final int indents = indent / INDENT_UNIT;
if (indents <= currentIndents) {
final String[] array = key.split(PATH_SEPARATOR_QUOTED);
final int backspace = currentIndents - indents + 1;
key = join(array, array.length - backspace);
}
final String separator = key.isEmpty() ? "" : PATH_SEPARATOR_STRING;
final String lineKey = line.contains(":") ? line.split(Pattern.quote(":"))[0] : line;
key += separator + lineKey.substring(indent);
currentIndents = indents;
if (!currentComments.isEmpty()) {
comments.put(key, currentComments.toArray(EMPTY));
currentComments.clear();
}
}
return comments;
}
private static int getIndents(final String line) {
int count = 0;
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == ' ') count++;
else break;
}
return count;
}
private static String join(final String[] array, final int length) {
final String[] copy = new String[length];
System.arraycopy(array, 0, copy, 0, length);
return String.join(PATH_SEPARATOR_STRING, copy);
}
}
@@ -0,0 +1,52 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.dump;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.Map;
public final class MaintenanceDump {
private final ServerDump general;
private final Map<String, Object> configuration;
private final JsonObject plugins;
public MaintenanceDump(final MaintenancePlugin plugin, final Settings settings) {
general = new ServerDump(plugin.getVersion(), plugin.getServerType().toString(), plugin.getServerVersion(), plugin.getMaintenanceServers());
configuration = new LinkedHashMap<>(settings.getConfig().getValues());
final Object o = configuration.get("mysql");
if (o instanceof Map) {
final Map<String, Object> map = new LinkedHashMap<>(((Map<String, Object>) o));
map.keySet().removeIf(key -> !key.equals("use-mysql") && !key.equals("update-interval"));
configuration.put("mysql", map);
}
configuration.put("whitelisted-players", settings.getWhitelistedPlayers());
configuration.put("icon-exists", new File(plugin.getDataFolder(), "maintenance-icon.png").exists());
final JsonObject jsonObject = new JsonObject();
jsonObject.add("plugins", new GsonBuilder().create().toJsonTree(plugin.getPlugins()));
plugins = jsonObject;
}
}
@@ -0,0 +1,33 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.dump;
import java.util.List;
public final class PluginDump {
private final String name;
private final String version;
private final List<String> authors;
public PluginDump(final String name, final String version, final List<String> authors) {
this.name = name;
this.version = version;
this.authors = authors != null && authors.isEmpty() ? null : authors;
}
}
@@ -0,0 +1,35 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.dump;
import java.util.List;
public final class ServerDump {
private final String pluginVersion;
private final String serverType;
private final String serverVersion;
private final List<String> maintenance;
public ServerDump(final String pluginVersion, final String serverType, final String serverVersion, final List<String> maintenance) {
this.pluginVersion = pluginVersion;
this.serverType = serverType;
this.serverVersion = serverVersion;
this.maintenance = maintenance;
}
}
@@ -0,0 +1,36 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.hook;
import net.minecrell.serverlistplus.core.ServerListPlusCore;
import net.minecrell.serverlistplus.core.plugin.ServerListPlusPlugin;
public final class ServerListPlusHook {
private final ServerListPlusCore serverListPlusCore;
public ServerListPlusHook(final Object serverListPlus) {
if (!(serverListPlus instanceof ServerListPlusPlugin))
throw new IllegalArgumentException("Couldn't parse ServerListPlus instance!");
this.serverListPlusCore = ((ServerListPlusPlugin) serverListPlus).getCore();
}
public void setEnabled(final boolean enable) {
serverListPlusCore.getProfiles().setEnabled(enable);
}
}
@@ -0,0 +1,79 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.listener;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public abstract class JoinListenerBase {
protected final MaintenancePlugin plugin;
protected final Settings settings;
protected final UUID notifyUuid = new UUID(-6334418481592579467L, -4779835342378829761L);
private final Set<UUID> notifiedPlayers = new HashSet<>();
protected JoinListenerBase(final MaintenancePlugin plugin, final Settings settings) {
this.plugin = plugin;
this.settings = settings;
}
/**
* Deals with the login and returns true if the player should be kicked after this method.
*
* @param sender wrapper of the joining player
* @return true if the sender should be kicked
*/
protected boolean kickPlayer(final SenderInfo sender, final boolean updateCheck) {
if (settings.isMaintenance() && !sender.getUuid().equals(notifyUuid)) {
if (!sender.hasMaintenancePermission("bypass") && !settings.getWhitelistedPlayers().containsKey(sender.getUuid())) {
if (settings.isJoinNotifications())
broadcastJoinNotification(sender.getName());
return true;
}
}
if (updateCheck)
updateCheck(sender);
return false;
}
protected boolean kickPlayer(final SenderInfo sender) {
return kickPlayer(sender, true);
}
protected void updateCheck(final SenderInfo sender) {
if (sender.getUuid().equals(notifyUuid)) {
sender.sendMessage("§6Maintenance §aVersion " + plugin.getVersion());
return;
}
if (!settings.hasUpdateChecks()) return;
if (!sender.hasPermission("maintenance.admin") || notifiedPlayers.contains(sender.getUuid())) return;
plugin.async(() -> {
if (!plugin.updateAvailable()) return;
notifiedPlayers.add(sender.getUuid());
sender.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + plugin.getNewestVersion() + "§c, you're on §a" + plugin.getVersion());
plugin.sendUpdateNotification(sender);
});
}
protected abstract void broadcastJoinNotification(String name);
}
@@ -0,0 +1,44 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.runnable;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
public final class MaintenanceRunnable extends MaintenanceRunnableBase {
public MaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int minutes, final boolean enable) {
super(plugin, settings, minutes, enable);
}
@Override
protected void finish() {
plugin.setMaintenance(enable);
}
@Override
protected String startMessageKey() {
return settings.getMessage("starttimerBroadcast").replace("%TIME%", getTime());
}
@Override
protected String endMessageKey() {
return settings.getMessage("endtimerBroadcast").replace("%TIME%", getTime());
}
}
Loaded 100 of 144 files, more files were not shown because too many files have changed in this diff. Show more