Compare commits

...
298 Commits
Author SHA1 Message Date
Nassim 29d9fa2ec8 3.0.6 Release 2021-02-17 10:25:23 +01:00
KennyTV ef2ce99746 Prepare for 3.0.6 Release 2021-02-17 10:24:56 +01:00
KennyTV aa5437605f Actually fire the MaintenanceReloadedEvent 2021-02-07 11:40:41 +01:00
KennyTV 22e1d53f81 Update copyright header 2021-02-07 11:32:00 +01:00
KennyTV 1359684c72 Add "maintenance schedule" command 2021-02-07 11:30:20 +01:00
KennyTV 22c53bd4ff Add primitive debug mode (only implemented on Bungee) 2020-12-31 12:59:31 +01:00
KennyTV c0e2586684 Hotfix dumps
I will use paste.gg in the future, this is only to make it work at all again
2020-12-31 12:28:24 +01:00
KennyTV 2f095f32ca Also replace online and max variable in the hover message 2020-11-20 22:38:10 +01:00
KennyTV e1e4926f83 Properly register main command with permissions (instead of checking for them in the actual command) 2020-10-26 16:55:37 +01:00
KennyTV 55b5bf2714 Update Velocity API usage 2020-10-26 16:47:07 +01:00
KennyTV 5f8f885530 Update language-es.yml (thanks to Vixo_Ulises) 2020-10-26 16:38:38 +01:00
KennyTV fc40b0230d Rename GH build artifact 2020-10-01 09:40:29 +02:00
Nassim 6fb79d7051 Make artifacts work 😎 2020-08-25 14:55:20 +02:00
KennyTV 7bc522c1d3 Upload artifacts 2020-08-25 14:52:15 +02:00
Nassim 8d0d97c220 Create maven.yml 2020-08-25 14:14:56 +02:00
KennyTV e7c8430909 Fix NPE in null pings 2020-08-22 09:48:21 +02:00
KennyTV 1646d4e417 Update Velocity API usage to 1.1.0-SNAPSHOT 🎉 2020-08-21 20:26:39 +02:00
KennyTV f8384f4f99 Add whitelist add arg to manually add offline uuid+name 2020-08-19 09:44:57 +02:00
KennyTV 4fd6ba33ff Fix linebreaks on Bungee in playercount hovermessage 2020-07-30 12:04:05 +02:00
KennyTV 94c146d0e9 Add MaintenanceReloadedEvent, also fire changed event for unregistered proxy servers 2020-07-29 14:17:49 +02:00
dependabot-preview[bot] c624b18b8e Bump junit-jupiter-engine from 5.6.1 to 5.6.2
Bumps [junit-jupiter-engine](https://github.com/junit-team/junit5) from 5.6.1 to 5.6.2.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.6.1...r5.6.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-27 18:39:05 +02:00
KennyTV 18a00f9054 Link to dev branch for Travis builds 2020-07-26 12:15:18 +02:00
KennyTV 9778a900a7 Add 'mt' command alias, add some braces 2020-07-26 11:08:25 +02:00
KennyTV 21fa6a3b7f Formatting fix in changelog 2020-07-14 12:10:34 +02:00
KennyTV c7980cbc86 Missing singleserver kick messages should not throw warnings 2020-06-25 11:28:36 +02:00
KennyTV cdb6715744 Implement new methods for dummyprofile 2020-06-25 09:12:24 +02:00
KennyTV d868f069cc Add translators to the individual language files 2020-06-21 09:26:59 +02:00
Aurélien c58b29a78f Fixes for French translation (#42) 2020-06-21 09:19:16 +02:00
KennyTV 5fb4f06f4c Rename method to get server name of player, cleanup config in test 2020-06-18 15:43:39 +02:00
KennyTV 8a3afdd1a8 Version increase to 3.0.6-SNAPSHOT 2020-06-18 15:26:39 +02:00
KennyTV 36e561c413 Sneak a mysql fix in 2020-06-17 14:09:02 +02:00
KennyTV 4739176e9b Update API jar to 3.0.5 2020-06-17 11:26:32 +02:00
Nassim 9546cc7b74 3.0.5 Release 2020-06-17 10:48:13 +02:00
KennyTV 740051dda5 Prepare for 3.0.5 release 2020-06-17 10:47:20 +02:00
KennyTV e53f4f2518 Config test additions 2020-06-17 09:31:49 +02:00
KennyTV 03390d7be9 Config set cleanup 2020-06-16 17:49:45 +02:00
KennyTV 039c5a3d04 Use precondition in api getter util 2020-06-16 16:39:23 +02:00
KennyTV 4360eb03e3 Wrong nullable annotation 2020-06-16 16:20:18 +02:00
KennyTV 89691e8064 Minor code cleanup to version checking 2020-06-16 16:19:20 +02:00
KennyTV 8f4860ad56 Update changelog, bump Guava provided version
Not that it matters, but want to get rid of the security alert
2020-06-16 09:51:25 +02:00
KennyTV b8b231ce78 Remove config updating from 2.x
See https://github.com/KennyTV/Maintenance/wiki/Updates#updating-from-2x on how to do that manually - virtually noone should be using such old versions anymore
2020-06-10 12:51:25 +02:00
KennyTV fd8b47a9f5 Automatically move files to new dir on updating 2020-06-09 19:25:21 +02:00
KennyTV 10c0b5bab3 Update README 2020-06-01 13:21:21 +02:00
KennyTV cece2b5813 Use higher proxy ping listener priority 2020-05-18 22:12:22 +02:00
KennyTV aa9a686b8a Replace newline variable in language file
Note on why this even exists: Yaml will force save all strings containing line breaks in this rather chunky format:
  key: |-
    First line text
     Second line text.
     ...

This also happens to string lists, making those practically unreadable, as well as confusing for most users in general.
Because of this, I replace %NEWLINE% manually, to spare users from these ugly breaks.
2020-05-15 13:38:41 +02:00
KennyTV f29b38989c Add option to set multiple fallback servers 2020-05-12 20:52:47 +02:00
KennyTV ad9c989213 Add secret language option for server specific kick messages
Closes #38
2020-05-12 20:27:59 +02:00
KennyTV f01e96a32a Implement deep get in config 2020-05-12 19:32:42 +02:00
KennyTV e247f4ef10 Remove platform suffix from plugin identifier 2020-04-22 10:59:27 +02:00
KennyTV b8e0f84d54 Don't hide playercount if custom playercount is disabled 2020-04-21 12:00:23 +02:00
KennyTV 424617c602 Respect custom playercount setting in Spigot ping 2020-04-21 08:36:28 +02:00
KennyTV 21ed266d3d Fix use-ssl option inversion 2020-04-13 09:29:22 +02:00
KennyTV a409ec5d66 Update copyright headers 2020-04-10 23:42:06 +02:00
KennyTV 66cba12fd3 Update Russian language file 2020-04-09 08:59:11 +02:00
KennyTV f6d178d8d1 Add placeholder link to readme 2020-04-06 22:34:04 +02:00
KennyTV d04749c835 Add Italian language file 2020-04-03 12:27:00 +02:00
KennyTV eebbc4d532 Fix config loading with multiline strings, add small tests
Fixes #37
2020-03-30 12:48:48 +02:00
KennyTV 335fe303b5 Throw around some nullable annotations 2020-03-30 11:02:35 +02:00
KennyTV 1c4b5e62a4 Add Chinese language file 2020-03-17 15:02:47 +01:00
KennyTV d41fa5ab24 Version increase to 3.0.5-SNAPSHOT 2020-03-17 11:57:12 +01:00
Nassim 7fd486ef40 3.0.4 Release 2020-03-17 11:01:41 +01:00
KennyTV d0b10f2524 Prepare for 3.0.4 release 2020-03-17 11:00:55 +01:00
KennyTV 865df5e20a Rearrange new language entries 2020-03-16 15:49:09 +01:00
KennyTV 469e8eb57b Fix join notifications with waiting servers enabled 2020-03-16 15:48:27 +01:00
KennyTV 368ac37099 Add waiting-server option for global proxy maintenance
Includes some other, minor fixes
Some proxy modules cleanup
2020-03-16 15:17:09 +01:00
KennyTV 0db4d77c10 Update missing pt messages (by JoaoPinto) 2020-03-16 11:16:46 +01:00
Max Kade ca4c711103 Fix single server timer accepting number as seconds and not minutes (#35) 2020-03-11 14:35:56 +01:00
KennyTV f4a5f288ca Fix singleserver timers broadcasting globally 2020-02-14 21:40:08 +01:00
KennyTV 0a37bfdefe Update bStats metrics 2020-02-12 17:20:37 +01:00
KennyTV 3a30dba011 Add option to disable sql ssl 2020-02-09 12:47:28 +01:00
KennyTV 111a229d48 Minor beauty changes 2020-01-29 15:11:01 +01:00
KennyTV 7e948fbe52 Forgot the return 2019-11-21 09:46:51 +01:00
KennyTV 355aa20244 Add Russian language file (thanks to En_0t_S) 2019-11-21 09:44:23 +01:00
KennyTV 6bc54d1812 Don't throw errors when failing the language update check because of custom langs 2019-11-21 09:41:42 +01:00
KennyTV 0042ce3ccd Version increase to 3.0.4-SNAPSHOT 2019-11-21 09:27:32 +01:00
KennyTV beb0e52371 Forgot to update the date in the changelog 2019-09-17 09:05:53 +02:00
Nassim 4774ec2f2a 3.0.3 Release 2019-09-17 09:02:27 +02:00
KennyTV 34115f443e Version increase to 3.0.3 2019-09-17 08:29:23 +02:00
KennyTV c8f0c1699e Update changelog, fix small oversight in the Bungee serverconnect 2019-09-13 10:30:53 +02:00
KennyTV f22be77023 Fix playercountmessage on Paper servers with Via 2019-09-09 08:35:53 +02:00
KennyTV 730a8dbeea Remove some old code 2019-08-24 18:55:30 +02:00
KennyTV 0548e0c447 Replace some streams with loops.. because why not
Not really that much of an improvement, but gotta strike those micro optimizations 🤷
2019-08-18 10:18:58 +02:00
KennyTV da0a757c5e Revert "Fix potential config deserialization error"
This reverts commit ac19bac1
2019-08-13 22:33:31 +02:00
KennyTV ac19bac11c Fix potential config deserialization error 2019-08-13 22:21:30 +02:00
KennyTV 1de926bb28 Minor pom changes 2019-08-13 22:21:11 +02:00
KennyTV 94308cde7c Fix some redundant config comment checks 2019-07-26 13:20:27 +02:00
KennyTV d863c709e1 Update bStats metrics 2019-07-26 12:29:34 +02:00
KennyTV 741914283a Minor config optimizations and cleanup 2019-07-22 09:28:53 +02:00
KennyTV 64902d90ff Language autoupdater, fix updating with broken texts 2019-07-21 15:49:10 +02:00
KennyTV d3b4c7c87b Add warning with PS 2019-07-20 09:58:00 +02:00
KennyTV 390b65a70e Add warning with PS 2019-07-20 09:49:00 +02:00
KennyTV 7cff908aae Switch to ProtocolLib/Spigot ping listener if PS is installed 2019-07-20 09:46:28 +02:00
KennyTV d1f049c3e5 Add help page header to language file 2019-06-28 21:43:27 +02:00
Nassim 8d552dbe33 Remove a space in language-es.yml 2019-06-27 10:34:36 +02:00
KennyTV d3a933d21d Add bypass permission for specific proxied servers 2019-06-27 10:05:57 +02:00
KennyTV a4d87dabf5 Update changelog 2019-06-09 09:53:04 +02:00
KennyTV c3b579e86c Update Spanish language (thanks to Vixo_Ulises) 2019-06-09 09:51:04 +02:00
KennyTV b75d2337df Update French language (thanks to Zendrique) 2019-05-31 21:26:58 +02:00
KennyTV b3e83c5c2e Language changes 2019-05-31 16:26:16 +02:00
KennyTV b6f447aded Update travis.yml 2019-05-31 15:45:35 +02:00
KennyTV 9febdfc140 Update travis.yml 2019-05-31 15:38:06 +02:00
KennyTV 90bc30d701 I'm a dumbo 2019-05-31 15:31:10 +02:00
KennyTV 843ba4ac86 Add help messages to language files 2019-05-31 15:30:03 +02:00
KennyTV 032fd7d582 Fix double messages in some server connections 2019-05-24 09:14:51 +02:00
KennyTV 9a0f680177 Kick connecting players before the connection succeeded, fix double join-notification (Bungee) 2019-05-23 22:18:05 +02:00
KennyTV 415d5f3807 Update config version 2019-05-20 15:28:06 +02:00
KennyTV 33c96de5fb Add option to not kick online players 2019-05-18 17:23:56 +02:00
KennyTV d141b40190 Version increase to 3.0.3-SNAPSHOT 2019-05-18 17:16:37 +02:00
KennyTV 77e1444dba 3.0.2 Release 2019-05-17 09:35:34 +02:00
KennyTV 915b43d897 👀 2019-05-17 09:35:14 +02:00
KennyTV adc06e3486 Update changelog 2019-05-17 09:31:17 +02:00
KennyTV cc7f5c2d11 Version increase to 3.0.2 2019-05-17 09:25:57 +02:00
KennyTV 0bb54ffc5d Finish timerspecific pingmessages 2019-05-17 09:21:35 +02:00
KennyTV 15ee2e6074 Update changelog, resort some config entries 2019-05-14 13:48:28 +02:00
KennyTV 89abab36f8 Timerspecific pingmessages 2019-05-14 09:07:23 +02:00
KennyTV e0bb1336b0 ‍Make setmotd command also set timerspecific messages 2019-05-13 22:53:04 +02:00
KennyTV 888ffd301a 🤦‍ 2019-05-13 15:30:40 +02:00
KennyTV 3a55dd3280 Make motd command display timerspecific ones 2019-05-13 15:30:00 +02:00
KennyTV 61c47ba2fa WIP: Timerspecific pingmessages 2019-05-13 11:02:13 +02:00
KennyTV b97e69a71f Make dumps prettier 2019-05-09 22:30:18 +02:00
KennyTV 75c940d089 Fix Sponge 8.0.0 compatibility 2019-05-09 21:53:30 +02:00
KennyTV 849fa2a720 Update to latest Velocity text api 2019-05-07 09:09:58 +02:00
KennyTV 7e249faa99 Update README.md 2019-04-27 15:34:07 +02:00
KennyTV c8272b39d5 Fix Velocity autoupdater 2019-04-17 15:38:51 +02:00
KennyTV b3c561ae26 Version increase to 3.0.2-SNAPSHOT 2019-04-17 15:38:33 +02:00
KennyTV af24c5a331 Update api, changelog and readme for latest release 2019-04-17 15:24:51 +02:00
KennyTV 4cc162f00d Merge pull request #29 from KennyTV/dev
3.0.1 Release
2019-04-17 14:38:55 +02:00
KennyTV 02610fd904 Version increase to 3.0.1 2019-04-17 14:36:56 +02:00
KennyTV bccd1bb936 Remove interface check 2019-04-17 14:36:47 +02:00
KennyTV c08dd5d430 Set group id to eu.kennytv.maintenance 2019-04-15 10:54:16 +02:00
KennyTV 1104a50882 Fix another potential error on startup 2019-04-14 13:07:01 +02:00
KennyTV 56898d7b40 Database sync fixes, adjustments to endtimer saving 2019-04-05 14:05:01 +02:00
KennyTV 4be31a6dd4 Update README 2019-04-05 14:04:45 +02:00
KennyTV 190a063d49 Add config updater + endtimer saving after restart 2019-04-03 14:22:06 +02:00
KennyTV 6e4591d45b Fix error printing in some cases, close hikari source on disable(/reload) 2019-04-03 11:15:30 +02:00
KennyTV 86c556e841 Hackily fix slf4j relocation and shorten jar sizes 2019-03-19 22:35:13 +01:00
KennyTV 404e14ee94 Revert "Only compile SnakeYaml in universal and Velocity file"
This reverts commit b8c0e3a7
2019-03-19 18:07:18 +01:00
KennyTV b8c0e3a799 Only compile SnakeYaml in universal and Velocity file 2019-03-19 18:04:05 +01:00
KennyTV 10d798acd4 Make ServerInfoPacketListener extend PacketAdapter instead of creating anonymous class 2019-03-19 17:04:08 +01:00
KennyTV be057f4b3b Don't register listener twice 2019-03-13 17:17:31 +01:00
KennyTV eea7a595c9 Add Ore url to plugin info 2019-03-13 10:21:29 +01:00
KennyTV bf4bf79b23 Readd update checking on Sponge, still disallow execution of update 2019-03-13 10:04:16 +01:00
KennyTV 686535228e Typo 👀 2019-03-11 13:24:33 +01:00
KennyTV 8b645b6f79 Fix Paper pinglistener and remove old code 2019-03-11 13:22:15 +01:00
KennyTV 4d97293a8c Rename dump variable 2019-03-11 13:00:43 +01:00
KennyTV c746a83f5f Use PaperServerListPingEvent if applicable 2019-03-11 12:48:10 +01:00
KennyTV eb7e6e3f0b Fix exception on ping that does not come from status packet 2019-03-10 19:08:08 +01:00
KennyTV f5ce41853f nooooo 2019-03-08 21:29:28 +01:00
KennyTV e67cde591c Try to please the beautiful people over at Ore (Sponge), attempt no 2 2019-03-08 21:28:35 +01:00
KennyTV 39682635c6 Try to please the beautiful people over at Ore (Sponge) 2019-03-08 21:18:21 +01:00
KennyTV efee532742 Make endtimer display format adjustable 2019-03-05 16:55:56 +01:00
KennyTV 0aee3a8fd6 Remove bStats from Sponge module
(Their beautiful repo is down and I don't really need it on Sponge anyways 🤔)
2019-02-21 17:22:29 +01:00
KennyTV f79b6caccb Minor maintenance event changes 2019-02-21 16:43:13 +01:00
KennyTV 73fd80b456 Some language changes 2019-02-21 15:35:52 +01:00
KennyTV ad1a7eb420 Make createFile method public 2019-02-19 17:30:58 +01:00
KennyTV bfa9b52497 Add api method to get a list of maintenance servers 2019-02-19 13:25:13 +01:00
KennyTV ff4b5b0d2e Custom maintenance events 2019-02-19 13:08:38 +01:00
KennyTV b8e73062fa Some language changes 2019-02-19 11:28:24 +01:00
KennyTV 863a9b3beb Version increase to 3.0.1-SNAPSHOT 2019-02-19 00:16:24 +01:00
KennyTV fe64936ddf Sneak Spanish language in 👀 2019-02-17 10:16:36 +01:00
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
186 changed files with 10626 additions and 3322 deletions

No files matched your search

+239
View File
@@ -0,0 +1,239 @@
# 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.6 - February 17th 2021
### Changed
* Updated the Velocity version to be compatible with Velocity 1.1.0 (use Maintenance 3.0.5 if you use an older version of Velocity)
* Added `maintenance schedule <minutes> <duration> command`
* This starts a timer for maintenance to be enabled, after which another timer will be started to disable it again (in contrast to `starttimer` and `endtimer`, which each only do one of)
* On proxies, you can use `maintenance schedule [server] <minutes> <duration> command` to schedule maintenance on a proxied server
* Added command alias `mt` for the Maintenance command
* Added secret argument to the whitelist add command: You can use `maintenance add <uuid> <name>` to add offline entries per command
* The maintenance's base command is now properly registered with a permission on each platform, so that it is excluded from tabcomplection to unauthorized players
* Some improvements to the French language file (thanks to @Aurelien30000)
* API addition: Added MaintenanceReloadedEvent
* If you are using the MaintenancePlaceholderAddon, you need to [update it to 1.0.4](https://github.com/KennyTV/MaintenanceAddon/releases)
### Fixed
* Fixed not setting custom singleserver kickmessages throwing warnings
* Bungee: Fixed linebreaks in the playercount hovermessage for 1.16+ clients
---
## 3.0.5 - June 17th 2020
### Changed
* The plugin identifiers are now `Maintenance` instead of the previous `MaintenanceSpigot` and `MaintenanceBungee`,
and `maintenance` instead of `maintenancesponge` and `maintenancevelocity`
* The plugin directory will automatically be renamed accordingly when starting the server
* If you are using the MaintenancePlaceholderAddon, you need to [update it to 1.0.3](https://github.com/KennyTV/MaintenanceAddon/releases)
* Bungee/Velocity: The `fallback` field can now also be set as a list to define multiple fallback servers
* Bungee/Velocity: Added language fields to choose custom kickmessages for individual proxied servers
* See [**HERE**](https://github.com/KennyTV/Maintenance/wiki/Configuration#language-file) for an example setting
* Added Chinese language file (thanks to Spigot user yeban)
* Added Italian language file (thanks to @TheViperShow)
* Updated Russian language file (thanks to Spigot user En_0t_S)
* Removed automated config migration from 2.x->3.0
* See [**HERE**](https://github.com/KennyTV/Maintenance/wiki/Updates#updating-from-2x) on how to do that manually - virtually noone should be using such old versions anymore
### Fixed
* Fixed the `use-ssl` option being inverted
* Fixed disabling the playercount-message still hiding online/max players
* Fixed config parsing with multi line strings
* Bungee: Fixed compatibility with other motd changing plugins using the 'HIGHEST' ping listener priority
---
## 3.0.4 - March 17th 2020
### Changed
* Bungee/Velocity: Added config option `waiting-server` to send players to a waiting server when global maintenance is enabled (instead of kicking them)
* Bungee/Velocity: Added config option `use-ssl` in the `mysql` section to disable SSL connections
* Added Russian language file (thanks to Spigot user En_0t_S)
* Updated missing translations in Portuguese language file (thanks to Spigot user JoaoPinto)
* Updated bStats metrics
### Fixed
* Fixed singleserver timers using input as seconds instead of minutes (by mxs42)
* Fixed singleserver timers broadcasting globally
* Fixed language updating with an unknown/self-translated language file
* Fixed Velocity server autocompletion in the maintenance command
---
## 3.0.3 - September 17th 2019
### Changed
* Bungee/Velocity: Added `maintenance.singleserver.bypass.<server>` permission to give individual bypasses for proxied servers (`maintenance.bypass` will still bypass everything as the super-perm)
* Added the messages of the help command into the language files
* Added config option `kick-online-players` to disable the kicks when maintenance is enabled (new connections will still be blocked)... not sure why you'd want that, but you can :p
* The language file will now be automatically updated as well, so no need to delete and recreate it anymore, yay!
* Updated missing and new translations in French language file (thanks to Spigot user Zendrique)
* Updated missing and new translations in Spanish language file (thanks to Spigot user Vixo_Ulises)
### Fixed
* Bungee/Velocity: Fixed the join-notifications being sent twice if both global and server maintenance are enabled, as well as when just a server has maintenance in some cases
* Bungee: Fixed players being kicked *after* the initial connection and thus triggering a join and leave message before being kicked
* Bungee: Fixed the kickmessage not being displayed in some cases
* Paper: Fixed the playercount message not being displayed on Paper servers with ViaVersion
* Paper: Fixed the motd not being changed at all on Paper servers with ProtocolSupport (-> ProtocolLib listener used, since ProtocolSupport does not fire Paper's ping event)
* Fixed the config autoupdater when the config contained strings broken over multiple lines
---
## 3.0.2 - May 17th 2019
### Changed
* Added config option `timerspecific-pingmessages` to have specific pingmessages shown when endtimers are run
* You can also set them ingame by using `/maintenance setmotd timer <index> ...` instead of `/maintenance setmotd <index> ...`, along with `/maintenance removemotd timer <index>` and `/maintenance motd timer`
* Made dumps a little prettier
* Support Sponge 8.0.0-SNAPSHOT
* Support latest text/Velocity (now only supports Velocity builds from May 7th upwards)
---
## 3.0.1 - April 17th 2019
### Changed
* Created an addon to have PlaceholderAPI placeholders on Spigot when running the Maintenance plugin on Bungee (see [**here**](https://github.com/KennyTV/Maintenance/wiki/MaintenanceAddon))
* Spigot version: If running on Paper 1.12.2 or higher, ProtocolLib will not be needed anymore
* The universal jar now only includes Bungee and Spigot (whereas before Sponge and Velocity as well) and has been further minimized in size
* To use the plugin on the other platforms, use the `MaintenanceSponge.jar` or `MaintenanceVelocity.jar` respectively
* Added config option `continue-endtimer-after-restart` to have endtimers continued, even if the server restarts during its runtime
* Added custom eventsystem to the API
* Removed bStats metrics from Sponge module
### Fixed
* Actually fixed compatibility to other plugins using the same MySQL library (such as LuckPerms) in the Bungee version
* Fixed an issue with executing the maintenance change with MySQL enabled on connected proxies
* Fixed an occasional error on pings of non clients in the Spigot version
* Fixed 1.13 clients on sub 1.13 servers not showing the playercountmessage in the Spigot version
* Minor fixes/changes to Spanish and Portuguese language files
---
## 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**
+35
View File
@@ -0,0 +1,35 @@
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2.1.1
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-maven-
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Upload a Build Artifact
uses: actions/upload-artifact@v2.1.4
with:
name: MaintenanceFiles
path: |
**/Maintenance.jar
**/MaintenanceSpigot.jar
**/MaintenanceBungee.jar
**/MaintenanceVelocity.jar
**/MaintenanceSponge.jar
+3 -2
View File
@@ -1,5 +1,4 @@
.metadata
dependencies/
bin/
tmp/
*.tmp
@@ -91,4 +90,6 @@ $RECYCLE.BIN/
*.msi
*.msm
*.msp
*.lnk
*.lnk
!MaintenanceAPI.jar
**/src/test/resources/
+7
View File
@@ -0,0 +1,7 @@
language: java
jdk:
- oraclejdk8
dist: trusty
cache:
directories:
- '$HOME/.m2/repository'
-13
View File
@@ -1,13 +0,0 @@
## Issue
Include here how the problem occured and how it's reproduceable.
If present, also paste the entire error message from the console, preferably via a https://hastebin.com/ link.
## Necessary server information
**Running on**: <BungeeCord/Bukkit>
**Maintenance version**: <>
## Other information
**Other motd changing plugins**: <>
**ProtocolLib version**: <>
Binary file not shown.
@@ -1,40 +0,0 @@
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();
/**
* @return {@link ISettings} for options regarding configuration files
*/
ISettings getSettings();
}
@@ -1,15 +0,0 @@
package eu.kennytv.maintenance.api;
/**
* @author KennyTV
* @since 2.2.2
*/
public interface IMaintenanceBase {
/**
* Returns API instance of IMaintenance.
*
* @return {@link IMaintenance} instance
*/
IMaintenance getApi();
}
@@ -1,30 +0,0 @@
package eu.kennytv.maintenance.api.bungee;
import eu.kennytv.maintenance.api.IMaintenance;
import net.md_5.bungee.api.config.ServerInfo;
/**
* @author KennyTV
* @since 2.5
*/
public interface IMaintenanceBungee 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 maintenance true to enable, false to disable maintenance mode
*/
boolean setMaintenanceToServer(ServerInfo server, boolean maintenance);
/**
* @return true if maintenance is currently enabled on the proxied server
*/
boolean isMaintenance(ServerInfo server);
/**
* @return true if a start- or endtimer task is currently running regarding the proxied server
*/
boolean isServerTaskRunning(ServerInfo server);
}
@@ -1,29 +0,0 @@
package eu.kennytv.maintenance.api.bungee;
import eu.kennytv.maintenance.api.IMaintenanceBase;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
/**
* Utility class to get the {@link IMaintenanceBungee} 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 IMaintenance.
*
* @return {@link IMaintenanceBungee} instance
*/
public static IMaintenanceBungee getAPI() {
final Plugin maintenance = ProxyServer.getInstance().getPluginManager().getPlugin("MaintenanceBungee");
if (maintenance == null)
ProxyServer.getInstance().getLogger().warning("Could not get instance of MaintenanceBungee!");
return (IMaintenanceBungee) ((IMaintenanceBase) maintenance).getApi();
}
}
@@ -1,30 +0,0 @@
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 IMaintenance.
*
* @return {@link IMaintenance} instance
*/
public static IMaintenance getAPI() {
final Plugin maintenance = Bukkit.getPluginManager().getPlugin("MaintenanceSpigot");
if (maintenance == null)
Bukkit.getLogger().warning("Could not get instance of MaintenanceSpigot!");
return ((IMaintenanceBase) maintenance).getApi();
}
}
-48
View File
@@ -1,48 +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>
<artifactId>maintenance-base</artifactId>
<groupId>eu.kennytv</groupId>
<version>2.5.2</version>
</parent>
<artifactId>maintenance-bungee</artifactId>
<name>MaintenanceBungee</name>
<repositories>
<repository>
<id>bungeecord-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-core</artifactId>
<version>${parent.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.13-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.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -1,25 +0,0 @@
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();
}
}
@@ -1,194 +0,0 @@
package eu.kennytv.maintenance.bungee;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.ISettings;
import eu.kennytv.maintenance.api.bungee.IMaintenanceBungee;
import eu.kennytv.maintenance.api.bungee.MaintenanceBungeeAPI;
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.ServerConnectListener;
import eu.kennytv.maintenance.bungee.metrics.MetricsLite;
import eu.kennytv.maintenance.bungee.runnable.SingleMaintenanceRunnable;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
import eu.kennytv.maintenance.core.util.ServerType;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
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.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
/**
* @author KennyTV
* @since 1.0
*/
public final class MaintenanceBungeePlugin extends MaintenanceModePlugin implements IMaintenanceBungee {
private final MaintenanceBungeeBase plugin;
private final SettingsBungee settings;
private final Map<String, Integer> serverTaskIds = new HashMap<>();
MaintenanceBungeePlugin(final MaintenanceBungeeBase plugin) {
super("§8[§eMaintenanceBungee§8] ", plugin.getDescription().getVersion(), ServerType.BUNGEE);
this.plugin = plugin;
plugin.getLogger().info("Plugin by KennyTV");
plugin.getLogger().info(getUpdateMessage());
settings = new SettingsBungee(this, plugin);
final PluginManager pm = getProxy().getPluginManager();
pm.registerListener(plugin, new PostLoginListener(this, settings));
pm.registerListener(plugin, new ServerConnectListener(this, settings));
final MaintenanceBungeeCommand maintenanceCommand = new MaintenanceBungeeCommand(this, settings);
pm.registerCommand(plugin, new MaintenanceBungeeCommandBase(maintenanceCommand));
new MetricsLite(plugin);
// ServerListPlus integration
final Plugin serverListPlus = pm.getPlugin("ServerListPlus");
if (serverListPlus != null) {
serverListPlusHook = new ServerListPlusHook(((ServerListPlusPlugin) serverListPlus).getCore());
serverListPlusHook.setEnabled(!settings.isMaintenance());
plugin.getLogger().info("Enabled ServerListPlus integration!");
}
}
@Override
public void setMaintenance(final boolean maintenance) {
if (settings.getMySQL() != null) {
settings.setMaintenanceToSQL(maintenance);
} else {
settings.setMaintenance(maintenance);
settings.setToConfig("enable-maintenance-mode", maintenance);
settings.saveConfig();
}
serverActions(maintenance);
if (isTaskRunning())
cancelTask();
}
void serverActions(final boolean maintenance) {
if (serverListPlusHook != null)
serverListPlusHook.setEnabled(!maintenance);
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.getMessage("maintenanceActivated"));
} else
getProxy().broadcast(settings.getMessage("maintenanceDeactivated"));
}
@Override
public boolean isMaintenance(final ServerInfo server) {
return settings.isMaintenance(server);
}
@Override
public boolean setMaintenanceToServer(final ServerInfo server, final boolean maintenance) {
if (maintenance) {
if (!settings.addMaintenanceServer(server.getName())) return false;
} else {
if (!settings.removeMaintenanceServer(server.getName())) return false;
}
serverActions(server, maintenance);
cancelSingleTask(server);
return true;
}
void serverActions(final ServerInfo server, final boolean maintenance) {
if (maintenance) {
final ServerInfo fallback = getProxy().getServerInfo(settings.getFallbackServer());
if (fallback == null && !server.getPlayers().isEmpty())
plugin.getLogger().warning("The fallback server set in the SpigotServers.yml could not be found! Instead kicking players from that server off the network!");
else if (fallback.equals(server))
plugin.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!");
server.getPlayers().forEach(p -> {
if (!p.hasPermission("maintenance.bypass") && !settings.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
if (fallback != null && fallback.canAccess(p)) {
p.sendMessage(settings.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName()));
p.connect(fallback);
} else
p.disconnect(settings.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", server.getName()));
} else {
p.sendMessage(settings.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName()));
}
});
} else
server.getPlayers().forEach(p -> p.sendMessage(settings.getMessage("singleMaintenanceDeactivated").replace("%SERVER%", server.getName())));
}
@Override
public boolean isServerTaskRunning(final ServerInfo server) {
return serverTaskIds.containsKey(server.getName());
}
@Override
protected int startMaintenanceRunnable(final Runnable runnable) {
return getProxy().getScheduler().schedule(plugin, runnable, 0, 1, TimeUnit.SECONDS).getId();
}
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final ServerInfo server, final int minutes, final boolean enable) {
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, (Settings) getSettings(), minutes, enable, server);
serverTaskIds.put(server.getName(), getProxy().getScheduler().schedule(plugin, runnable, 0, 1, TimeUnit.SECONDS).getId());
return runnable;
}
@Override
public void async(final Runnable runnable) {
getProxy().getScheduler().runAsync(plugin, runnable);
}
@Override
public void cancelTask() {
getProxy().getScheduler().cancel(taskId);
runnable = null;
taskId = 0;
}
public void cancelSingleTask(final ServerInfo server) {
final Integer task = serverTaskIds.remove(server.getName());
if (task != null)
getProxy().getScheduler().cancel(task);
}
@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();
}
@Override
public Logger getLogger() {
return plugin.getLogger();
}
}
@@ -1,358 +0,0 @@
package eu.kennytv.maintenance.bungee;
import eu.kennytv.maintenance.bungee.listener.ProxyPingListener;
import eu.kennytv.maintenance.bungee.mysql.MySQL;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.listener.IPingListener;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.plugin.PluginManager;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.YamlConfiguration;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.sql.SQLException;
import java.util.*;
public final class SettingsBungee extends Settings {
private final String mySQLTable;
private final String serverTable;
private final String maintenanceQuery;
private final String serverQuery;
private final MySQL mySQL;
private final MaintenanceBungeePlugin maintenancePlugin;
private final MaintenanceBungeeBase plugin;
private final IPingListener pingListener;
private Set<String> maintenanceServers;
private Configuration config;
private Configuration language;
private Configuration whitelist;
private Configuration spigotServers;
private String fallbackServer;
private long millisecondsToCheck;
private long lastMySQLCheck;
private long lastServerCheck;
SettingsBungee(final MaintenanceBungeePlugin maintenancePlugin, final MaintenanceBungeeBase plugin) {
super(maintenancePlugin);
this.maintenancePlugin = maintenancePlugin;
this.plugin = plugin;
final PluginManager pm = plugin.getProxy().getPluginManager();
final ProxyPingListener listener = new ProxyPingListener(plugin, this);
pm.registerListener(plugin, listener);
pingListener = listener;
if (!plugin.getDataFolder().exists())
plugin.getDataFolder().mkdirs();
createFile("bungee-config.yml");
createFile("WhitelistedPlayers.yml");
createFile("SpigotServers.yml");
reloadConfigs();
final Configuration mySQLSection = config.getSection("mysql");
if (mySQLSection.getBoolean("use-mysql", false)) {
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"));
// Varchar as the value regarding the possibility of saving stuff like the motd as well in future updates
mySQLTable = mySQLSection.getString("table", "maintenance_settings");
serverTable = mySQLSection.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;
maintenance = loadMaintenance();
plugin.getLogger().info("Done!");
} else {
mySQL = null;
mySQLTable = null;
maintenanceQuery = null;
serverTable = null;
serverQuery = null;
}
}
private void createFile(final String name) {
final File file = new File(plugin.getDataFolder(), name);
if (!file.exists()) {
try (final InputStream in = plugin.getResourceAsStream(name)) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
throw new RuntimeException("Unable to create " + name + " file for MaintenanceBungee", e);
}
}
}
@Override
public boolean updateExtraConfig() {
// 2.3.1 mysql.update-interval
if (!configContains("mysql.update-interval")) {
setToConfig("mysql.update-interval", 15);
return true;
}
return false;
}
@Override
public void reloadConfigs() {
try {
config = YamlConfiguration.getProvider(YamlConfiguration.class)
.load(new InputStreamReader(new FileInputStream(new File(plugin.getDataFolder(), "bungee-config.yml")), StandardCharsets.UTF_8));
whitelist = YamlConfiguration.getProvider(YamlConfiguration.class).load(new File(plugin.getDataFolder(), "WhitelistedPlayers.yml"));
spigotServers = YamlConfiguration.getProvider(YamlConfiguration.class).load(new File(plugin.getDataFolder(), "SpigotServers.yml"));
} catch (final IOException e) {
throw new RuntimeException("Unable to load Maintenance files!", e);
}
loadSettings();
createAndLoadLanguageFile();
}
private void createAndLoadLanguageFile() {
final File file = new File(plugin.getDataFolder(), "language-" + getLanguage() + ".yml");
if (!file.exists()) {
try (final InputStream in = plugin.getResourceAsStream("language-" + getLanguage() + ".yml")) {
Files.copy(in, file.toPath());
} catch (final IOException | NullPointerException e) {
plugin.getLogger().warning("Unable to provide language " + getLanguage());
if (!languageName.equals("en")) {
plugin.getLogger().warning("Falling back to default language: en");
languageName = "en";
createAndLoadLanguageFile();
return;
}
}
}
try {
language = YamlConfiguration.getProvider(YamlConfiguration.class)
.load(new InputStreamReader(new FileInputStream(new File(plugin.getDataFolder(), "language-" + getLanguage() + ".yml")), StandardCharsets.UTF_8));
} catch (final IOException e) {
throw new RuntimeException("Unable to load Maintenance language file!", e);
}
}
@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), StandardCharsets.UTF_8));
} catch (final IOException e) {
throw new RuntimeException("Unable to save bungee-config.yml!", e);
}
}
@Override
public void saveWhitelistedPlayers() {
saveFile(whitelist, "WhitelistedPlayers.yml");
}
public void saveSpigotServers() {
saveFile(spigotServers, "SpigotServers.yml");
}
private void saveFile(final Configuration config, final String name) {
final File file = new File(plugin.getDataFolder(), name);
try {
YamlConfiguration.getProvider(YamlConfiguration.class).save(config, file);
} catch (final IOException e) {
throw new RuntimeException("Unable to save " + name + "!", e);
}
}
@Override
public void loadExtraSettings() {
whitelistedPlayers.clear();
whitelist.getKeys().forEach(key -> whitelistedPlayers.put(UUID.fromString(key), whitelist.getString(key)));
fallbackServer = spigotServers.getString("fallback", "hub");
if (mySQL != null) {
final long configValue = config.getInt("mysql.update-interval");
millisecondsToCheck = configValue > 0 ? configValue * 1000 : -1;
lastMySQLCheck = 0;
lastServerCheck = 0;
maintenanceServers = loadMaintenanceServersFromSQL();
} else {
final List<String> list = spigotServers.getStringList("maintenance-on");
maintenanceServers = list == null ? new HashSet<>() : new HashSet<>(list);
}
}
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;
}
@Override
public void setWhitelist(final String uuid, final String s) {
whitelist.set(uuid, s);
}
@Override
public String getConfigString(final String path) {
final String s = config.getString(path);
if (s == null) {
plugin.getLogger().warning("The config is missing the following string: " + path);
return "null";
}
return s;
}
@Override
public String getMessage(final String path) {
final String s = language.getString(path);
if (s == null) {
plugin.getLogger().warning("The language file is missing the following string: " + path);
return "null";
}
return ChatColor.translateAlternateColorCodes('&', s);
}
@Override
public boolean getConfigBoolean(final String path) {
return config.getBoolean(path);
}
@Override
public List<Integer> getConfigIntList(final String path) {
return config.getIntList(path);
}
@Override
public List<String> getConfigList(final String path) {
return config.getStringList(path);
}
@Override
public void setToConfig(final String path, final Object var) {
config.set(path, var);
}
@Override
public boolean configContains(final String path) {
return config.contains(path);
}
@Override
public String getColoredString(final String message) {
return ChatColor.translateAlternateColorCodes('&', message);
}
@Override
public boolean isMaintenance() {
if (mySQL != null && (millisecondsToCheck == -1 || System.currentTimeMillis() - lastMySQLCheck > millisecondsToCheck)) {
final boolean databaseValue = loadMaintenance();
if (databaseValue != maintenance) {
maintenancePlugin.serverActions(maintenance);
maintenance = databaseValue;
}
if (millisecondsToCheck != -1)
lastMySQLCheck = System.currentTimeMillis();
}
return maintenance;
}
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];
}
public boolean isMaintenance(final ServerInfo server) {
if (mySQL != null && (millisecondsToCheck == -1 || System.currentTimeMillis() - lastServerCheck > millisecondsToCheck)) {
final Set<String> databaseValue = loadMaintenanceServersFromSQL();
if (!databaseValue.equals(maintenanceServers)) {
maintenancePlugin.serverActions(server, maintenance);
maintenanceServers = databaseValue;
}
if (millisecondsToCheck != -1)
lastServerCheck = System.currentTimeMillis();
}
return maintenanceServers.contains(server.getName());
}
@Override
public boolean reloadMaintenanceIcon() {
return pingListener.loadIcon();
}
void setMaintenanceToSQL(final boolean maintenance) {
maintenancePlugin.async(() -> {
final String s = String.valueOf(maintenance);
mySQL.executeUpdate("INSERT INTO " + mySQLTable + " (setting, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = ?", "maintenance", s, s);
if (millisecondsToCheck != -1)
lastMySQLCheck = System.currentTimeMillis();
});
this.maintenance = maintenance;
}
MySQL getMySQL() {
return mySQL;
}
boolean addMaintenanceServer(final String server) {
if (mySQL != null) {
maintenanceServers = loadMaintenanceServersFromSQL();
if (!maintenanceServers.add(server)) return false;
maintenancePlugin.async(() -> mySQL.executeUpdate("INSERT INTO " + serverTable + " (server) VALUES (?)", server));
if (millisecondsToCheck != -1)
lastServerCheck = System.currentTimeMillis();
} else {
if (!maintenanceServers.add(server)) return false;
saveServersToConfig();
}
return true;
}
boolean removeMaintenanceServer(final String server) {
if (mySQL != null) {
maintenanceServers = loadMaintenanceServersFromSQL();
if (!maintenanceServers.remove(server)) return false;
maintenancePlugin.async(() -> mySQL.executeUpdate("DELETE FROM " + serverTable + " WHERE server = ?", server));
if (millisecondsToCheck != -1)
lastServerCheck = System.currentTimeMillis();
} else {
if (!maintenanceServers.remove(server)) return false;
saveServersToConfig();
}
return true;
}
public void saveServersToConfig() {
spigotServers.set("maintenance-on", new ArrayList<>(maintenanceServers));
saveSpigotServers();
}
public Set<String> getMaintenanceServers() {
return maintenanceServers;
}
public String getFallbackServer() {
return fallbackServer;
}
}
@@ -1,157 +0,0 @@
package eu.kennytv.maintenance.bungee.command;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.bungee.SettingsBungee;
import eu.kennytv.maintenance.bungee.util.ProxiedSenderInfo;
import eu.kennytv.maintenance.core.command.MaintenanceCommand;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
import eu.kennytv.maintenance.core.util.SenderInfo;
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.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public final class MaintenanceBungeeCommand extends MaintenanceCommand {
private final MaintenanceBungeePlugin plugin;
private final SettingsBungee settingsBungee;
public MaintenanceBungeeCommand(final MaintenanceBungeePlugin plugin, final SettingsBungee settings) {
super(plugin, settings, "MaintenanceBungee");
this.plugin = plugin;
settingsBungee = settings;
}
@Override
protected void addPlayerToWhitelist(final SenderInfo sender, final String name) {
final ProxiedPlayer selected = plugin.getProxy().getPlayer(name);
if (selected == null) {
sender.sendMessage(settings.getMessage("playerNotOnline"));
return;
}
if (settings.addWhitelistedPlayer(selected.getUniqueId(), selected.getName()))
sender.sendMessage(settings.getMessage("whitelistAdded").replace("%PLAYER%", selected.getName()));
else
sender.sendMessage(settings.getMessage("whitelistAlreadyAdded").replace("%PLAYER%", selected.getName()));
}
@Override
protected void removePlayerFromWhitelist(final SenderInfo sender, final String name) {
final ProxiedPlayer selected = plugin.getProxy().getPlayer(name);
if (selected == null) {
if (settings.removeWhitelistedPlayer(name))
sender.sendMessage(settings.getMessage("whitelistRemoved").replace("%PLAYER%", name));
else
sender.sendMessage(settings.getMessage("whitelistNotFound"));
return;
}
if (settings.removeWhitelistedPlayer(selected.getUniqueId()))
sender.sendMessage(settings.getMessage("whitelistRemoved").replace("%PLAYER%", selected.getName()));
else
sender.sendMessage(settings.getMessage("whitelistNotFound"));
}
@Override
protected 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 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/maintenance forceupdate");
((ProxiedSenderInfo) sender).sendMessage(tc);
} else
sender.sendMessage(plugin.getPrefix() + "§aYou already have the latest version of the plugin!");
}
@Override
protected void handleToggleServerCommand(final SenderInfo sender, final String[] args) {
final ServerInfo server = plugin.getProxy().getServerInfo(args[1]);
if (server == null) {
sender.sendMessage(settings.getMessage("serverNotFound"));
return;
}
final boolean maintenance = args[0].equalsIgnoreCase("on");
if (plugin.setMaintenanceToServer(server, maintenance)) {
if (!sender.isPlayer() || !plugin.getProxy().getPlayer(sender.getUuid()).getServer().getInfo().equals(server))
sender.sendMessage(settings.getMessage(maintenance ? "singleMaintenanceActivated" : "singleMaintenanceDeactivated").replace("%SERVER%", server.getName()));
} else
sender.sendMessage(settings.getMessage(maintenance ? "singleServerAlreadyEnabled" : "singleServerAlreadyDisabled").replace("%SERVER%", server.getName()));
}
@Override
protected void handleTimerServerCommands(final SenderInfo sender, final String[] args) {
if (args[0].equalsIgnoreCase("endtimer")) {
if (checkPermission(sender, "servertimer")) return;
if (checkTimerArgs(sender, args[2], "singleEndtimerUsage")) return;
final ServerInfo server = checkSingleTimerArgs(sender, args);
if (server == null) return;
if (!plugin.isMaintenance(server)) {
sender.sendMessage(settings.getMessage("singleServerAlreadyDisabled").replace("%SERVER%", server.getName()));
return;
}
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, Integer.parseInt(args[2]), false);
sender.sendMessage(settings.getMessage("endtimerStarted").replace("%TIME%", runnable.getTime()));
} else if (args[0].equalsIgnoreCase("starttimer")) {
if (checkPermission(sender, "servertimer")) return;
if (checkTimerArgs(sender, args[2], "singleStarttimerUsage")) return;
final ServerInfo server = checkSingleTimerArgs(sender, args);
if (server == null) return;
if (plugin.isMaintenance(server)) {
sender.sendMessage(settings.getMessage("singleServerAlreadyEnabled").replace("%SERVER%", server.getName()));
return;
}
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, Integer.parseInt(args[2]), true);
sender.sendMessage(settings.getMessage("starttimerStarted").replace("%TIME%", runnable.getTime()));
} else if (args[0].equalsIgnoreCase("timer")) {
if (args[1].equalsIgnoreCase("abort") || args[1].equalsIgnoreCase("stop") || args[1].equalsIgnoreCase("cancel")) {
if (checkPermission(sender, "servertimer")) return;
final ServerInfo server = plugin.getProxy().getServerInfo(args[2]);
if (server == null) {
sender.sendMessage(settings.getMessage("serverNotFound"));
return;
}
if (!plugin.isServerTaskRunning(server)) {
sender.sendMessage(settings.getMessage("timerNotRunning"));
return;
}
plugin.cancelSingleTask(server);
sender.sendMessage(settings.getMessage("timerCancelled"));
} else
sendUsage(sender);
}
}
@Override
protected void showMaintenanceStatus(final SenderInfo sender) {
if (settingsBungee.getMaintenanceServers().isEmpty()) {
sender.sendMessage(settings.getMessage("singleServerMaintenanceListEmpty"));
} else {
sender.sendMessage(settings.getMessage("singleServerMaintenanceList"));
settingsBungee.getMaintenanceServers().forEach(server -> sender.sendMessage("§8- §b" + server));
}
}
private ServerInfo checkSingleTimerArgs(final SenderInfo sender, final String[] args) {
final ServerInfo server = plugin.getProxy().getServerInfo(args[1]);
if (server == null) {
sender.sendMessage(settings.getMessage("serverNotFound"));
return null;
}
if (plugin.isServerTaskRunning(server)) {
sender.sendMessage(settings.getMessage("timerAlreadyRunning"));
return null;
}
return server;
}
}
@@ -1,19 +0,0 @@
package eu.kennytv.maintenance.bungee.command;
import eu.kennytv.maintenance.bungee.util.ProxiedSenderInfo;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
public final class MaintenanceBungeeCommandBase extends Command {
private final MaintenanceBungeeCommand command;
public MaintenanceBungeeCommandBase(final MaintenanceBungeeCommand command) {
super("maintenance", "", "maintenancebungee");
this.command = command;
}
@Override
public void execute(final CommandSender sender, final String[] args) {
command.execute(new ProxiedSenderInfo(sender), args);
}
}
@@ -1,64 +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;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public final class PostLoginListener implements Listener {
private final MaintenanceBungeePlugin plugin;
private final SettingsBungee settings;
private final Set<UUID> notifiedPlayers = new HashSet<>();
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.getMessage("joinNotification").replace("%PLAYER%", p.getName())));
return;
}
}
if (!p.hasPermission("maintenance.admin") || notifiedPlayers.contains(p.getUniqueId())) return;
plugin.async(() -> {
if (plugin.updateAvailable()) {
p.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + plugin.getNewestVersion() + "§c, you're on §a" + plugin.getVersion());
notifiedPlayers.add(p.getUniqueId());
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,62 +0,0 @@
package eu.kennytv.maintenance.bungee.listener;
import eu.kennytv.maintenance.bungee.MaintenanceBungeeBase;
import eu.kennytv.maintenance.bungee.SettingsBungee;
import eu.kennytv.maintenance.core.listener.IPingListener;
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, IPingListener {
private final MaintenanceBungeeBase plugin;
private final SettingsBungee settings;
private Favicon favicon;
public ProxyPingListener(final MaintenanceBungeeBase plugin, final SettingsBungee 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() && favicon != null)
ping.setFavicon(favicon);
}
@Override
public boolean loadIcon() {
try {
favicon = Favicon.create(ImageIO.read(new File("maintenance-icon.png")));
} catch (final IOException | IllegalArgumentException e) {
plugin.getLogger().warning("§4Could not load 'maintenance-icon.png' - did you create one in your Bungee folder (not the plugins folder)?");
if (settings.debugEnabled())
e.printStackTrace();
return false;
}
return true;
}
}
@@ -1,53 +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.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;
import net.md_5.bungee.event.EventPriority;
public final class ServerConnectListener implements Listener {
private final MaintenanceBungeePlugin plugin;
private final SettingsBungee settings;
private boolean warned;
public ServerConnectListener(final MaintenanceBungeePlugin plugin, final SettingsBungee settings) {
this.plugin = plugin;
this.settings = settings;
}
@EventHandler(priority = EventPriority.HIGHEST)
public void serverConnect(final ServerConnectEvent event) {
final ProxiedPlayer p = event.getPlayer();
final ServerInfo target = event.getTarget();
if (!plugin.isMaintenance(target))return;
if (p.hasPermission("maintenance.bypass") || settings.getWhitelistedPlayers().containsKey(p.getUniqueId()))
return;
event.setCancelled(true);
if (settings.isJoinNotifications()) {
target.getPlayers().stream().filter(player -> player.hasPermission("maintenance.joinnotification"))
.forEach(player -> player.sendMessage(settings.getMessage("joinNotification").replace("%PLAYER%", p.getName())));
}
// 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) {
p.sendMessage(settings.getMessage("singleMaintenanceKick").replace("%SERVER%", target.getName()));
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(p) || plugin.isMaintenance(fallback)) {
p.disconnect(settings.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", target.getName()));
if (!warned) {
plugin.getLogger().warning("Could not send player to the fallback server set in the SpigotServers.yml! Instead kicking player off the network!");
warned = true;
}
} else
p.connect(fallback);
}
}
@@ -1,33 +0,0 @@
package eu.kennytv.maintenance.bungee.runnable;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
import net.md_5.bungee.api.config.ServerInfo;
public final class SingleMaintenanceRunnable extends MaintenanceRunnableBase {
private final ServerInfo server;
public SingleMaintenanceRunnable(final MaintenanceModePlugin plugin, final Settings settings, final int minutes,
final boolean enable, final ServerInfo server) {
super(plugin, settings, minutes, enable);
this.server = server;
}
@Override
protected void finish() {
final MaintenanceBungeePlugin plugin = (MaintenanceBungeePlugin) this.plugin;
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());
}
}
@@ -1,45 +0,0 @@
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 ProxiedSenderInfo implements SenderInfo {
private final CommandSender sender;
public ProxiedSenderInfo(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);
}
}
@@ -1,6 +0,0 @@
# Enables maintenance on certain Spigot servers managed by your Bungee instance(s)
# If it's enabled on a server with players on it, they will be forwarded to the fallback server (or kicked completely if not set correctly)
maintenance-on:
#- SpigotServer1
#- AnotherServer
fallback: hub
@@ -1,53 +0,0 @@
# MaintenanceBungee Plugin by KennyTV
# Configs are cool, which means after the first plugin save, all comments will vanish
# To still know what each field is for, check https://gist.github.com/KennyTV/a73f2aed1e278d4c927f9f6a3ef9fde2#file-bungee-config-yml
# Enables maintenance-mode.
enable-maintenance-mode: false
# The message shown in the multiplayer server list motd.
# If you put in multiple entries, one of them will be chosen randomly on every ping.
pingmessages:
- "&cMaintenance mode!%NEWLINE%&6We will be back soon!"
#- "Another entry"
# If set to true, the message below will be shown at the top right corner of the server in the serverlist,
# where the playercount would normally be displayed.
# If set to false, the normal playercount will be shown.
# Alternatively you can use '%ONLINE%' and '%MAX% if you want to include the playercount in a custom message (e.g. '&cMaintenance &7%ONLINE%&8/&7%MAX%').
enable-playercountmessage: true
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"
# Is shown when a player tries to join while maintenance is enabled and they don't have the permission to bypass it.
kickmessage: "&cThe server is currently under maintenance!%NEWLINE%Try again later!"
# If using the timer command: In what intervalls before enabling/disabling maintenance there will be a broadcast.
timer-broadcast-for-seconds: [1200, 900, 600, 300, 120, 60, 30, 20, 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
# If set to true, the server icon will be changed to maintenance-icon.png in the Bungee main/base-folder.
custom-maintenance-icon: false
# Changes the language of command feedback/messages.
# Currently available are: en (English), de (German), fr (French), pt (Portuguese)
language: en
# Only enable MySQL if you really know what you are doing.
mysql:
use-mysql: false
host: host
port: 3306
database: database
username: username
password: password
# Requests to the database will only be made at least x seconds after the last request,
# so there won't be a request on every single ping on a server with many players.
# Set this to 0 to make a database request on every single ping.
update-interval: 15
@@ -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/
@@ -1,161 +0,0 @@
package eu.kennytv.maintenance.core;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
import eu.kennytv.maintenance.core.util.ServerType;
import eu.kennytv.maintenance.core.util.Version;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Logger;
public abstract class MaintenanceModePlugin implements IMaintenance {
protected final Version version;
protected ServerListPlusHook serverListPlusHook;
protected MaintenanceRunnable runnable;
protected int taskId;
private final String prefix;
private final ServerType serverType;
private Version newestVersion;
protected MaintenanceModePlugin(final String prefix, final String version, final ServerType serverType) {
this.prefix = prefix;
this.version = new Version(version);
this.serverType = serverType;
checkNewestVersion();
}
@Override
public boolean isMaintenance() {
return getSettings().isMaintenance();
}
@Override
public String getVersion() {
return version.toString();
}
@Override
public boolean isTaskRunning() {
return taskId != 0 && runnable != null;
}
public void startMaintenanceRunnable(final int minutes, final boolean enable) {
runnable = new MaintenanceRunnable(this, (Settings) getSettings(), minutes, enable);
taskId = startMaintenanceRunnable(runnable);
}
public Version getNewestVersion() {
return newestVersion;
}
protected abstract int startMaintenanceRunnable(Runnable runnable);
public abstract void async(Runnable runnable);
public abstract void cancelTask();
public abstract File getPluginFile();
public abstract void broadcast(String message);
public MaintenanceRunnable getRunnable() {
return runnable;
}
public String getPrefix() {
return prefix;
}
public ServerType getServerType() {
return serverType;
}
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 checkNewestVersion() {
try {
final HttpURLConnection c = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=40699").openConnection();
final String newVersionString = new BufferedReader(new InputStreamReader(c.getInputStream())).readLine();
final Version newVersion = new Version(newVersionString);
final boolean available = !newVersion.equals(version);
if (available)
newestVersion = newVersion;
} catch (final Exception ignored) {
}
}
public boolean updateAvailable() {
checkNewestVersion();
return version.compareTo(newestVersion) == -1;
}
public String getUpdateMessage() {
if (version.compareTo(newestVersion) == -1) {
return "§cNewest version available: §aVersion " + newestVersion + "§c, you're on §a" + version;
} else if (version.compareTo(newestVersion) != 0) {
if (version.getTag().equalsIgnoreCase("snapshot")) {
return "§cYou're running a development version, please report bugs on the Discord server (https://kennytv.eu/discord) or the GitHub tracker (https://kennytv.eu/maintenance/issues)";
} else {
return "§cYou're running a version, that doesn't exist! §cN§ai§dc§ee§5!";
}
}
return "You have the latest version of the plugin installed.";
}
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;
}
}
public abstract Logger getLogger();
}
@@ -1,216 +0,0 @@
package eu.kennytv.maintenance.core;
import eu.kennytv.maintenance.api.ISettings;
import java.util.*;
public abstract class Settings implements ISettings {
private static final Random RANDOM = new Random();
protected final Map<UUID, String> whitelistedPlayers = new HashMap<>();
private final MaintenanceModePlugin plugin;
protected boolean maintenance;
private Set<Integer> broadcastIntervalls;
private List<String> pingMessages;
private String playerCountMessage;
private String playerCountHoverMessage;
private String kickMessage;
protected String languageName;
private boolean customPlayerCountMessage;
private boolean customMaintenanceIcon;
private boolean joinNotifications;
private boolean debug;
protected Settings(final MaintenanceModePlugin plugin) {
this.plugin = plugin;
}
protected void loadSettings() {
updateConfig();
pingMessages = getConfigList("pingmessages");
maintenance = getConfigBoolean("enable-maintenance-mode");
customPlayerCountMessage = getConfigBoolean("enable-playercountmessage");
customMaintenanceIcon = getConfigBoolean("custom-maintenance-icon");
joinNotifications = getConfigBoolean("send-join-notification");
broadcastIntervalls = new HashSet<>(getConfigIntList("timer-broadcast-for-seconds"));
playerCountMessage = getColoredString(getConfigString("playercountmessage"));
playerCountHoverMessage = getColoredString(getConfigString("playercounthovermessage"));
kickMessage = getColoredString(getConfigString("kickmessage"));
languageName = getConfigString("language").toLowerCase();
debug = getConfigBoolean("debug");
if (customMaintenanceIcon) {
reloadMaintenanceIcon();
}
loadExtraSettings();
if (debug) {
plugin.getLogger().info("enable-maintenance-mode:" + maintenance);
plugin.getLogger().info("whitelistedPlayers:" + whitelistedPlayers);
plugin.getLogger().info("timer-broadcast-for-seconds:" + broadcastIntervalls);
plugin.getLogger().info("pingmessages:" + pingMessages);
plugin.getLogger().info("playercountmessage:" + playerCountMessage);
plugin.getLogger().info("playercounthovermessage:" + playerCountHoverMessage);
plugin.getLogger().info("kickmessage:" + kickMessage);
plugin.getLogger().info("language:" + languageName);
plugin.getLogger().info("enable-playercountmessage:" + customPlayerCountMessage);
plugin.getLogger().info("custom-maintenance-icon:" + customMaintenanceIcon);
plugin.getLogger().info("send-join-notification:" + joinNotifications);
}
}
private void updateConfig() {
boolean fileChanged = false;
// 2.3 pingmessage -> pingmessages
if (configContains("pingmessage")) {
final List<String> list = new ArrayList<>();
list.add(getConfigString("pingmessage"));
setToConfig("pingmessages", list);
setToConfig("pingmessage", null);
fileChanged = true;
}
// 2.4 enable-playercountmessage
if (!configContains("enable-playercountmessage")) {
setToConfig("enable-playercountmessage", true);
fileChanged = true;
}
// 2.4. timer-broadcasts-for-minutes -> timer-broadcast-for-seconds
if (configContains("timer-broadcasts-for-minutes") || !configContains("timer-broadcast-for-seconds")) {
setToConfig("timer-broadcast-for-seconds", Arrays.asList(1200, 900, 600, 300, 120, 60, 30, 20, 10, 5, 4, 3, 2, 1));
setToConfig("timer-broadcasts-for-minutes", null);
fileChanged = true;
}
// 2.5 language
if (!configContains("language")) {
setToConfig("language", "en");
}
if (updateExtraConfig() || fileChanged) {
saveConfig();
}
}
public boolean updateExtraConfig() {
return false;
}
public abstract void saveWhitelistedPlayers();
public abstract String getConfigString(String path);
public abstract String getMessage(String path);
public abstract boolean getConfigBoolean(String path);
public abstract List<Integer> getConfigIntList(String path);
public abstract List<String> getConfigList(String path);
public abstract void loadExtraSettings();
public abstract void setWhitelist(String uuid, String s);
public abstract void saveConfig();
public abstract void reloadConfigs();
public abstract void setToConfig(String path, Object var);
public abstract boolean configContains(String path);
public abstract String getColoredString(String s);
public List<String> getPingMessages() {
return pingMessages;
}
public Set<Integer> getBroadcastIntervalls() {
return broadcastIntervalls;
}
public String getPlayerCountMessage() {
return playerCountMessage;
}
public String getPlayerCountHoverMessage() {
return playerCountHoverMessage;
}
public String getKickMessage() {
return kickMessage;
}
public String getLanguage() {
return languageName;
}
public void setMaintenance(final boolean maintenance) {
this.maintenance = maintenance;
}
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()));
}
public boolean hasCustomPlayerCountMessage() {
return customPlayerCountMessage;
}
@Override
public boolean isMaintenance() {
return maintenance;
}
@Override
public boolean isJoinNotifications() {
return joinNotifications;
}
@Override
public boolean hasCustomIcon() {
return customMaintenanceIcon;
}
@Override
public Map<UUID, String> getWhitelistedPlayers() {
return whitelistedPlayers;
}
@Override
public boolean removeWhitelistedPlayer(final UUID uuid) {
if (!whitelistedPlayers.containsKey(uuid)) return false;
whitelistedPlayers.remove(uuid);
setWhitelist(uuid.toString(), null);
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);
setWhitelist(uuid.toString(), null);
saveWhitelistedPlayers();
return true;
}
@Override
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;
}
@Override
public boolean debugEnabled() {
return debug;
}
}
@@ -1,21 +0,0 @@
package eu.kennytv.maintenance.core.command;
import eu.kennytv.maintenance.core.util.SenderInfo;
final class CommandInfo {
private final String[] messages;
private final String permission;
CommandInfo(final String permission, final String... messages) {
this.messages = messages;
this.permission = permission;
}
public boolean hasPermission(final SenderInfo sender) {
return sender.hasPermission("maintenance." + permission);
}
public String[] getMessages() {
return messages;
}
}
@@ -1,315 +0,0 @@
package eu.kennytv.maintenance.core.command;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.util.SenderInfo;
import eu.kennytv.maintenance.core.util.ServerType;
import java.util.*;
public abstract class MaintenanceCommand {
protected final MaintenanceModePlugin plugin;
protected final Settings settings;
private final List<CommandInfo> commandInfos;
private final String name;
protected MaintenanceCommand(final MaintenanceModePlugin plugin, final Settings settings, final String name) {
this.plugin = plugin;
this.settings = settings;
this.name = name;
this.commandInfos = new ArrayList<>();
addCommandInfo("reload", "§6/maintenance reload §7(Reloads the config file, whitelist file and the server-icon)");
addCommandInfo("toggle", "§6/maintenance on §7(Enables maintenance mode)", "§6/maintenance off §7(Disables maintenance mode)");
if (plugin.getServerType() == ServerType.BUNGEE) {
addCommandInfo("toggleserver", "§6/maintenance on <server> §7(Enables maintenance mode on a specific proxied server)",
"§6/maintenance off <server> §7(Disables maintenance mode on a specific proxied server)");
}
addCommandInfo("timer", "§6/maintenance starttimer <minutes> §7(After the given time in minutes, maintenance mode will be enabled)",
"§6/maintenance endtimer <minutes> §7(After the given time in minutes, maintenance mode will be disabled)",
"§6/maintenance timer abort §7(If running, the current timer will be aborted)");
if (plugin.getServerType() == ServerType.BUNGEE) {
addCommandInfo("servertimer", "§6/maintenance starttimer <server> <minutes> §7(After the given time in minutes, maintenance mode will be enabled on the given server)",
"§6/maintenance endtimer <server> <minutes> §7(After the given time in minutes, maintenance mode will be disabled on the given server)",
"§6/maintenance timer abort <server> §7(If running, the timer running for that server will be aborted)");
}
addCommandInfo("whitelist.list", "§6/maintenance whitelist §7(Shows all whitelisted players for the maintenance mode)");
addCommandInfo("whitelist.add", "§6/maintenance add <player> §7(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)");
addCommandInfo("whitelist.remove", "§6/maintenance remove <player> §7(Removes the player from the maintenance whitelist)");
addCommandInfo("setmotd", "§6/maintenance setmotd <index> <1/2> <message> §7(Sets a motd for maintenance mode)", "§6/maintenance removemotd <index> §7(Removes a maintenance motd)");
addCommandInfo("motd", "§6/maintenance motd §7(Lists the currently set maintenance motds)");
addCommandInfo("update", "§6/maintenance update §7(Remotely downloads the newest version of the plugin onto your server)");
}
private void addCommandInfo(final String permission, final String... messages) {
commandInfos.add(new CommandInfo(permission, messages));
}
public void execute(final SenderInfo sender, final String[] args) {
if (checkPermission(sender, "command")) return;
if (args.length == 1) {
if (args[0].equalsIgnoreCase("on") || args[0].equalsIgnoreCase("off")) {
if (checkPermission(sender, "toggle")) return;
final boolean maintenance = args[0].equalsIgnoreCase("on");
if (maintenance == plugin.isMaintenance()) {
sender.sendMessage(settings.getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
return;
}
plugin.setMaintenance(maintenance);
} else if (args[0].equalsIgnoreCase("reload")) {
if (checkPermission(sender, "reload")) return;
settings.reloadConfigs();
sender.sendMessage(settings.getMessage("reload"));
} else if (args[0].equalsIgnoreCase("update")) {
if (checkPermission(sender, "update")) return;
checkForUpdate(sender);
} else if (args[0].equals("forceupdate")) {
if (checkPermission(sender, "update")) return;
sender.sendMessage(settings.getMessage("updateDownloading"));
if (plugin.installUpdate())
sender.sendMessage(settings.getMessage("updateFinished"));
else
sender.sendMessage(settings.getMessage("updateFailed"));
} else if (args[0].equalsIgnoreCase("whitelist")) {
if (checkPermission(sender, "whitelist.list")) return;
final Map<UUID, String> players = settings.getWhitelistedPlayers();
if (players.isEmpty()) {
sender.sendMessage(settings.getMessage("whitelistEmtpy"));
} else if (players.size() == 1 && players.containsKey(UUID.fromString("a8179ff3-c201-4a75-bdaa-9d14aca6f83f"))) {
sender.sendMessage(settings.getMessage("whitelistEmptyDefault"));
} else {
sender.sendMessage(settings.getMessage("whitelistedPlayers"));
final String format = settings.getMessage("whitelistedPlayersFormat");
players.forEach((key, value) -> sender.sendMessage(format.replace("%NAME%", value).replace("%UUID%", key.toString())));
sender.sendMessage("");
}
} else if (args[0].equalsIgnoreCase("motd")) {
if (checkPermission(sender, "motd")) return;
sender.sendMessage(settings.getMessage("motdList"));
for (int i = 0; i < settings.getPingMessages().size(); i++) {
sender.sendMessage("§b" + (i + 1) + "§8§m---------");
for (final String motd : settings.getColoredString(settings.getPingMessages().get(i)).split("%NEWLINE%")) {
sender.sendMessage(motd);
}
}
sender.sendMessage("§8§m----------");
} else if (args[0].equalsIgnoreCase("status") && plugin.getServerType() == ServerType.BUNGEE) {
if (checkPermission(sender, "status")) return;
showMaintenanceStatus(sender);
} else
sendUsage(sender);
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("help")) {
if (!isNumeric(args[1])) {
sender.sendMessage(settings.getMessage("helpUsage"));
return;
}
sendUsage(sender, Integer.parseInt(args[1]));
} else if ((args[0].equalsIgnoreCase("on") || args[0].equalsIgnoreCase("off")) && plugin.getServerType() == ServerType.BUNGEE) {
if (checkPermission(sender, "toggleserver")) return;
handleToggleServerCommand(sender, args);
} else if (args[0].equalsIgnoreCase("endtimer")) {
if (checkPermission(sender, "timer")) return;
if (checkTimerArgs(sender, args[1], "endtimerUsage")) return;
if (!plugin.isMaintenance()) {
sender.sendMessage(settings.getMessage("alreadyDisabled"));
return;
}
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), false);
sender.sendMessage(settings.getMessage("endtimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
} else if (args[0].equalsIgnoreCase("starttimer")) {
if (checkPermission(sender, "timer")) return;
if (checkTimerArgs(sender, args[1], "starttimerUsage")) return;
if (plugin.isMaintenance()) {
sender.sendMessage(settings.getMessage("alreadyEnabled"));
return;
}
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), true);
sender.sendMessage(settings.getMessage("starttimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
} else if (args[0].equalsIgnoreCase("timer")) {
if (args[1].equalsIgnoreCase("abort") || args[1].equalsIgnoreCase("stop") || args[1].equalsIgnoreCase("cancel")) {
if (checkPermission(sender, "timer")) return;
if (!plugin.isTaskRunning()) {
sender.sendMessage(settings.getMessage("timerNotRunning"));
return;
}
plugin.cancelTask();
sender.sendMessage(settings.getMessage("timerCancelled"));
} else
sendUsage(sender);
} else if (args[0].equalsIgnoreCase("add")) {
if (checkPermission(sender, "whitelist.add")) return;
addPlayerToWhitelist(sender, args[1]);
} else if (args[0].equalsIgnoreCase("remove")) {
if (checkPermission(sender, "whitelist.remove")) return;
removePlayerFromWhitelist(sender, args[1]);
} else if (args[0].equalsIgnoreCase("removemotd")) {
if (checkPermission(sender, "setmotd")) return;
if (!isNumeric(args[1])) {
sender.sendMessage(settings.getMessage("removeMotdUsage"));
return;
}
if (settings.getPingMessages().size() < 2) {
sender.sendMessage(settings.getMessage("removeMotdError"));
return;
}
final int index = Integer.parseInt(args[1]);
if (index > settings.getPingMessages().size()) {
sender.sendMessage(settings.getMessage("setMotdIndexError").replace("%MOTDS%", Integer.toString(settings.getPingMessages().size()))
.replace("%NEWAMOUNT%", Integer.toString(settings.getPingMessages().size())));
return;
}
settings.getPingMessages().remove(index - 1);
settings.setToConfig("pingmessages", settings.getPingMessages());
settings.saveConfig();
sender.sendMessage(settings.getMessage("removedMotd").replace("%INDEX%", args[1]));
} else
sendUsage(sender);
} else if (args.length == 3 && plugin.getServerType() == ServerType.BUNGEE) {
handleTimerServerCommands(sender, args);
} else if (args.length > 3 && args[0].equalsIgnoreCase("setmotd")) {
if (checkPermission(sender, "setmotd")) return;
if (!isNumeric(args[1])) {
sender.sendMessage(settings.getMessage("setMotdUsage"));
return;
}
final int index = Integer.parseInt(args[1]);
if (index < 1 || index > settings.getPingMessages().size() + 1) {
sender.sendMessage(settings.getMessage("setMotdIndexError").replace("%MOTDS%", Integer.toString(settings.getPingMessages().size()))
.replace("%NEWAMOUNT%", Integer.toString(settings.getPingMessages().size() + 1)));
return;
}
if (!isNumeric(args[2])) {
sender.sendMessage(settings.getMessage("setMotdLineError"));
return;
}
final int line = Integer.parseInt(args[2]);
if (line != 1 && line != 2) {
sender.sendMessage(settings.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.setToConfig("pingmessages", settings.getPingMessages());
settings.saveConfig();
sender.sendMessage(settings.getMessage("setMotd").replace("%LINE%", args[2]).replace("%INDEX%", args[1])
.replace("%MOTD%", "§f" + settings.getColoredString(message)));
} else
sendUsage(sender);
}
protected void sendUsage(final SenderInfo sender) {
sendUsage(sender, 1);
}
private static final int COMMANDS_PER_PAGE = 8;
protected void sendUsage(final SenderInfo sender, final int page) {
final List<String> commands = new ArrayList<>();
commandInfos.stream().filter(cmd -> cmd.hasPermission(sender)).forEach(cmd -> {
for (final String message : cmd.getMessages()) {
commands.add(message);
}
});
if ((page - 1) * COMMANDS_PER_PAGE > commands.size()) {
sender.sendMessage(settings.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);
sender.sendMessage("");
sender.sendMessage("§8========[ §e" + name + " §8| §eVersion: §e" + plugin.getVersion() + " §8]========");
filteredCommands.forEach(sender::sendMessage);
if (page * 10 < commands.size())
sender.sendMessage("§7Use §b/maintenance help " + (page + 1) + " §7to get to the next help window.");
else
sender.sendMessage("§8× §7Created by §bKennyTV");
sender.sendMessage("§8========[ §e" + name + " §8| §e" + page + "/" + ((commands.size() + getDivide(commands.size())) / COMMANDS_PER_PAGE) + " §8]========");
sender.sendMessage("");
}
private int getDivide(final int size) {
final int commandSize = size % COMMANDS_PER_PAGE;
return commandSize > 0 ? COMMANDS_PER_PAGE - commandSize : 0;
}
protected boolean checkTimerArgs(final SenderInfo sender, final String time, final String usageKey) {
if (!isNumeric(time)) {
sender.sendMessage(settings.getMessage(usageKey));
return true;
}
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] §c§oThink about running a timer for a negative amount of minutes. Doesn't work §lthat §c§owell.");
return true;
}
return false;
}
protected boolean checkPermission(final SenderInfo sender, final String permission) {
if (!sender.hasPermission("maintenance." + permission)) {
sender.sendMessage(settings.getMessage("noPermission"));
return true;
}
return false;
}
protected boolean isNumeric(final String string) {
try {
Integer.parseInt(string);
} catch (final NumberFormatException nfe) {
return false;
}
return true;
}
protected abstract void addPlayerToWhitelist(SenderInfo sender, String name);
protected abstract void removePlayerFromWhitelist(SenderInfo sender, String name);
protected abstract void checkForUpdate(SenderInfo sender);
protected void showMaintenanceStatus(SenderInfo sender) {
}
protected void handleToggleServerCommand(SenderInfo sender, String[] args) {
}
protected void handleTimerServerCommands(SenderInfo sender, String[] args) {
}
}
@@ -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,6 +0,0 @@
package eu.kennytv.maintenance.core.listener;
public interface IPingListener {
boolean loadIcon();
}
@@ -1,26 +0,0 @@
package eu.kennytv.maintenance.core.runnable;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
public final class MaintenanceRunnable extends MaintenanceRunnableBase {
public MaintenanceRunnable(final MaintenanceModePlugin 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());
}
}
@@ -1,61 +0,0 @@
package eu.kennytv.maintenance.core.runnable;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.Settings;
public abstract class MaintenanceRunnableBase implements Runnable {
protected final MaintenanceModePlugin plugin;
protected final Settings settings;
protected final boolean enable;
protected int seconds;
protected MaintenanceRunnableBase(final MaintenanceModePlugin plugin, final Settings settings, final int minutes, final boolean enable) {
this.plugin = plugin;
this.settings = settings;
this.seconds = minutes * 60;
this.enable = enable;
}
@Override
public void run() {
if (seconds == 0) {
finish();
} else if (settings.getBroadcastIntervalls().contains(seconds)) {
if (enable)
plugin.broadcast(startMessageKey());
else
plugin.broadcast(endMessageKey());
}
seconds--;
}
protected abstract void finish();
protected abstract String startMessageKey();
protected abstract String endMessageKey();
public String getTime() {
final int preHours = this.seconds / 60;
final int minutes = preHours % 60;
final int seconds = this.seconds % 60;
final StringBuilder buider = new StringBuilder();
append(buider, "hour", preHours / 60);
append(buider, "minute", minutes);
append(buider, "second", seconds);
return buider.toString();
}
private void append(final StringBuilder builder, final String timeUnit, final int time) {
if (time == 0) return;
if (builder.length() != 0)
builder.append(" ");
builder.append(time).append(" ").append(settings.getMessage(time == 1 ? timeUnit : timeUnit + "s"));
}
public int getSecondsLeft() {
return seconds;
}
}
@@ -1,16 +0,0 @@
package eu.kennytv.maintenance.core.util;
import java.util.UUID;
public interface SenderInfo {
UUID getUuid();
String getName();
boolean hasPermission(String permission);
void sendMessage(String message);
boolean isPlayer();
}
@@ -1,7 +0,0 @@
package eu.kennytv.maintenance.core.util;
public enum ServerType {
BUNGEE,
SPIGOT
}
@@ -1,76 +0,0 @@
package eu.kennytv.maintenance.core.util;
public final class Version implements Comparable<Version> {
private final int[] parts = new int[3];
private final String version;
private final String tag;
public Version(final String version) {
if (version == null || version.isEmpty()) {
this.version = "";
tag = "";
System.out.println("Unknown Maintenance version detected!");
return;
}
final String[] split = version.split("-", 2)[0].split("\\.");
for (int i = 0; i < split.length; i++) {
if (!isNumeric(split[i])) {
this.version = "";
tag = "";
System.out.println("Unknown Maintenance version detected!");
return;
}
parts[i] = Integer.parseInt(split[i]);
}
this.version = version;
tag = version.contains("-") ? version.split("-", 2)[1] : "";
}
/**
* Compare two versions
*
* @param version version to compare to
* @return 0 if they are the same, 1 if this version (not the one to compare to) is newer, -1 if older
*/
@Override
public int compareTo(final Version version) {
if (version == null || version.toString() == null) return 0;
final int max = Math.max(this.parts.length, version.parts.length);
for (int i = 0; i < max; i += 1) {
final int partA = i < this.parts.length ? this.parts[i] : 0;
final int partB = i < version.parts.length ? version.parts[i] : 0;
if (partA < partB) return -1;
if (partA > partB) return 1;
}
if (this.tag.isEmpty() && !version.tag.isEmpty())
return 1;
if (!this.tag.isEmpty() && version.tag.isEmpty())
return -1;
return 0;
}
public String getTag() {
return tag;
}
@Override
public String toString() {
return version;
}
@Override
public boolean equals(final Object o) {
return o instanceof Version && o == this || version.equals(o.toString());
}
private 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
@@ -1,65 +0,0 @@
# Maintenance Plugin by KennyTV
# Don't remove words inbetween the '%' if you don't exactly know why you're doing it
noPermission: "&cYou do not have the permission to execute that command."
maintenanceActivated: "&8[&eMaintenance&8] &6Maintenance mode is now activated."
maintenanceDeactivated: "&8[&eMaintenance&8] &6Maintenance mode is now deactivated."
alreadyEnabled: "&8[&eMaintenance&8] &cMaintenance is already enabled!"
alreadyDisabled: "&8[&eMaintenance&8] &cMaintenance is already disabled!"
helpUsage: "&8[&eMaintenance&8] &c/maintenance help <page>"
helpPageNotFound: "&8[&eMaintenance&8] &cThere is no page with that number!"
endtimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode will be disabled in &6%TIME%&7."
endtimerStarted: "&8[&eMaintenance&8] &aStarted timer: &7Maintenance mode will be deactivated in &6%TIME%&7."
endtimerUsage: "&8[&eMaintenance&8] &c/maintenance endtimer <minutes>"
starttimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%TIME%&7."
starttimerStarted: "&8[&eMaintenance&8] &aStarted timer: &7Maintenance mode will be activated in &6%TIME%&7."
starttimerUsage: "&8[&eMaintenance&8] &c/maintenance starttimer <minutes>"
timerAlreadyRunning: "&8[&eMaintenance&8] &cThere's already a timer scheduled!"
timerNotRunning: "&8[&eMaintenance&8] &cThere's currently no running timer."
timerCancelled: "&8[&eMaintenance&8] &cThe current timer has been disabled."
timerTooLong: "&8[&eMaintenance&8] &cThe number has to be less than 40320 (28 days)!"
joinNotification: "&8[&eMaintenance&8] &e%PLAYER% &ctried to join the server."
motdList: "&8[&eMaintenance&8] &7List of your maintenance motds:"
reload: "&8[&eMaintenance&8] &aReloaded config, whitelistedplayers, language file and the maintenance icon."
removedMotd: "&8[&eMaintenance&8] &aRemoved motd number %INDEX%."
removeMotdError: "&8[&eMaintenance&8] &cYou only have one motd, so you can't remove any!"
removeMotdUsage: "&8[&eMaintenance&8] &c/maintenance removemotd <index>"
setMotd: "&8[&eMaintenance&8] &aSet line %LINE% of the %INDEX%. maintenance motd to %MOTD%"
setMotdUsage: "&8[&eMaintenance&8] &c/maintenance setmotd <index> <1/2> <message>"
setMotdIndexError: "&8[&eMaintenance&8] &cYou currently have %MOTDS% motds, so you have to pick a number between 1 and %NEWAMOUNT%."
setMotdLineError: "&8[&eMaintenance&8] &cThe second argument has to be the line number (1 or 2)!"
updateDownloading: "&8[&eMaintenance&8] &c&lDownloading update..."
updateFailed: "&8[&eMaintenance&8] &4&lUpdate failed!"
updateFinished: "&8[&eMaintenance&8] &a&lThe update was successful! To prevent issues with tasks and to complete the update, you have to restart the server!"
whitelistedPlayers: "&8[&eMaintenance&8] &6Whitelisted players for maintenance:"
whitelistedPlayersFormat: "&8- &e%NAME% &8(&7%UUID%&8)"
whitelistAdded: "&8[&eMaintenance&8] &aAdded &b%PLAYER% &ato the maintenance whitelist!"
whitelistAlreadyAdded: "&8[&eMaintenance&8] &b%PLAYER% &calready is in the maintenance whitelist!"
whitelistRemoved: "&8[&eMaintenance&8] &aRemoved &b%PLAYER% &afrom the maintenance whitelist!"
whitelistNotFound: "&8[&eMaintenance&8] &cThis player is not in the maintenance whitelist!"
whitelistEmtpy: "&8[&eMaintenance&8] &cThe maintenance whitelist is empty! Use '/maintenance add <player>' to add someone!"
whitelistEmptyDefault: "&8[&eMaintenance&8] &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!"
playerNotFound: "&8[&eMaintenance&8] &cNo player with this name has played on this server before."
playerNotOnline: "&8[&eMaintenance&8] &cThere's no player online with that name."
second: "second"
seconds: "seconds"
minute: "minute"
minutes: "minutes"
hour: "hour"
hours: "hours"
# Some messages for the Bungee part, just ignore them if you use the plugin on Spigot
serverNotFound: "&8[&eMaintenance&8] &cNo server with this name is registered on the proxy!"
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be disabled in &6%TIME%&7."
singleEndtimerUsage: "&8[&eMaintenance&8] &c/maintenance endtimer <server> <minutes>"
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be enabled in &6%TIME%&7."
singleStarttimerUsage: "&8[&eMaintenance&8] &c/maintenance starttimer <server> <minutes>"
singleMaintenanceKick: "&8[&eMaintenance&8] &cThe server %SERVER% is currently under maintenance! Try again later!"
singleMaintenanceKickComplete: "&cThe server %SERVER% is under maintenance!%NEWLINE%&cYou may try to rejoin to go onto another server!"
singleMaintenanceActivated: "&8[&eMaintenance&8] &6Maintenance mode is now activated on server &e%SERVER%&6."
singleMaintenanceDeactivated: "&8[&eMaintenance&8] &6Maintenance mode is now deactivated on server &e%SERVER%&6."
singleServerAlreadyEnabled: "&8[&eMaintenance&8] &cMaintenance is already enabled on server &e%SERVER%&c!"
singleServerAlreadyDisabled: "&8[&eMaintenance&8] &cMaintenance is already disabled on server &e%SERVER%&c!"
singleServerMaintenanceList: "&8[&eMaintenance&8] &7Proxied servers, that have maintenance enabled:"
singleServerMaintenanceListEmpty: "&8[&eMaintenance&8] &7There are no proxied servers that are under maintenance."
@@ -1,65 +0,0 @@
# Maintenance Plugin par KennyTV
# Ne supprime pas des mots entre les '%' si tu ne sait pas pourqoi exactement
noPermission: "&cVous n'avez pas la permission d'exécuter cette commande."
maintenanceActivated: "&8[&eMaintenance&8] &6Le mode maintenance est maintenant activé."
maintenanceDeactivated: "&8[&eMaintenance&8] &6Le mode maintenance est maintenant désactivé."
alreadyEnabled: "&8[&eMaintenance&8] &cLa maintenance est déjà activée!"
alreadyDisabled: "&8[&eMaintenance&8] &cLa maintenance est déjà désactivée!"
helpUsage: "&8[&eMaintenance&8] &c/maintenance help <page>"
helpPageNotFound: "&8[&eMaintenance&8] &cIl n'y a pas cette page!"
endtimerBroadcast: "&8[&eMaintenance&8] &7Le mode maintenance sera désactivé dans &6%TIME%&7."
endtimerStarted: "&8[&eMaintenance&8] &aminuterie: &7Le mode maintenance sera désactivé dans &6%TIME%&7."
endtimerUsage: "&8[&eMaintenance&8] &c/maintenance endtimer <minutes>"
starttimerBroadcast: "&8[&eMaintenance&8] &7MLe mode de maintenance sera activé dans &6%TIME%&7."
starttimerStarted: "&8[&eMaintenance&8] &aminuterie: &7Le mode maintenance sera activé dans &6%TIME%&7."
starttimerUsage: "&8[&eMaintenance&8] &c/maintenance starttimer <minutes>"
timerAlreadyRunning: "&8[&eMaintenance&8] &cIl y a déjà un horaire prévu!"
timerNotRunning: "&8[&eMaintenance&8] &cIl n'y a actuellement aucune maintenance prévue."
timerCancelled: "&8[&eMaintenance&8] &cLa minuterie actuelle a été désactivée."
timerTooLong: "&8[&eMaintenance&8] &cLe nombre doit être inférieur à 40320 (28 jours)!"
joinNotification: "&8[&eMaintenance&8] &e%PLAYER% &ca essayé de rejoindre le serveur."
motdList: "&8[&eMaintenance&8] &7Liste de vos motd pour la maintenance:"
reload: "&8[&eMaintenance&8] &afichier config, liste blanche (whitelist) joueurs, fichier de langue et l'icône de maintenance, recharger."
removedMotd: "&8[&eMaintenance&8] &aNuméro de motd supprimé %INDEX%."
removeMotdError: "&8[&eMaintenance&8] &cVous n’avez qu’un motd, vous ne pouvez donc en supprimer!"
removeMotdUsage: "&8[&eMaintenance&8] &c/maintenance removemotd <index>"
setMotd: "&8[&eMaintenance&8] &aLigne fixe %LINE% du %INDEX%. maintenance motd à %MOTD%"
setMotdUsage: "&8[&eMaintenance&8] &c/maintenance setmotd <index> <1/2> <message>"
setMotdIndexError: "&8[&eMaintenance&8] &cVous avez actuellement %MOTDS% vous devez donc choisir un nombre compris entre 1 et %NEWAMOUNT%."
setMotdLineError: "&8[&eMaintenance&8] &cLe deuxième argument doit être le numéro de ligne (1 ou 2)!"
updateDownloading: "&8[&eMaintenance&8] &c&lTéléchargement de la mise à jour..."
updateFailed: "&8[&eMaintenance&8] &4&lLa mise à jour a échoué!"
updateFinished: "&8[&eMaintenance&8] &a&lLa mise à jour a été réussie! Pour éviter les problèmes liés aux tâches et terminer la mise à jour, vous devez redémarrer le serveur!"
whitelistedPlayers: "&8[&eMaintenance&8] &6Liste blanche des joueurs pour la maintenance:"
whitelistedPlayersFormat: "&8- &e%NAME% &8(&7%UUID%&8)"
whitelistAdded: "&8[&eMaintenance&8] &aAdded &b%PLAYER% &aà la liste blanche de maintenance!"
whitelistAlreadyAdded: "&8[&eMaintenance&8] &b%PLAYER% &cest déjà dans la liste blanche de maintenance!"
whitelistRemoved: "&8[&eMaintenance&8] &aEnlevé &b%PLAYER% &ade la liste blanche de maintenance!"
whitelistNotFound: "&8[&eMaintenance&8] &cCe joueur n'est pas dans la liste blanche de la maintenance!"
whitelistEmtpy: "&8[&eMaintenance&8] &cLa liste blanche de maintenance est vide! Utilisation '/maintenance add <joueur>' ajouter quelqu'un!"
whitelistEmptyDefault: "&8[&eMaintenance&8] &cUtilisation '/maintenance add <joueur>' ajouter quelqu'un. Alternativement, vous pouvez ajouter le uuid d'un joueur à la WhitelistedPlayers.yml comme on le voit dans l'exemple du fichier!"
playerNotFound: "&8[&eMaintenance&8] &cAucun joueur avec ce nom n'a joué sur ce serveur auparavant."
playerNotOnline: "&8[&eMaintenance&8] &cIl n'y a pas de joueur en ligne avec ce nom."
second: "second"
seconds: "seconds"
minute: "minute"
minutes: "minutes"
hour: "heur"
hours: "heurs"
# Quelques messages pour la partie Bungee, ignorez-les si vous utilisez le plugin sur Spigot
serverNotFound: "&8[&eMaintenance&8] &cAucun serveur avec ce nom n'est enregistré sur le proxy!"
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7maintenance sur serveur %SERVER% sera désactivé dans &6%TIME%&7."
singleEndtimerUsage: "&8[&eMaintenance&8] &c/maintenance endtimer <serveur> <minutes>"
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7Maintenance sur le serveur %SERVER% sera activé dans &6%TIME%&7."
singleStarttimerUsage: "&8[&eMaintenance&8] &c/maintenance starttimer <serveur> <minutes>"
singleMaintenanceKick: "&8[&eMaintenance&8] &cLe serveur %SERVER% est actuellement en maintenance! Réessayez plus tard!"
singleMaintenanceKickComplete: "&cLe serveur %SERVER% est en maintenance!%NEWLINE%&cVous pouvez essayer un autre serveur!"
singleMaintenanceActivated: "&8[&eMaintenance&8] &6La maintenance est maintenant activé sur le serveur &e%SERVER%&6."
singleMaintenanceDeactivated: "&8[&eMaintenance&8] &6La maintenance est maintenant désactivé sur le serveur &e%SERVER%&6."
singleServerAlreadyEnabled: "&8[&eMaintenance&8] &cLa maintenance est déjà activée sur le serveur &e%SERVER%&c!"
singleServerAlreadyDisabled: "&8[&eMaintenance&8] &cLa maintenance est déjà désactivée sur le serveur &e%SERVER%&c!"
singleServerMaintenanceList: "&8[&eMaintenance&8] &7Serveurs proxy avec maintenance activée:"
singleServerMaintenanceListEmpty: "&8[&eMaintenance&8] &7Il n'y a pas de serveurs proxy en maintenance."
@@ -1,65 +0,0 @@
# Maintenance Plugin by KennyTV
# Nao removas o '%' se nao souberes exatamente o que estas a fazer
noPermission: "&cNao tens permissao para executar este comando."
maintenanceActivated: "&8[&cManutencao&8] &6Manutencao esta agora ativada!"
maintenanceDeactivated: "&8[&cManutencao&8] &6Manutencao esta agora desativada!"
alreadyEnabled: "&8[&cManutencao&8] &cManutencao ja esta ativada!"
alreadyDisabled: "&8[&cManutencao&8] &cManutencao ja esta desativada!"
helpUsage: "&8[&cManutencao&8] &c/maintenance help <pagina>"
helpPageNotFound: "&8[&eManutencao&8] &cNao existe nenhuma pagina com esse numero!"
endtimerBroadcast: "&8[&cManutencao&8] &7Manutencao vai ser desativada em &6%TIME%&7"
endtimerStarted: "&8[&cManutencao&8] &aTemporizador: &7Manutencao vai ser desativada em &6%TIME%&7"
endtimerUsage: "&8&8[&cManutencao&8] &c/maintenance endtimer <minutos>"
starttimerBroadcast: "&8[&cManutencao&8] &7Manutencao vai ser ativada em &6%TIME%&7"
starttimerStarted: "&8[&cManutencao&8] &7Manutencao vai ser ativada em &6%TIME%&7"
starttimerUsage: "&8[&cManutencao&8] &c/maintenance starttimer <minutos>"
timerAlreadyRunning: "&8[&cManutencao&8] &cO Timer ja esta a decorrer!"
timerNotRunning: "&8[&cManutencao&8] &cO Timer nao esta a decorrer!"
timerCancelled: "&8[&cManutencao&8] &cO Timer foi cancelado!"
timerTooLong: "&8[&cManutencao&8] &cO numero tem de ser menor que 40320 (28 dias)!"
joinNotification: "&8[&cManutencao&8] &e%PLAYER% &ctentou entrar no servidor."
motdList: "&8[&cManutencao&8] &7Lista de motds de manutencao:"
reload: "&8[&cManutencao&8] &aReloaded config, whitelistedplayers, linguagem e icon de manutencao."
removedMotd: "&8[&cManutencao&8] &aRemovida motd numero %INDEX%."
removeMotdError: "&8[&cManutencao&8] &cSo tens uma motd, entao nao podes remover esta!"
removeMotdUsage: "&8[&cManutencao&8] &c/maintenance removemotd <index>"
setMotd: setMotd: "&8[&eManutencao&8] &aLinha %LINE% do %INDEX%. Motd de manutencao %MOTD%"
setMotdUsage: "&8[&cManutencao&8] &c/maintenance setmotd <index> <1/2> <message>"
setMotdIndexError: "&8[&cManutencao&8] §cTens atualmente %MOTDS% motds, entao escolhe um numero entre 1 e %NEWAMOUNT%."
setMotdLineError: "&8[&cManutencao&8] &cO segundo argumento tem de ser na linha (1 ou 2)!"
updateDownloading: "&8[&cManutencao&8] &c&lDownloading update..."
updateFailed: "&8[&cManutencao&8] &4&lUpdate falhado!"
updateFinished: "&8[&cManutencao&8] &a&lO update foi feito com sucesso! Reinicia o servidor paa evitar erros e acabar a atualizacao"
whitelistedPlayers: "&8[&cManutencao&8] &6Whitelisted players para a manutencao:"
whitelistedPlayersFormat: "&8- &e%NAME% &8(&7%UUID%&8)"
whitelistAdded: "&8[&cManutencao&8] &aAdicionado &b%PLAYER% &ana whitelist!"
whitelistAlreadyAdded: "&8[&cManutencao&8] &b%PLAYER% &cja esta na whitelist!"
whitelistRemoved: "&8[&cManutencao&8] &b%PLAYER% &aremovido da whitelist!"
whitelistNotFound: "&8[&cManutencao&8] &cEste jogador nao esta na whitelist!"
whitelistEmtpy: "&8[&cManutencao&8] &cA whitelist esta vazia! Usa '/maintenance add <player>' para adicionar alguem!"
whitelistEmptyDefault: "&8[&cManutencao&8] &cUsa '/maintenance add <player>' para adicionar alguem. Ou entao adicona o uuid do jogador no ficheiro WhitelistedPlayers.yml"
playerNotFound: "&8[&cManutencao&8] &cNinguem com esse nome se registou no servidor."
playerNotOnline: "&8[&cManutencao&8] &cNao esta ninguem online com esse nome"
second: "segundo"
seconds: "segundos"
minute: "minuto"
minutes: "minutos"
hour: "hora"
hours: "horas"
# Algumas mensagens para o Bungee, ignora-as se estas a usar Spigot
serverNotFound: "&8[&cManutencao&8] &cServidor nao encontrado!"
singleEndtimerBroadcast: "&8[&cManutencao&8] &7Manutencao no %SERVER% vai ser desativada em &6%TIME%&7."
singleEndtimerUsage: "&8[&cManutencao&8] &c/maintenance endtimer <servidor> <minutos>"
singleStarttimerBroadcast: "&8[&cManutencao&8] &7Manutencao no %SERVER% vai ser ativada em &6%TIME%&7."
singleStarttimerUsage: "&8[&cManutencao&8] &c/maintenance starttimer <servidor> <minutos>"
singleMaintenanceKick: "&8[&cManutencao&8] &cO %SERVER% esta em manutencao! Tente mais tarde!"
singleMaintenanceKickComplete: "&cO %SERVER% esta em manutencao!%NEWLINE%&cTente mais tarde!"
singleMaintenanceActivated: "&8[&cManutencao&8] &6Manutencao esta agora ativada no &e%SERVER%&6."
singleMaintenanceDeactivated: "&8[&cManutencao&8] &6Manutencao esta agora desativada no &e%SERVER%&6."
singleServerAlreadyEnabled: "&8[&cManutencao&8] &cManutencao ja esta ativada no &e%SERVER%&c!"
singleServerAlreadyDisabled: "&8[&cManutencao&8] &cManutencao ja esta desativada no &e%SERVER%&c!"
singleServerMaintenanceList: "&8[&cManutencao&8] &7Servidores com manutencao ativa:"
singleServerMaintenanceListEmpty: "&8[&cManutencao&8] &7Nao existem servidores com a manutencao ativa."
-35
View File
@@ -1,35 +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>
<artifactId>maintenance-base</artifactId>
<groupId>eu.kennytv</groupId>
<version>2.5.2</version>
</parent>
<artifactId>maintenance-parent</artifactId>
<name>Maintenance</name>
<dependencies>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-core</artifactId>
<version>${parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-bungee</artifactId>
<version>${parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>eu.kennytv</groupId>
<artifactId>maintenance-spigot</artifactId>
<version>${parent.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -1,25 +0,0 @@
package eu.kennytv.maintenance.spigot;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.IMaintenanceBase;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
public final class MaintenanceSpigotBase extends JavaPlugin implements IMaintenanceBase {
private IMaintenance maintenance;
@Override
public void onEnable() {
maintenance = new MaintenanceSpigotPlugin(this);
}
File getPluginFile() {
return getFile();
}
@Override
public IMaintenance getApi() {
return maintenance;
}
}
@@ -1,118 +0,0 @@
package eu.kennytv.maintenance.spigot;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.ISettings;
import eu.kennytv.maintenance.api.spigot.MaintenanceSpigotAPI;
import eu.kennytv.maintenance.core.MaintenanceModePlugin;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import eu.kennytv.maintenance.core.util.ServerType;
import eu.kennytv.maintenance.spigot.command.MaintenanceSpigotCommand;
import eu.kennytv.maintenance.spigot.listener.PlayerLoginListener;
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;
import java.util.logging.Logger;
/**
* @author KennyTV
* @since 2.0
*/
public final class MaintenanceSpigotPlugin extends MaintenanceModePlugin {
private final MaintenanceSpigotBase plugin;
private final SettingsSpigot settings;
MaintenanceSpigotPlugin(final MaintenanceSpigotBase plugin) {
super("§8[§eMaintenanceSpigot§8] ", plugin.getDescription().getVersion(), ServerType.SPIGOT);
this.plugin = plugin;
settings = new SettingsSpigot(this, plugin);
plugin.getLogger().info("Plugin by KennyTV");
plugin.getLogger().info(getUpdateMessage());
plugin.getCommand("maintenancespigot").setExecutor(new MaintenanceSpigotCommand(this, settings));
final PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new PlayerLoginListener(this, settings), plugin);
new MetricsLite(plugin);
// ServerListPlus integration
final Plugin serverListPlus = pm.getPlugin("ServerListPlus");
if (serverListPlus != null) {
serverListPlusHook = new ServerListPlusHook(((ServerListPlusPlugin) serverListPlus).getCore());
serverListPlusHook.setEnabled(!settings.isMaintenance());
plugin.getLogger().info("Enabled ServerListPlus integration!");
}
}
@Override
public void setMaintenance(final boolean maintenance) {
settings.setMaintenance(maintenance);
settings.setToConfig("enable-maintenance-mode", maintenance);
settings.saveConfig();
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.getMessage("maintenanceActivated"));
} else
getServer().broadcastMessage(settings.getMessage("maintenanceDeactivated"));
}
@Override
public int startMaintenanceRunnable(final Runnable runnable) {
return getServer().getScheduler().scheduleSyncRepeatingTask(plugin, runnable, 0, 20);
}
@Override
public void async(final Runnable runnable) {
getServer().getScheduler().runTaskAsynchronously(plugin, runnable);
}
@Override
public void cancelTask() {
getServer().getScheduler().cancelTask(taskId);
runnable = null;
taskId = 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();
}
@Override
public Logger getLogger() {
return plugin.getLogger();
}
}
@@ -1,186 +0,0 @@
package eu.kennytv.maintenance.spigot;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.listener.IPingListener;
import eu.kennytv.maintenance.spigot.listener.ServerInfoPacketListener;
import eu.kennytv.maintenance.spigot.listener.ServerListPingListener;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.PluginManager;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import java.util.UUID;
public final class SettingsSpigot extends Settings {
private final MaintenanceSpigotBase plugin;
private final IPingListener pingListener;
private FileConfiguration config;
private FileConfiguration language;
private FileConfiguration whitelist;
SettingsSpigot(final MaintenanceSpigotPlugin pl, final MaintenanceSpigotBase plugin) {
super(pl);
this.plugin = plugin;
final PluginManager pm = plugin.getServer().getPluginManager();
if (pm.getPlugin("ProtocolLib") != null) {
final ServerInfoPacketListener serverInfoListener = new ServerInfoPacketListener(plugin, this);
pm.registerEvents(serverInfoListener, plugin);
pingListener = serverInfoListener;
} else {
final ServerListPingListener listener = new ServerListPingListener(plugin, this);
pm.registerEvents(listener, plugin);
pingListener = listener;
}
if (!plugin.getDataFolder().exists())
plugin.getDataFolder().mkdirs();
createFile("spigot-config.yml");
createFile("WhitelistedPlayers.yml");
reloadConfigs();
}
private 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 createAndLoadLanguageFile() {
final File file = new File(plugin.getDataFolder(), "language-" + getLanguage() + ".yml");
if (!file.exists()) {
try (final InputStream in = plugin.getResource("language-" + getLanguage() + ".yml")) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
plugin.getLogger().warning("Unable to provide language " + getLanguage());
if (!languageName.equals("en")) {
plugin.getLogger().warning("Falling back to default language: en");
languageName = "en";
createAndLoadLanguageFile();
return;
}
}
}
try {
language = YamlConfiguration.loadConfiguration(new InputStreamReader(new FileInputStream(new File(plugin.getDataFolder(), "language-" + getLanguage() + ".yml")), StandardCharsets.UTF_8));
} catch (final IOException e) {
throw new RuntimeException("Unable to load Maintenance language file!", e);
}
}
@Override
public boolean updateExtraConfig() {
// Remove MySQL part from default config
/*if (configContains("mysql")) {
setToConfig("mysql", null);
return true;
}*/
return false;
}
@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() {
try {
config = YamlConfiguration.loadConfiguration(new InputStreamReader(new FileInputStream(new File(plugin.getDataFolder(), "spigot-config.yml")), StandardCharsets.UTF_8));
whitelist = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), "WhitelistedPlayers.yml"));
} catch (final IOException e) {
throw new RuntimeException("Unable to load Maintenance files!", e);
}
loadSettings();
createAndLoadLanguageFile();
}
@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 String getConfigString(final String path) {
final String s = config.getString(path);
if (s == null) {
plugin.getLogger().warning("The config is missing the following string: " + path);
return "null";
}
return s;
}
@Override
public String getMessage(final String path) {
final String s = language.getString(path);
if (s == null) {
plugin.getLogger().warning("The language file is missing the following string: " + path);
return "null";
}
return ChatColor.translateAlternateColorCodes('&', s);
}
@Override
public boolean getConfigBoolean(final String path) {
return config.getBoolean(path);
}
@Override
public List<Integer> getConfigIntList(final String path) {
return config.getIntegerList(path);
}
@Override
public List<String> getConfigList(final String path) {
return config.getStringList(path);
}
@Override
public void setToConfig(final String path, final Object var) {
config.set(path, var);
}
@Override
public boolean configContains(final String path) {
return config.contains(path);
}
@Override
public String getColoredString(final String message) {
return ChatColor.translateAlternateColorCodes('&', message);
}
@Override
public boolean reloadMaintenanceIcon() {
return pingListener.loadIcon();
}
}
@@ -1,83 +0,0 @@
package eu.kennytv.maintenance.spigot.command;
import eu.kennytv.maintenance.core.command.MaintenanceCommand;
import eu.kennytv.maintenance.core.util.SenderInfo;
import eu.kennytv.maintenance.spigot.MaintenanceSpigotPlugin;
import eu.kennytv.maintenance.spigot.SettingsSpigot;
import eu.kennytv.maintenance.spigot.util.BukkitSenderInfo;
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;
public final class MaintenanceSpigotCommand extends MaintenanceCommand implements CommandExecutor {
public MaintenanceSpigotCommand(final MaintenanceSpigotPlugin plugin, final SettingsSpigot settings) {
super(plugin, settings, "MaintenanceSpigot");
}
@Override
public boolean onCommand(final CommandSender sender, final Command cmd, final String s, final String[] args) {
execute(new BukkitSenderInfo(sender), args);
return true;
}
@Override
protected void addPlayerToWhitelist(final SenderInfo sender, final String name) {
final Player selected = Bukkit.getPlayer(name);
if (selected != null) {
if (settings.addWhitelistedPlayer(selected.getUniqueId(), selected.getName()))
sender.sendMessage(settings.getMessage("whitelistAdded").replace("%PLAYER%", selected.getName()));
else
sender.sendMessage(settings.getMessage("whitelistAlreadyAdded").replace("%PLAYER%", selected.getName()));
return;
}
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name);
if (!offlinePlayer.hasPlayedBefore()) {
sender.sendMessage(settings.getMessage("playerNotFound"));
return;
}
if (settings.addWhitelistedPlayer(offlinePlayer.getUniqueId(), offlinePlayer.getName()))
sender.sendMessage(settings.getMessage("whitelistAdded").replace("%PLAYER%", offlinePlayer.getName()));
else
sender.sendMessage(settings.getMessage("whitelistAlreadyAdded").replace("%PLAYER%", offlinePlayer.getName()));
}
@Override
protected void removePlayerFromWhitelist(final SenderInfo sender, final String name) {
final Player selected = Bukkit.getPlayer(name);
if (selected != null) {
if (settings.removeWhitelistedPlayer(selected.getUniqueId()))
sender.sendMessage(settings.getMessage("whitelistRemoved").replace("%PLAYER%", selected.getName()));
else
sender.sendMessage(settings.getMessage("whitelistNotFound"));
return;
}
final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name);
if (!offlinePlayer.hasPlayedBefore()) {
sender.sendMessage(settings.getMessage("playerNotFound"));
return;
}
if (settings.removeWhitelistedPlayer(offlinePlayer.getUniqueId()))
sender.sendMessage(settings.getMessage("whitelistRemoved").replace("%PLAYER%", offlinePlayer.getName()));
else
sender.sendMessage(settings.getMessage("whitelistNotFound"));
}
@Override
protected 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!");
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,34 +0,0 @@
package eu.kennytv.maintenance.spigot.listener;
import eu.kennytv.maintenance.core.listener.IPingListener;
import eu.kennytv.maintenance.spigot.MaintenanceSpigotBase;
import eu.kennytv.maintenance.spigot.SettingsSpigot;
import org.bukkit.event.Listener;
import org.bukkit.util.CachedServerIcon;
import javax.imageio.ImageIO;
import java.io.File;
public abstract class PingListenerBase implements IPingListener, Listener {
protected final MaintenanceSpigotBase plugin;
protected final SettingsSpigot settings;
protected CachedServerIcon serverIcon;
protected PingListenerBase(final MaintenanceSpigotBase plugin, final SettingsSpigot settings) {
this.plugin = plugin;
this.settings = settings;
}
@Override
public boolean loadIcon() {
try {
serverIcon = plugin.getServer().loadServerIcon(ImageIO.read(new File("maintenance-icon.png")));
} catch (final Exception e) {
plugin.getLogger().warning("Could not load 'maintenance-icon.png' - did you create one in your Spigot folder (not the plugins folder)?");
if (settings.debugEnabled())
e.printStackTrace();
return false;
}
return true;
}
}
@@ -1,70 +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.util.HashSet;
import java.util.Set;
import java.util.UUID;
public final class PlayerLoginListener implements Listener {
private final MaintenanceSpigotPlugin plugin;
private final SettingsSpigot settings;
private final Set<UUID> notifiedPlayers = new HashSet<>();
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.getMessage("joinNotification").replace("%PLAYER%", p.getName())));
return;
}
}
if (!p.hasPermission("maintenance.admin") || notifiedPlayers.contains(p.getUniqueId())) return;
plugin.async(() -> {
if (plugin.updateAvailable()) {
p.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + plugin.getNewestVersion() + "§c, you're on §a" + plugin.getVersion());
notifiedPlayers.add(p.getUniqueId());
try {
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 e) {
p.sendMessage(plugin.getPrefix() + "§cDownload it at: §6https://www.spigotmc.org/resources/maintenancemode.40699/");
}
}
});
}
}
@@ -1,72 +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 eu.kennytv.maintenance.core.listener.IPingListener;
import eu.kennytv.maintenance.spigot.MaintenanceSpigotBase;
import eu.kennytv.maintenance.spigot.SettingsSpigot;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.server.ServerListPingEvent;
import javax.imageio.ImageIO;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public final class ServerInfoPacketListener extends PingListenerBase {
//private WrappedServerPing.CompressedImage image;
public ServerInfoPacketListener(final MaintenanceSpigotBase base, final SettingsSpigot settings) {
super(base, settings);
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(base, ListenerPriority.HIGHEST,
PacketType.Status.Server.SERVER_INFO) {
@Override
public void onPacketSending(final PacketEvent event) {
if (!settings.isMaintenance()) return;
final WrappedServerPing ping = event.getPacket().getServerPings().read(0);
ping.setMotD(settings.getRandomPingMessage());
if (settings.hasCustomPlayerCountMessage()) {
ping.setVersionProtocol(0);
ping.setVersionName(settings.getPlayerCountMessage()
.replace("%ONLINE%", Integer.toString(base.getServer().getOnlinePlayers().size()))
.replace("%MAX%", Integer.toString(base.getServer().getMaxPlayers())));
}
final List<WrappedGameProfile> players = new ArrayList<>();
for (final String string : settings.getPlayerCountHoverMessage().split("%NEWLINE%"))
players.add(new WrappedGameProfile(UUID.randomUUID(), string));
ping.setPlayers(players);
//if (settings.hasCustomIcon() && image != null) ping.setFavicon(image);
}
});
}
@EventHandler(priority = EventPriority.HIGHEST)
public void serverListPing(final ServerListPingEvent event) {
if (settings.isMaintenance() && settings.hasCustomIcon() && serverIcon != null)
event.setServerIcon(serverIcon);
}
/*@Override
public boolean loadIcon() {
try {
image = WrappedServerPing.CompressedImage.fromPng(ImageIO.read(new File("maintenance-icon.png")));
} catch (final Exception e) {
pl.getLogger().warning("Could not load 'maintenance-icon.png' - did you create one in your Spigot folder (not the plugins folder)?");
if (pl.getApi().getSettings().debugEnabled())
e.printStackTrace();
return false;
}
return true;
}*/
}
@@ -1,25 +0,0 @@
package eu.kennytv.maintenance.spigot.listener;
import eu.kennytv.maintenance.spigot.MaintenanceSpigotBase;
import eu.kennytv.maintenance.spigot.SettingsSpigot;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.server.ServerListPingEvent;
public final class ServerListPingListener extends PingListenerBase {
public ServerListPingListener(final MaintenanceSpigotBase plugin, final SettingsSpigot settings) {
super(plugin, settings);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void serverListPing(final ServerListPingEvent event) {
if (!settings.isMaintenance()) return;
event.setMaxPlayers(0);
event.setMotd(settings.getRandomPingMessage());
if (settings.hasCustomIcon() && serverIcon != null)
event.setServerIcon(serverIcon);
}
}
@@ -1,40 +0,0 @@
package eu.kennytv.maintenance.spigot.util;
import eu.kennytv.maintenance.core.util.SenderInfo;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.UUID;
public final class BukkitSenderInfo implements SenderInfo {
private final CommandSender sender;
public BukkitSenderInfo(final CommandSender sender) {
this.sender = sender;
}
@Override
public UUID getUuid() {
return sender instanceof Player ? ((Player) 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 Player;
}
}
@@ -1,11 +0,0 @@
name: ${project.name}
version: ${project.version}
main: eu.kennytv.maintenance.spigot.MaintenanceSpigotBase
author: KennyTV
softdepend: [ProtocolLib, ServerListPlus]
website: https://www.spigotmc.org/resources/maintenancemode.40699/
commands:
maintenance:
description: Maintenance main-command
aliases: [maintenancespigot]
@@ -1,41 +0,0 @@
# MaintenanceSpigot Plugin by KennyTV
# Important note: To use this plugin to its full extend, it requires the plugin 'ProtocolLib'
# Also, configs are cool, which means after the first plugin save, all comments will vanish
# To still know what each field is for, check https://gist.github.com/KennyTV/a73f2aed1e278d4c927f9f6a3ef9fde2#file-spigot-config-yml
# Enables maintenance-mode.
enable-maintenance-mode: false
# The message shown in the multiplayer server list motd.
# If you put in multiple entries, one of them will be chosen randomly on every ping.
pingmessages:
- "&cMaintenance mode!%NEWLINE%&6We will be back soon!"
#- "Another entry"
# If set to true, the message below will be shown at the top right corner of the server in the serverlist,
# where the playercount would normally be displayed.
# If set to false, the normal playercount will be shown.
# Alternatively you can use '%ONLINE%' and '%MAX% if you want to include the playercount in a custom message (e.g. '&cMaintenance &7%ONLINE%&8/&7%MAX%').
enable-playercountmessage: true
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"
# Is shown when a player tries to join while maintenance is enabled and they don't have the permission to bypass it.
kickmessage: "&cThe server is currently under maintenance!%NEWLINE%Try again later!"
# If using the timer command: In what intervalls before enabling/disabling maintenance there will be a broadcast.
timer-broadcast-for-seconds: [1200, 900, 600, 300, 120, 60, 30, 20, 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
# If set to true, the server icon will be changed to maintenance-icon.png in the Bungee main/base-folder.
custom-maintenance-icon: false
# Changes the language of command feedback/messages.
# Currently available are: en (English), de (German), fr (French), pt (Portuguese)
language: en
Binary file not shown.
+32 -11
View File
@@ -1,16 +1,37 @@
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://github.com/KennyTV/Maintenance/workflows/Build/badge.svg)
[![GH Downloads](https://img.shields.io/github/downloads/KennyTV/Maintenance/total)](https://github.com/KennyTV/Maintenance/releases)
[![Discord](https://img.shields.io/discord/489135856284729384.svg?label=Discord&logo=discord&logoColor=fff)](https://discord.gg/vGCUzHq)
[![Twitter](https://img.shields.io/twitter/follow/KennyTVN.svg?label=Twitter)](https://twitter.com/KennyTVN)
Maintenance is probably the most customizable free maintenance plugin for your Minecraft server you can find. It runs on Spigot, BungeeCord, Sponge, as well as Velocity.
# MaintenanceMode-Issues
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
* Use PlaceholderAPI placeholders with the [**MaintenanceAddon**](https://github.com/KennyTV/Maintenance/wiki/MaintenanceAddon) (only for Bungee)
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
A full list of commands, permissions and configuration options can be found in the wiki listed below.
* [Wiki](https://github.com/KennyTV/Maintenance/wiki) (configuration, permissions, API usage)
* [Downloads](https://github.com/KennyTV/Maintenance/releases) (GitHub)
* [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)
* [PlaceholderAPI addon](https://github.com/KennyTV/Maintenance/wiki/MaintenanceAddon)
Issues can be created here: https://github.com/KennyTV/Maintenance/issues
Other forum threads
* [Spigot forums](https://www.spigotmc.org/resources/maintenance.40699/)
* [Ore/Sponge Forums](https://ore.spongepowered.org/KennyTV/Maintenance)
* [Velocity forums](https://forums.velocitypowered.com/t/maintenance/129)
### MaintenanceMode API
## 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).
There's no official maven 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. A rough documentation can be found here https://github.com/KennyTV/Maintenance/tree/master/Maintenance-API/src/main/java/eu/kennytv/maintenance/api
## Licence
When modifying the project's code, do that 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.5.2</version>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.6</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.13-SNAPSHOT</version>
<version>1.15-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<version>1.15.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,81 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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 eu.kennytv.maintenance.api.event.manager.IEventManager;
/**
* @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();
/**
* Returns the {@link IEventManager} instance to register listeners to maintenance events.
*
* @return {@link IEventManager} instance
*/
IEventManager getEventManager();
/**
* @return true if debug mode is enabled, currently only implemented on Bungee
*/
boolean isDebug();
/**
* Sets the debug mode.
*
* @param debug debug state
*/
void setDebug(boolean debug);
}
@@ -0,0 +1,33 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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();
}
@@ -1,3 +1,21 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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;
@@ -17,20 +35,31 @@ public interface ISettings {
boolean isMaintenance();
/**
* @return true if "send-join-notification" is set to true in the config
* @return value of the 'send-join-notification' config field
*/
boolean isJoinNotifications();
/**
* @return true if "custom-maintenance-icon" is set to true in the config
* @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();
/**
* Returns whether the uuid is whitelisted.
*
* @param uuid uuid of the player to check
* @return true if the uuid is whitelisted
*/
boolean isWhitelisted(UUID uuid);
/**
* Removes a player from the maintenance whitelist.
*
@@ -60,11 +89,14 @@ public interface ISettings {
boolean addWhitelistedPlayer(UUID uuid, String name);
/**
* Reloads the maintenance-icon.png image from the server folder.
*
* @return true if loading the image was successful
* Reloads maintenance-icon, config, language file and WhitelistedPlayers.
*/
boolean reloadMaintenanceIcon();
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-2021 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 com.google.common.base.Preconditions;
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("Maintenance");
Preconditions.checkNotNull(maintenance, "Could not get instance of Maintenance! Broken/custom build of the plugin?");
return (IMaintenanceProxy) ((IMaintenanceBase) maintenance).getApi();
}
}
@@ -0,0 +1,42 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.event;
import eu.kennytv.maintenance.api.event.manager.MaintenanceEvent;
/**
* Notification event fired when maintenance mode has been changed.
*
* @author KennyTV
* @since 3.0.1
*/
public final class MaintenanceChangedEvent implements MaintenanceEvent {
private final boolean maintenance;
public MaintenanceChangedEvent(final boolean maintenance) {
this.maintenance = maintenance;
}
/**
* @return true if maintenance has been enabled, false otherwise
*/
public boolean isMaintenance() {
return maintenance;
}
}
@@ -0,0 +1,34 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.event;
import eu.kennytv.maintenance.api.IMaintenance;
import eu.kennytv.maintenance.api.event.manager.MaintenanceEvent;
import eu.kennytv.maintenance.api.proxy.IMaintenanceProxy;
/**
* Notification event fired when Maintenance configuration is reloaded.
*
* @author KennyTV
* @see IMaintenance#isMaintenance() for the new maintenance status
* @see IMaintenanceProxy#getMaintenanceServers() for the new list of servers under maintenance
* @since 3.0.6
*/
public final class MaintenanceReloadedEvent implements MaintenanceEvent {
}
@@ -0,0 +1,36 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.event.manager;
/**
* Abstract class representing a maintenance eventlistener.
*
* @param <T> event to be listened to
* @author KennyTV
* @since 3.0.1
*/
public abstract class EventListener<T extends MaintenanceEvent> {
/**
* This method is to be overwritten and is called on the given event.
*
* @param event fired event
*/
public abstract void onEvent(final T event);
}
@@ -0,0 +1,41 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.event.manager;
/**
* @author KennyTV
* @since 3.0.1
*/
public interface IEventManager {
/**
* Registers an eventlistener for the given maintenance event.
*
* @param listener listener to register
* @param eventClass class of the event that should be registered
*/
void registerListener(EventListener listener, Class<? extends MaintenanceEvent> eventClass);
/**
* Fires a maintenance event.
*
* @param event event to fire
*/
void callEvent(MaintenanceEvent event);
}
@@ -0,0 +1,28 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.event.manager;
/**
* Dummy interface representing a maintenance event.
*
* @author KennyTV
* @since 3.0.1
*/
public interface MaintenanceEvent {
}
@@ -0,0 +1,57 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.event.proxy;
import eu.kennytv.maintenance.api.event.manager.MaintenanceEvent;
import eu.kennytv.maintenance.api.proxy.Server;
/**
* Notification event fired when maintenance mode has been changed on a proxied server.
*
* @author KennyTV
* @since 3.0.1
*/
public final class ServerMaintenanceChangedEvent implements MaintenanceEvent {
private final Server server;
private final boolean maintenance;
public ServerMaintenanceChangedEvent(final Server server, final boolean maintenance) {
this.server = server;
this.maintenance = maintenance;
}
/**
* Returns wrapped server object for the server.
* <br>
* This does not necessarily have to be an existing server:
* If maintenance is disabled on a *previously* registered server, see {@link Server#isRegisteredServer()}.
*
* @return wrapped server object for the server
*/
public Server getServer() {
return server;
}
/**
* @return true if maintenance has been enabled on the server, false otherwise
*/
public boolean isMaintenance() {
return maintenance;
}
}
@@ -0,0 +1,71 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
/**
* @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
*/
@Nullable
Server getServer(String server);
/**
* @return immutable set with names of all proxied server that are currently under maintenance
*/
Set<String> getMaintenanceServers();
}
@@ -0,0 +1,54 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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);
/**
* Returns whether the server is registered under the proxy.
* This will only ever be false if maintenance is disabled on a *previously* registered server.
*
* @return whether the server is registered under the proxy
*/
boolean isRegisteredServer();
}
@@ -0,0 +1,49 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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 com.google.common.base.Preconditions;
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("Maintenance");
Preconditions.checkNotNull(maintenance, "Could not get instance of Maintenance! Broken/custom build of the plugin?");
return ((IMaintenanceBase) maintenance).getApi();
}
}
@@ -0,0 +1,51 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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 com.google.common.base.Preconditions;
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("maintenance");
Preconditions.checkArgument(container.isPresent() && container.get().getInstance().isPresent(),
"Could not get instance of Maintenance! Broken/custom build of the plugin?");
return (IMaintenance) container.get().getInstance().get();
}
}
+62
View File
@@ -0,0 +1,62 @@
<?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.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.6</version>
</parent>
<artifactId>maintenance-build</artifactId>
<name>Maintenance</name>
<dependencies>
<!-- Also includes maintenance-core and maintenance-core-proxy modules -->
<dependency>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-bungee</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-spigot</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<!-- Don't include Sponge and Velocity in main jar anymore, counters relocation errors and minimizes shading -->
</dependencies>
<!-- Needed to relocate stuff in Bungee module, but not in the core one -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>org.slf4j</pattern>
<shadedPattern>eu.kennytv.lib.slf4j</shadedPattern>
</relocation>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>eu.kennytv.lib.hikari</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
+67
View File
@@ -0,0 +1,67 @@
<?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.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.6</version>
</parent>
<artifactId>maintenance-bungee</artifactId>
<name>MaintenanceBungee</name>
<dependencies>
<dependency>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-core-proxy</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<!-- Only compile slf4j on Bungee (not Velocity) to prevent relocation errors -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.16-R0.4-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- Needed to relocate stuff in Bungee module, but not in the core one -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>org.slf4j</pattern>
<shadedPattern>eu.kennytv.lib.slf4j</shadedPattern>
</relocation>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>eu.kennytv.lib.hikari</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,48 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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 MaintenanceBungeePlugin maintenance;
@Override
public void onEnable() {
maintenance = new MaintenanceBungeePlugin(this);
}
@Override
public void onDisable() {
maintenance.disable();
}
@Override
public IMaintenance getApi() {
return maintenance;
}
File getPluginFile() {
return getFile();
}
}
@@ -0,0 +1,266 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.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 org.jetbrains.annotations.Nullable;
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 ProxyPingListener(this, settingsProxy));
pm.registerListener(plugin, new ServerConnectListener(this, settingsProxy));
commandManager = new MaintenanceBungeeCommand(this, settingsProxy);
pm.registerCommand(plugin, new MaintenanceBungeeCommandBase(commandManager));
continueLastEndtimer();
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(serverInfo.getName());
}
@Override
protected void kickPlayersFromProxy() {
for (final ProxiedPlayer p : getProxy().getPlayers()) {
if (!hasPermission(p, "bypass") && !settingsProxy.isWhitelisted(p.getUniqueId())) {
p.disconnect(settingsProxy.getKickMessage());
}
}
}
@Override
protected void kickPlayers(final Server server, final Server fallback) {
// Kick players from a proxied server
final ServerInfo fallbackServer = fallback != null ? ((BungeeServer) fallback).getServer() : null;
final boolean checkForFallback = fallbackServer != null && !isMaintenance(fallback);
for (final ProxiedPlayer player : ((BungeeServer) server).getServer().getPlayers()) {
if (!hasPermission(player, "bypass") && !settingsProxy.isWhitelisted(player.getUniqueId())) {
if (checkForFallback && fallbackServer.canAccess(player)) {
player.sendMessage(settingsProxy.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName()));
player.connect(fallbackServer);
} else {
player.disconnect(settingsProxy.getFullServerKickMessage(server.getName()));
}
} else {
player.sendMessage(settingsProxy.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName()));
}
}
}
@Override
protected void kickPlayersTo(final Server server) {
// Kick all players to a single waiting server
final ServerInfo serverInfo = ((BungeeServer) server).getServer();
// Notifications done in global method
for (final ProxiedPlayer player : getProxy().getPlayers()) {
if (hasPermission(player, "bypass") || settingsProxy.isWhitelisted(player.getUniqueId())) continue;
if (player.getServer() != null && player.getServer().getInfo().getName().equals(serverInfo.getName()))
continue;
if (serverInfo.canAccess(player) && !isMaintenance(serverInfo)) {
player.sendMessage(settingsProxy.getMessage("sentToWaitingServer").replace("%SERVER%", server.getName()));
player.connect(serverInfo);
} else {
player.disconnect(settingsProxy.getKickMessage());
}
}
}
@Override
public Task startMaintenanceRunnable(final Runnable runnable) {
return new BungeeTask(getProxy().getScheduler().schedule(plugin, runnable, 0, 1, TimeUnit.SECONDS).getId());
}
@Override
@Nullable
public Server getServer(final String server) {
final ServerInfo serverInfo = getProxy().getServerInfo(server);
return serverInfo != null ? new BungeeServer(serverInfo) : null;
}
@Override
@Nullable
public SenderInfo getOfflinePlayer(final String name) {
final ProxiedPlayer player = getProxy().getPlayer(name);
return player != null ? new BungeeSenderInfo(player) : null;
}
@Override
@Nullable
public SenderInfo getOfflinePlayer(final UUID uuid) {
final ProxiedPlayer player = getProxy().getPlayer(uuid);
return player != null ? new BungeeSenderInfo(player) : null;
}
@Override
@Nullable
public String getServerNameOf(final SenderInfo sender) {
final ProxiedPlayer player = getProxy().getPlayer(sender.getUuid());
if (player == null || player.getServer() == null) return null;
return 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
protected int getOnlinePlayers() {
return getProxy().getOnlineCount();
}
@Override
protected int getMaxPlayers() {
return getProxy().getConfig().getPlayerLimit();
}
@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,83 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.chat.ClickEvent;
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 java.util.ArrayList;
import java.util.List;
import java.util.Map;
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) {
final List<String> list = new ArrayList<>();
for (final Map.Entry<String, ServerInfo> entry : plugin.getProxy().getServers().entrySet()) {
final String serverName = entry.getValue().getName();
if (entry.getKey().toLowerCase().startsWith(s) && !plugin.getSettingsProxy().getMaintenanceServers().contains(serverName)) {
list.add(serverName);
}
}
return list;
}
@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() {
final List<String> list = new ArrayList<>();
for (final ProxiedPlayer p : plugin.getProxy().getPlayers()) {
list.add(p.getName());
}
return list;
}
}
@@ -0,0 +1,49 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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", "maintenance.command", "maintenancebungee", "mt");
this.command = command;
}
@Override
public boolean hasPermission(final CommandSender sender) {
return sender.hasPermission("maintenance.admin") || sender.hasPermission("maintenance.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,66 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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;
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 = 80)
public void proxyPing(final ProxyPingEvent event) {
if (!settings.isMaintenance()) return;
final ServerPing ping = event.getResponse();
ServerPing.Players players = ping.getPlayers();
if (players == null) {
ping.setPlayers(players = new ServerPing.Players(0, 0, null));
}
if (settings.hasCustomPlayerCountMessage()) {
ping.setVersion(new ServerPing.Protocol(settings.getPlayerCountMessage()
.replace("%ONLINE%", Integer.toString(players.getOnline()))
.replace("%MAX%", Integer.toString(players.getMax())), 1));
}
ping.setDescription(settings.getRandomPingMessage());
final String[] split = settings.getPlayerCountHoverMessage().split("\n");
final ServerPing.PlayerInfo[] samplePlayers = new ServerPing.PlayerInfo[split.length];
for (int i = 0; i < split.length; i++) {
samplePlayers[i] = new ServerPing.PlayerInfo(split[i], "");
}
players.setSample(samplePlayers);
if (settings.hasCustomIcon() && plugin.getFavicon() != null) {
ping.setFavicon(plugin.getFavicon());
}
}
}
@@ -0,0 +1,119 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.api.proxy.Server;
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
import eu.kennytv.maintenance.bungee.util.BungeeSenderInfo;
import eu.kennytv.maintenance.bungee.util.BungeeServer;
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
import eu.kennytv.maintenance.core.proxy.listener.ProxyJoinListenerBase;
import eu.kennytv.maintenance.core.proxy.util.ServerConnectResult;
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.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;
import net.md_5.bungee.event.EventPriority;
public final class ServerConnectListener extends ProxyJoinListenerBase implements Listener {
private final MaintenanceBungeePlugin plugin;
public ServerConnectListener(final MaintenanceBungeePlugin plugin, final SettingsProxy settings) {
super(plugin, settings);
this.plugin = plugin;
}
@EventHandler
public void initialServerConnect(final ServerConnectEvent event) {
// Global maintenance check
if (event.isCancelled() || event.getReason() != ServerConnectEvent.Reason.JOIN_PROXY) return;
final BungeeSenderInfo sender = new BungeeSenderInfo(event.getPlayer());
if (plugin.isDebug()) {
plugin.getLogger().info("Join permission check for " + event.getPlayer().getName()
+ " - Permission: " + sender.hasMaintenancePermission("bypass") + ", whitelist: " + settings.isWhitelisted(sender.getUuid()));
}
if (shouldKick(sender)) {
final Server waitingServer = shouldConnectToWaitingServer(sender);
if (waitingServer != null) {
event.setTarget(((BungeeServer) waitingServer).getServer());
sender.sendMessage(settings.getMessage("sentToWaitingServer"));
if (plugin.isDebug()) {
plugin.getLogger().info("Join to waiting server for " + event.getPlayer().getName());
}
return;
}
event.setCancelled(true);
event.getPlayer().disconnect(settings.getKickMessage());
if (settings.isJoinNotifications()) {
broadcastJoinNotification(sender.getName());
}
}
}
@EventHandler(priority = EventPriority.HIGH)
public void serverConnect(final ServerConnectEvent event) {
// Server specific maintenance check
if (event.isCancelled()) return;
final ProxiedPlayer player = event.getPlayer();
final boolean normalServerConnect = 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;
final ServerConnectResult connectResult = serverConnect(new BungeeSenderInfo(player), new BungeeServer(event.getTarget()), normalServerConnect);
if (plugin.isDebug()) {
plugin.getLogger().info("Connectresult for " + player.getName() + " to " + event.getTarget().getName() + ": " + connectResult);
}
if (connectResult.isCancelled()) {
event.setCancelled(true);
// Player has no server to connect to
if (player.getServer() == null) {
player.disconnect(settings.getKickMessage());
}
} else if (connectResult.getTarget() != null) {
event.setTarget(((BungeeServer) connectResult.getTarget()).getServer());
}
}
@Override
protected void broadcastJoinNotification(final String name) {
sendJoinMessage(ProxyServer.getInstance().getPlayers(), name);
}
@Override
protected void broadcastJoinNotification(final String name, final Server server) {
sendJoinMessage(((BungeeServer) server).getServer().getPlayers(), name);
}
private void sendJoinMessage(final Iterable<ProxiedPlayer> players, final String name) {
final BaseComponent[] message = TextComponent.fromLegacyText(settings.getMessage("joinNotification").replace("%PLAYER%", name));
for (final ProxiedPlayer player : players) {
if (plugin.hasPermission(player, "joinnotification")) {
player.sendMessage(message);
}
}
}
}
@@ -23,6 +23,7 @@ import java.util.zip.GZIPOutputStream;
public final class MetricsLite {
public static final int B_STATS_VERSION = 1;
private static final int PLUGIN_ID = 742;
private static final String URL = "https://bStats.org/submitData/bungeecord";
private final Plugin plugin;
private boolean enabled;
@@ -75,10 +76,12 @@ public final class MetricsLite {
public JsonObject getPluginData() {
final JsonObject data = new JsonObject();
final String pluginName = plugin.getDescription().getName();
//final String pluginName = plugin.getDescription().getName();
final String pluginName = "MaintenanceBungee"; // I cut off the suffix, not sure how bStats would like the name change
final String pluginVersion = plugin.getDescription().getVersion();
data.addProperty("pluginName", pluginName);
data.addProperty("id", PLUGIN_ID);
data.addProperty("pluginVersion", pluginVersion);
final JsonArray customCharts = new JsonArray();
@@ -92,8 +95,7 @@ public final class MetricsLite {
}
private JsonObject getServerData() {
int playerAmount = plugin.getProxy().getOnlineCount();
playerAmount = playerAmount > 500 ? 500 : playerAmount;
final int playerAmount = Math.min(plugin.getProxy().getOnlineCount(), 500);
final int onlineMode = plugin.getProxy().getConfig().isOnlineMode() ? 1 : 0;
final String bungeecordVersion = plugin.getProxy().getVersion();
final int managedServers = plugin.getProxy().getServers().size();
@@ -148,9 +150,9 @@ public final class MetricsLite {
}
private void loadConfig() throws IOException {
final Path configPath = plugin.getDataFolder().toPath().getParent().resolve("bStats");
configPath.toFile().mkdirs();
final File configFile = new File(configPath.toFile(), "config.yml");
final File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
bStatsFolder.mkdirs();
final File configFile = new File(bStatsFolder, "config.yml");
if (!configFile.exists()) {
writeFile(configFile,
"#bStats collects some data for plugin authors like how many servers are using their plugins.",
@@ -158,7 +160,7 @@ 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().toString() + "\"",
"serverUuid: \"" + UUID.randomUUID() + "\"",
"logFailedRequests: false",
"logSentData: false",
"logResponseStatusText: false");
@@ -200,10 +202,7 @@ public final class MetricsLite {
if (!file.exists()) {
return null;
}
try (
final FileReader fileReader = new FileReader(file);
final BufferedReader bufferedReader = new BufferedReader(fileReader);
) {
try (final BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
return bufferedReader.readLine();
}
}
@@ -212,10 +211,7 @@ public final class MetricsLite {
if (!file.exists()) {
file.createNewFile();
}
try (
final FileWriter fileWriter = new FileWriter(file);
final BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)
) {
try (final BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file))) {
for (final String line : lines) {
bufferedWriter.write(line);
bufferedWriter.newLine();
@@ -228,7 +224,7 @@ public final class MetricsLite {
throw new IllegalArgumentException("Data cannot be null");
}
if (logSentData) {
plugin.getLogger().info("Sending data to bStats: " + data.toString());
plugin.getLogger().info("Sending data to bStats: " + data);
}
final HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
@@ -244,22 +240,19 @@ public final class MetricsLite {
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
connection.setDoOutput(true);
final DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.write(compressedData);
outputStream.flush();
outputStream.close();
try (final DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.write(compressedData);
}
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);
try (final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
}
bufferedReader.close();
plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString());
plugin.getLogger().info("Sent data to bStats and received response: " + builder);
} else {
connection.getInputStream().close();
}
@@ -270,9 +263,9 @@ public final class MetricsLite {
return null;
}
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes(StandardCharsets.UTF_8));
gzip.close();
try (final GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
gzip.write(str.getBytes(StandardCharsets.UTF_8));
}
return outputStream.toByteArray();
}
@@ -0,0 +1,77 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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 eu.kennytv.maintenance.core.proxy.util.ProxySenderInfo;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.Connection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.UUID;
public final class BungeeSenderInfo implements ProxySenderInfo {
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);
}
@Override
public boolean canAccess(final Server server) {
return ((BungeeServer) server).getServer().canAccess(sender);
}
@Override
public void disconnect(final String message) {
if (sender instanceof Connection) {
((Connection) sender).disconnect(message);
}
}
}
@@ -0,0 +1,60 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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;
import net.md_5.bungee.api.connection.ProxiedPlayer;
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);
for (final ProxiedPlayer p : server.getPlayers()) {
p.sendMessage(s);
}
}
@Override
public boolean isRegisteredServer() {
return true;
}
public ServerInfo getServer() {
return server;
}
}
@@ -0,0 +1,35 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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: Maintenance
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/
+36
View File
@@ -0,0 +1,36 @@
<?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.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.6</version>
</parent>
<artifactId>maintenance-core-proxy</artifactId>
<name>MaintenanceCoreProxy</name>
<dependencies>
<dependency>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-core</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.2</version>
<scope>compile</scope>
<!-- Shade slf4j specifically and only in the Bungee module to prevent issues -->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,182 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.event.proxy.ServerMaintenanceChangedEvent;
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.runnable.SingleMaintenanceScheduleRunnable;
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 org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @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 disable() {
super.disable();
if (settingsProxy.getMySQL() != null) {
settingsProxy.getMySQL().close();
}
}
@Override
public void setMaintenance(final boolean maintenance) {
if (settingsProxy.hasMySQL()) {
settingsProxy.setMaintenanceToSQL(maintenance);
}
super.setMaintenance(maintenance);
}
@Override
public boolean isMaintenance(final Server server) {
return settingsProxy.isMaintenance(server.getName());
}
@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 == null) return;
// Skip to the even fire for dummy servers
if (server.isRegisteredServer()) {
if (maintenance) {
final Server fallback = 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!");
}
}
kickPlayers(server, fallback);
} else {
server.broadcast(settingsProxy.getMessage("singleMaintenanceDeactivated").replace("%SERVER%", server.getName()));
}
cancelSingleTask(server);
}
eventManager.callEvent(new ServerMaintenanceChangedEvent(server, maintenance));
}
@Override
public boolean isServerTaskRunning(final Server server) {
return serverTasks.containsKey(server.getName());
}
@Override
public Set<String> getMaintenanceServers() {
return Collections.unmodifiableSet(settingsProxy.getMaintenanceServers());
}
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 long duration, final TimeUnit unit, final boolean enable) {
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, settingsProxy, (int) unit.toSeconds(duration), enable, server);
serverTasks.put(server.getName(), runnable.getTask());
return runnable;
}
public MaintenanceRunnableBase scheduleSingleMaintenanceRunnable(final Server server, final long duration, final long maintenanceDuration, final TimeUnit unit) {
final MaintenanceRunnableBase runnable = new SingleMaintenanceScheduleRunnable(this, settingsProxy,
(int) unit.toSeconds(duration), (int) unit.toSeconds(maintenanceDuration), server);
serverTasks.put(server.getName(), runnable.getTask());
return runnable;
}
@Override
@Nullable
public List<String> getMaintenanceServersDump() {
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;
}
@Override
protected void kickPlayers() {
// Send players to waiting server is set
if (settingsProxy.getWaitingServer() != null) {
final Server waitingServer = getServer(settingsProxy.getWaitingServer());
if (waitingServer != null) {
kickPlayersTo(waitingServer);
return;
}
}
// If not set, kick players from proxy
kickPlayersFromProxy();
}
public SettingsProxy getSettingsProxy() {
return settingsProxy;
}
@Nullable
public abstract String getServerNameOf(SenderInfo sender);
protected abstract void kickPlayers(Server server, Server fallback);
protected abstract void kickPlayersTo(Server server);
protected abstract void kickPlayersFromProxy();
}
@@ -0,0 +1,269 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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 org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public final class SettingsProxy extends Settings {
private final MaintenanceProxyPlugin proxyPlugin;
private Set<String> maintenanceServers;
private List<String> fallbackServers;
private String waitingServer;
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.proxyPlugin = plugin;
}
private void setupMySQL() throws Exception {
plugin.getLogger().info("Trying to open database connection... (also, you can simply ignore the SLF4J soft-warning if it shows up)");
final ConfigSection section = config.getSection("mysql");
if (section == null) {
plugin.getLogger().warning("Section missing: mysql");
return;
}
mySQL = new MySQL(plugin.getLogger(),
section.getString("host"),
section.getInt("port"),
section.getString("username"),
section.getString("password"),
section.getString("database"),
section.getBoolean("use-ssl", true));
// 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;
plugin.getLogger().info("Done!");
}
@Override
protected void loadExtraSettings() {
// Open database connection if enabled and not already done
if (!hasMySQL() && config.getBoolean("mysql.use-mysql")) {
try {
setupMySQL();
} catch (final Exception e) {
mySQL = null;
plugin.getLogger().warning("Error while trying do open database connection!");
e.printStackTrace();
}
}
final Object fallback = config.getObject("fallback");
fallbackServers = fallback instanceof String ? Collections.singletonList((String) fallback) : config.getStringList("fallback");
waitingServer = config.getString("waiting-server", "");
if (waitingServer.isEmpty() || waitingServer.equalsIgnoreCase("none")) {
waitingServer = null;
}
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) {
maintenance = databaseValue;
plugin.serverActions(maintenance);
}
lastMySQLCheck = System.currentTimeMillis();
}
return maintenance;
}
public boolean isMaintenance(final String serverName) {
if (hasMySQL() && System.currentTimeMillis() - lastServerCheck > millisecondsToCheck) {
final Set<String> databaseValue = loadMaintenanceServersFromSQL();
if (!maintenanceServers.equals(databaseValue)) {
// Enable maintenance on yet unlisted servers
for (final String s : databaseValue) {
if (!maintenanceServers.contains(s)) {
proxyPlugin.serverActions(proxyPlugin.getServer(s), true);
}
}
// Disable maintenance on now unlisted servers
for (final String s : maintenanceServers) {
if (!databaseValue.contains(s)) {
proxyPlugin.serverActions(proxyPlugin.getServer(s), false);
}
}
maintenanceServers = databaseValue;
}
lastServerCheck = System.currentTimeMillis();
}
return maintenanceServers.contains(serverName);
}
public String getServerKickMessage(final String server) {
String message = language.getString("singleMaintenanceKicks." + server);
if (message == null) {
message = getMessage("singleMaintenanceKick");
}
return plugin.replacePingVariables(message).replace("%SERVER%", server);
}
// Full = being kicked from the proxy, not just a proxied server
public String getFullServerKickMessage(final String server) {
String message = language.getString("singleMaintenanceKicksComplete." + server);
if (message == null) {
message = getMessage("singleMaintenanceKickComplete");
}
return plugin.replacePingVariables(message).replace("%SERVER%", server);
}
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) {
plugin.getLogger().warning("An error occured while trying to get the maintenance value from the database!");
e.printStackTrace();
}
}, "maintenance");
return databaseValue[0];
}
private void saveServersToConfig() {
config.set("proxied-maintenance-servers", new ArrayList<>(maintenanceServers));
saveConfig();
}
public Set<String> getMaintenanceServers() {
return maintenanceServers;
}
@Nullable
public Server getFallbackServer() {
for (final String fallbackServer : fallbackServers) {
final Server server = proxyPlugin.getServer(fallbackServer);
if (server != null && !isMaintenance(server.getName())) {
return server;
}
}
return null;
}
@Nullable
public String getWaitingServer() {
return waitingServer;
}
@Nullable
MySQL getMySQL() {
return mySQL;
}
}
@@ -0,0 +1,75 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.ArrayList;
import java.util.List;
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 SingleScheduleTimerCommand(plugin), "scheduletimer", "schedule");
add(new AbortSingleTimerCommand(plugin), "aborttimer", "abort");
}
@Override
public List<String> getMaintenanceServersCompletion(final String s) {
final List<String> list = new ArrayList<>();
for (final String server : settingsBungee.getMaintenanceServers()) {
if (server.toLowerCase().startsWith(s)) {
list.add(server);
}
}
return list;
}
public Server checkSingleTimerServerArg(final SenderInfo sender, final String serverName) {
final Server server = plugin.getServer(serverName);
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-2021 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) {
super(plugin, permission);
this.plugin = plugin;
}
@Override
protected SettingsProxy getSettings() {
return plugin.getSettingsProxy();
}
}
@@ -0,0 +1,73 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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);
}
@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(getHelpMessage());
}
@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,82 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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;
import java.util.concurrent.TimeUnit;
public final class SingleEndtimerCommand extends ProxyCommandInfo {
public SingleEndtimerCommand(final MaintenanceProxyPlugin plugin) {
super(plugin, null);
}
@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(getHelpMessage());
return;
}
if (!plugin.isMaintenance()) {
sender.sendMessage(getMessage("alreadyDisabled"));
return;
}
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), TimeUnit.MINUTES, 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(getHelpMessage());
return;
}
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, args[1]);
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]), TimeUnit.MINUTES, false);
sender.sendMessage(getMessage("endtimerStarted").replace("%TIME%", runnable.getTime()));
} else {
sender.sendMessage(getHelpMessage());
}
}
@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,84 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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;
import java.util.concurrent.TimeUnit;
public final class SingleScheduleTimerCommand extends ProxyCommandInfo {
public SingleScheduleTimerCommand(final MaintenanceProxyPlugin plugin) {
super(plugin, null);
}
@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 == 3) {
if (checkPermission(sender, "timer")) return;
if (plugin.getCommandManager().checkTimerArgs(sender, args[1])
|| plugin.getCommandManager().checkTimerArgs(sender, args[2], false)) {
sender.sendMessage(getHelpMessage());
return;
}
if (plugin.isMaintenance()) {
sender.sendMessage(getMessage("alreadyEnabled"));
return;
}
plugin.scheduleMaintenanceRunnable(Integer.parseInt(args[1]), Integer.parseInt(args[2]), TimeUnit.MINUTES);
sender.sendMessage(getMessage("starttimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
} else if (args.length == 4) {
if (checkPermission(sender, "singleserver.timer")) return;
if (plugin.getCommandManager().checkTimerArgs(sender, args[2], false)
|| plugin.getCommandManager().checkTimerArgs(sender, args[3], false)) {
sender.sendMessage(getHelpMessage());
return;
}
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, args[1]);
if (server == null) return;
if (plugin.isMaintenance(server)) {
sender.sendMessage(getMessage("singleServerAlreadyEnabled").replace("%SERVER%", server.getName()));
return;
}
final MaintenanceRunnableBase runnable = plugin.scheduleSingleMaintenanceRunnable(server, Integer.parseInt(args[2]), Integer.parseInt(args[3]), TimeUnit.MINUTES);
sender.sendMessage(getMessage("starttimerStarted").replace("%TIME%", runnable.getTime()));
} else {
sender.sendMessage(getHelpMessage());
}
}
@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,82 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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;
import java.util.concurrent.TimeUnit;
public final class SingleStarttimerCommand extends ProxyCommandInfo {
public SingleStarttimerCommand(final MaintenanceProxyPlugin plugin) {
super(plugin, null);
}
@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(getHelpMessage());
return;
}
if (plugin.isMaintenance()) {
sender.sendMessage(getMessage("alreadyEnabled"));
return;
}
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), TimeUnit.MINUTES, 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(getHelpMessage());
return;
}
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, args[1]);
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]), TimeUnit.MINUTES, true);
sender.sendMessage(getMessage("starttimerStarted").replace("%TIME%", runnable.getTime()));
} else {
sender.sendMessage(getHelpMessage());
}
}
@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,87 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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);
}
@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() || !server.getName().equals(plugin.getServerNameOf(sender))) {
sender.sendMessage(getMessage(maintenance ? "singleMaintenanceActivated" : "singleMaintenanceDeactivated").replace("%SERVER%", server.getName()));
}
} else {
sender.sendMessage(getMessage(maintenance ? "singleServerAlreadyEnabled" : "singleServerAlreadyDisabled").replace("%SERVER%", server.getName()));
}
} else {
sender.sendMessage(getHelpMessage());
}
}
@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,43 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (getSettings().getMaintenanceServers().isEmpty()) {
sender.sendMessage(getMessage("singleServerMaintenanceListEmpty"));
return;
}
sender.sendMessage(getMessage("singleServerMaintenanceList"));
for (final String server : getSettings().getMaintenanceServers()) {
sender.sendMessage("§8- §b" + server);
}
}
}
@@ -0,0 +1,122 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.listener;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.listener.JoinListenerBase;
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
import eu.kennytv.maintenance.core.proxy.util.ProxySenderInfo;
import eu.kennytv.maintenance.core.proxy.util.ServerConnectResult;
import eu.kennytv.maintenance.core.util.SenderInfo;
import org.jetbrains.annotations.Nullable;
public abstract class ProxyJoinListenerBase extends JoinListenerBase {
private static final ServerConnectResult ALLOWED = new ServerConnectResult(false);
private static final ServerConnectResult DENIED = new ServerConnectResult(true);
protected final MaintenanceProxyPlugin plugin;
protected final SettingsProxy settings;
private boolean warned;
protected ProxyJoinListenerBase(final MaintenanceProxyPlugin plugin, final SettingsProxy settings) {
super(plugin, settings);
this.plugin = plugin;
this.settings = settings;
}
/**
* @param sender joined player
* @param target target server
* @param normalServerConnect true if normal server connect, false if initial proxy join or kick
* @return connect result with data for further handling
*/
protected ServerConnectResult serverConnect(final ProxySenderInfo sender, final Server target, final boolean normalServerConnect) {
// Check waiting server for global maintenance
if (settings.isMaintenance()) {
if (sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.getUuid())) return ALLOWED;
final Server waitingServer = shouldConnectToWaitingServer(sender);
// Should never be null, but just in case
if (waitingServer == null) return DENIED;
// Player is connecting to the waiting server
if (target.getName().equals(waitingServer.getName())) return ALLOWED;
// Player already is on the waiting server
final String currentServer = plugin.getServerNameOf(sender);
if (waitingServer.getName().equals(currentServer)) {
sender.sendMessage(settings.getMessage("forceWaitingServer"));
return DENIED;
}
sender.sendMessage(settings.getMessage("sentToWaitingServer"));
return new ServerConnectResult(waitingServer);
}
// Single server maintenance
if (!settings.isMaintenance(target.getName())) return ALLOWED;
if (sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.getUuid())
|| sender.hasMaintenancePermission("singleserver.bypass." + target.getName().toLowerCase())) {
return ALLOWED;
}
if (settings.isJoinNotifications()) {
broadcastJoinNotification(sender.getName(), target);
}
if (normalServerConnect) {
sender.sendMessage(settings.getServerKickMessage(target.getName()));
return DENIED;
}
// If it's the initial proxy join or a kick from another server, go back to fallback server
final Server fallback = settings.getFallbackServer();
if (fallback == null || !sender.canAccess(fallback)) {
// Nothing to redirect to, player has to be kicked from the proxy
sender.disconnect(settings.getFullServerKickMessage(target.getName()));
if (!warned) {
plugin.getLogger().warning("Could not send player to the set fallback server; instead kicking player off the network!");
warned = true;
}
return DENIED;
} else {
return new ServerConnectResult(fallback);
}
}
/**
* To be called after {@link #shouldKick(SenderInfo, boolean)} to get the waiting server if present.
* Does not do any permission checks, they should be done separately!
*
* @param sender sender
* @return waiting server, null if player should be kicked
*/
@Nullable
protected Server shouldConnectToWaitingServer(final ProxySenderInfo sender) {
if (settings.getWaitingServer() == null) return null;
final Server waitingServer = plugin.getServer(settings.getWaitingServer());
if (waitingServer == null) return null;
if (!sender.canAccess(waitingServer) || settings.isMaintenance(waitingServer.getName())) return null;
return waitingServer;
}
protected abstract void broadcastJoinNotification(String name, Server server);
}
@@ -1,4 +1,22 @@
package eu.kennytv.maintenance.bungee.mysql;
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.mysql;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
@@ -8,19 +26,29 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
public final class MySQL {
private final Logger logger;
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) {
public MySQL(final Logger logger, final String hostname, final int port, final String username, final String password, final String database, final boolean useSSL) {
this.logger = logger;
final HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setMaximumPoolSize(10);
hikariConfig.addDataSourceProperty("serverName", hostname);
hikariConfig.addDataSourceProperty("user", username);
hikariConfig.addDataSourceProperty("password", password);
hikariConfig.addDataSourceProperty("url", "jdbc:mysql://" + hostname + ":" + port + "/" + database);
hikariConfig.setJdbcUrl("jdbc:mysql://" + hostname + ":" + port + "/" + database);
String urlProperty = "jdbc:mysql://" + hostname + ":" + port + "/" + database;
if (!useSSL) {
urlProperty += "?useSSL=false";
}
hikariConfig.addDataSourceProperty("url", urlProperty);
hikariConfig.setJdbcUrl(urlProperty);
hikariConfig.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
hikariDataSource = new HikariDataSource(hikariConfig);
}
@@ -37,7 +65,7 @@ public final class MySQL {
callback.accept(preparedStatement.executeUpdate());
}
} catch (final SQLException e) {
System.out.println("Error while executing update method: " + query);
logger.log(Level.SEVERE, "Error while executing update method: " + query);
e.printStackTrace();
}
}
@@ -56,7 +84,7 @@ public final class MySQL {
resultSet.close();
}
} catch (final SQLException e) {
System.out.println("Error while executing query method: " + query);
logger.log(Level.SEVERE, "Error while executing query method: " + query);
e.printStackTrace();
}
}
@@ -65,4 +93,8 @@ public final class MySQL {
executeUpdate(query, res -> {
}, objects);
}
public void close() {
hikariDataSource.close();
}
}
@@ -0,0 +1,54 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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 class SingleMaintenanceRunnable extends MaintenanceRunnableBase {
protected final Server server;
public SingleMaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final boolean enable, final Server server) {
super(plugin, settings, seconds, enable);
this.server = server;
}
@Override
protected void broadcast(final String message) {
server.broadcast(message);
}
@Override
protected void finish() {
((IMaintenanceProxy) plugin).setMaintenanceToServer(server, enable);
}
@Override
protected String getStartMessage() {
return settings.getMessage("singleStarttimerBroadcast").replace("%TIME%", getTime()).replace("%SERVER%", server.getName());
}
@Override
protected String getEndMessage() {
return settings.getMessage("singleEndtimerBroadcast").replace("%TIME%", getTime()).replace("%SERVER%", server.getName());
}
}
@@ -0,0 +1,41 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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.Server;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
import java.util.concurrent.TimeUnit;
public final class SingleMaintenanceScheduleRunnable extends SingleMaintenanceRunnable {
private final int maintenanceDuration;
public SingleMaintenanceScheduleRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final int maintenanceDuration, final Server server) {
super(plugin, settings, seconds, true, server);
this.maintenanceDuration = maintenanceDuration;
}
@Override
protected void finish() {
super.finish();
((MaintenanceProxyPlugin) plugin).startSingleMaintenanceRunnable(server, maintenanceDuration, TimeUnit.SECONDS, false);
}
}
@@ -0,0 +1,48 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018-2021 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(final String s) {
}
@Override
public boolean isRegisteredServer() {
return false;
}
}
Loaded 100 of 186 files, more files were not shown because too many files have changed in this diff. Show more