Compare commits

..
96 Commits
Author SHA1 Message Date
Nassim Jahnke c1a03a6733 3.0.7 Release 2021-08-17 12:58:42 +02:00
kennytv 92ab4574e8 Prepare for 3.0.7 Release 2021-08-17 12:57:36 +02:00
kennytv f81851ad9a Update copyright header, readme, and license format 2021-08-12 10:43:10 +02:00
kennytv 6fb153eb9c Remove debug command from help list 2021-08-08 12:54:57 +02:00
kennytv a6e7bfa793 Update workflow and dependencies 2021-08-07 12:37:18 +02:00
kennytv 75656be4f5 Add helpDump to language files 2021-07-23 10:26:44 +02:00
KennyTV f09f95549a Fix Velocity update message, update depend to 3.0.0-SNAPSHOT 2021-05-27 22:25:58 +02:00
KennyTV 78dc87e74a Remove that 2021-05-23 14:23:33 +02:00
KennyTV 3503d02501 Shade mysql connector in Velocity module
Fixes #61
2021-05-22 19:24:38 +02:00
KennyTV f8ea89b0b9 Update ProtocolLib Maven repo 2021-05-10 08:48:02 +02:00
KennyTV d0d672b76b Do offline web lookup in whitelist add on proxies 2021-05-08 09:49:23 +02:00
KennyTV 616d4c7aba Update changelog, update sponge repo url 2021-03-06 18:25:01 +01:00
KennyTV 4415d036a2 Have an extra broadcast key for schedule starts
Closes #58
2021-03-06 16:44:58 +01:00
KennyTV 1f70247c1d Add config options to dispatch commands on maintenance toggle 2021-03-06 16:02:09 +01:00
KennyTV 02ed575e3c Fix inverted if condition 2021-02-18 09:15:33 +01:00
KennyTV 4e005bca17 Add "enable-pingmessages" config option
Closes #57
2021-02-18 09:14:48 +01:00
Aurélien dcf61a4036 Update language-fr.yml (#56) 2021-02-17 10:48:35 +01:00
KennyTV 8e7b80bddf Bump version 3.0.7-SNAPSHOT 2021-02-17 10:47:56 +01:00
KennyTV 16775bda54 Update changelog 2021-02-17 10:30:28 +01:00
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
137 changed files with 3206 additions and 1313 deletions

No files matched your search

+63 -2
View File
@@ -1,7 +1,68 @@
# 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.
## Unreleased
---
## 3.0.7 - August 17th 2021
### Changed
* Bungee/Velocity: `/maintenance add <name>` now works for offline players as well
* Added config options `commands-on-maintenance-enable` and `commands-on-maintenance-disable` to define commands to be executed after maintenance has been toggled
* Added config option `enable-pingmessages` to can change whether a custom maintenance motd should be displayed during maintenance
* Added language fields `scheduletimerBroadcast` and `singleScheduletimerBroadcast` with the variables `%SERVER%`, `%TIME%`, and `%DURATION%` instead of using the normal starttimer broadcasts
### Fixed
* Fixed SQL loading issues on some platforms
* Fixed missing language key warning for the debug command
* Velocity: Fixed the update message
---
## 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.1.0](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
@@ -15,7 +76,7 @@ This file contains update logs for this project. The top may contain a `Unreleas
* 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.
* Fixed the config autoupdater when the config contained strings broken over multiple lines
---
## 3.0.2 - May 17th 2019
### Changed
+36
View File
@@ -0,0 +1,36 @@
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.6
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-maven-
- name: Set up JDK 11
uses: actions/setup-java@v2.1.0
with:
java-version: 11
distribution: 'adopt'
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Upload a Build Artifact
uses: actions/upload-artifact@v2.2.4
with:
name: MaintenanceFiles
path: |
**/Maintenance.jar
**/MaintenanceSpigot.jar
**/MaintenanceBungee.jar
**/MaintenanceVelocity.jar
**/MaintenanceSponge.jar
+2 -2
View File
@@ -1,5 +1,4 @@
.metadata
dependencies/
bin/
tmp/
*.tmp
@@ -92,4 +91,5 @@ $RECYCLE.BIN/
*.msm
*.msp
*.lnk
!MaintenanceAPI.jar
!MaintenanceAPI.jar
**/src/test/resources/
+5 -5
View File
@@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
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/>.
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
@@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
<https://www.gnu.org/licenses/why-not-lgpl.html>.
Binary file not shown.
+13 -12
View File
@@ -1,10 +1,11 @@
# Maintenance
[![Version](https://img.shields.io/github/release/KennyTV/Maintenance.svg)](https://github.com/KennyTV/Maintenance/releases)
[![Build Status](https://travis-ci.org/KennyTV/Maintenance.svg?branch=master)](https://travis-ci.org/KennyTV/Maintenance)
[![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)
[![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 Bukkit/Spigot, BungeeCord, Sponge as well as Velocity.
Maintenance is the most customizable free maintenance plugin for your Minecraft server you can find. It runs on Spigot, BungeeCord, Sponge, as well as Velocity.
Its features include:
* A custom motd as well as server icon, that will be shown during maintenance
@@ -15,15 +16,15 @@ Its features include:
* 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)
* Use PlaceholderAPI placeholders with the [**MaintenanceAddon**](https://github.com/kennytv/Maintenance/wiki/MaintenanceAddon) (only for Bungee)
A full list of commands, permissions and configuration options can be found in the wiki listed below.
* [Wiki](https://github.com/KennyTV/Maintenance/wiki)
* [Downloads](https://github.com/KennyTV/Maintenance/releases) (GitHub)
* [Development builds](https://kennytv.eu/maintenance/snapshot/) (might be unstable)
* [Changelogs](https://github.com/KennyTV/Maintenance/blob/master/.github/CHANGELOG.md)
* [Issue tracker/bug reports](https://github.com/KennyTV/Maintenance/issues)
* [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)
Other forum threads
* [Spigot forums](https://www.spigotmc.org/resources/maintenance.40699/)
@@ -33,5 +34,5 @@ Other forum threads
## Compiling
To create a working jar yourself, simply clone the project and compile it with maven (by using `mvn clean package` in your IDE console).
## Licence
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)).
## License
This project is licensed under the [GNU General Public License v3](LICENSE.txt).
+5 -5
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.3</version>
<version>3.0.7</version>
</parent>
<artifactId>maintenance-api</artifactId>
@@ -16,13 +16,13 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.14-SNAPSHOT</version>
<version>1.17-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.destroystokyo.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.14.4-R0.1-SNAPSHOT</version>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.16.5-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,13 +15,12 @@
* 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
* @author kennytv
* @since 2.1
*/
public interface IMaintenance {
@@ -66,4 +65,16 @@ public interface IMaintenance {
* @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);
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,11 +15,10 @@
* 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
* @author kennytv
* @since 2.2.2
*/
public interface IMaintenanceBase {
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,14 +15,13 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.api;
import java.util.Map;
import java.util.UUID;
/**
* @author KennyTV
* @author kennytv
* @since 2.1
*/
public interface ISettings {
@@ -34,6 +33,11 @@ public interface ISettings {
*/
boolean isMaintenance();
/**
* @return true if custom ping messages during maintenance should be used
*/
boolean isEnablePingMessages();
/**
* @return value of the 'send-join-notification' config field
*/
@@ -52,6 +56,14 @@ public interface ISettings {
*/
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.
*
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,9 +15,9 @@
* 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;
@@ -29,7 +29,7 @@ import net.md_5.bungee.api.plugin.Plugin;
* Only access this class if you're running the plugin on a BungeeCord server!
* </p>
*
* @author KennyTV
* @author kennytv
* @since 2.5
*/
public final class MaintenanceBungeeAPI {
@@ -41,9 +41,8 @@ public final class MaintenanceBungeeAPI {
* @throws IllegalArgumentException if using a custom (or broken?) version of the plugin, that can't be identified
*/
public static IMaintenanceProxy getAPI() {
final Plugin maintenance = ProxyServer.getInstance().getPluginManager().getPlugin("MaintenanceBungee");
if (maintenance == null)
throw new IllegalArgumentException("Could not get instance of MaintenanceBungee! Broken/custom build of the plugin?");
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();
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -23,7 +22,7 @@ import eu.kennytv.maintenance.api.event.manager.MaintenanceEvent;
/**
* Notification event fired when maintenance mode has been changed.
*
* @author KennyTV
* @author kennytv
* @since 3.0.1
*/
public final class MaintenanceChangedEvent implements MaintenanceEvent {
@@ -0,0 +1,33 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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 {
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,14 +15,13 @@
* 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
* @author kennytv
* @since 3.0.1
*/
public abstract class EventListener<T extends MaintenanceEvent> {
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,11 +15,10 @@
* 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
* @author kennytv
* @since 3.0.1
*/
public interface IEventManager {
@@ -31,4 +30,11 @@ public interface IEventManager {
* @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);
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,13 +15,12 @@
* 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
* @author kennytv
* @since 3.0.1
*/
public interface MaintenanceEvent {
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -24,7 +23,7 @@ import eu.kennytv.maintenance.api.proxy.Server;
/**
* Notification event fired when maintenance mode has been changed on a proxied server.
*
* @author KennyTV
* @author kennytv
* @since 3.0.1
*/
public final class ServerMaintenanceChangedEvent implements MaintenanceEvent {
@@ -37,7 +36,12 @@ public final class ServerMaintenanceChangedEvent implements MaintenanceEvent {
}
/**
* @return wrapped server object for the proxied server
* 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;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,15 +15,15 @@
* 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
* @author kennytv
* @since 3.0
*/
public interface IMaintenanceProxy extends IMaintenance {
@@ -60,6 +60,7 @@ public interface IMaintenanceProxy extends IMaintenance {
* @param server name of the proxied server
* @return wrapped server object if present, else null
*/
@Nullable
Server getServer(String server);
/**
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,14 +15,13 @@
* 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
* @author kennytv
* @since 3.0
*/
public interface Server {
@@ -43,4 +42,12 @@ public interface 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();
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,9 +15,9 @@
* 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;
@@ -29,7 +29,7 @@ import org.bukkit.plugin.Plugin;
* Only access this class if you're running the plugin on a Spigot server!
* </p>
*
* @author KennyTV
* @author kennytv
* @since 2.5
*/
public final class MaintenanceSpigotAPI {
@@ -41,9 +41,8 @@ public final class MaintenanceSpigotAPI {
* @throws IllegalArgumentException if using a custom (or broken?) version of the plugin, that can't be identified
*/
public static IMaintenance getAPI() {
final Plugin maintenance = Bukkit.getPluginManager().getPlugin("MaintenanceSpigot");
if (maintenance == null)
throw new IllegalArgumentException("Could not get instance of MaintenanceSpigot! Broken/custom build of the plugin?");
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();
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,9 +15,9 @@
* 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;
@@ -30,7 +30,7 @@ import java.util.Optional;
* Only access this class if you're running the plugin on a Sponge server!
* </p>
*
* @author KennyTV
* @author kennytv
* @since 3.0
*/
public final class MaintenanceSpongeAPI {
@@ -42,9 +42,9 @@ public final class MaintenanceSpongeAPI {
* @throws IllegalArgumentException if using a custom (or broken?) version of the plugin, that can't be identified
*/
public static IMaintenance getAPI() {
final Optional<PluginContainer> container = Sponge.getPluginManager().getPlugin("maintenancesponge");
if (!container.isPresent() || !container.get().getInstance().isPresent())
throw new IllegalArgumentException("Could not get instance of MaintenanceSponge! Broken/custom build of the plugin?");
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();
}
}
+2 -2
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.3</version>
<version>3.0.7</version>
</parent>
<artifactId>maintenance-build</artifactId>
@@ -35,7 +35,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<version>3.2.2</version>
<executions>
<execution>
<phase>package</phase>
+4 -4
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.3</version>
<version>3.0.7</version>
</parent>
<artifactId>maintenance-bungee</artifactId>
@@ -23,13 +23,13 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<version>1.7.30</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.14-SNAPSHOT</version>
<version>1.17-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -40,7 +40,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<version>3.2.2</version>
<executions>
<execution>
<phase>package</phase>
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -33,6 +32,8 @@ 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.proxy.util.ProfileLookup;
import eu.kennytv.maintenance.core.proxy.util.ProxyOfflineSenderInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import eu.kennytv.maintenance.core.util.ServerType;
import eu.kennytv.maintenance.core.util.Task;
@@ -47,6 +48,7 @@ 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;
@@ -60,7 +62,7 @@ import java.util.logging.Logger;
import java.util.stream.Collectors;
/**
* @author KennyTV
* @author kennytv
* @since 1.0
*/
public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
@@ -89,7 +91,9 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
final Plugin serverListPlus = pm.getPlugin("ServerListPlus");
if (serverListPlus != null) {
serverListPlusHook = new ServerListPlusHook(serverListPlus);
serverListPlusHook.setEnabled(!settingsProxy.isMaintenance());
if (settings.isEnablePingMessages()) {
serverListPlusHook.setEnabled(!settingsProxy.isMaintenance());
}
plugin.getLogger().info("Enabled ServerListPlus integration!");
}
}
@@ -116,9 +120,9 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
}
@Override
protected void kickPlayers() {
protected void kickPlayersFromProxy() {
for (final ProxiedPlayer p : getProxy().getPlayers()) {
if (!hasPermission(p, "bypass") && !settingsProxy.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
if (!hasPermission(p, "bypass") && !settingsProxy.isWhitelisted(p.getUniqueId())) {
p.disconnect(settingsProxy.getKickMessage());
}
}
@@ -126,16 +130,37 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
@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;
for (final ProxiedPlayer p : ((BungeeServer) server).getServer().getPlayers()) {
if (!hasPermission(p, "bypass") && !settingsProxy.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
if (fallbackServer != null && fallbackServer.canAccess(p) && !isMaintenance(fallback)) {
p.sendMessage(settingsProxy.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName()));
p.connect(fallbackServer);
} else
p.disconnect(settingsProxy.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", server.getName()));
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 {
p.sendMessage(settingsProxy.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName()));
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());
}
}
}
@@ -146,27 +171,43 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
}
@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;
if (player != null) {
return new BungeeSenderInfo(player);
}
final ProfileLookup profile;
try {
profile = doUUIDLookup(name);
} catch (final IOException e) {
e.printStackTrace();
return null;
}
return new ProxyOfflineSenderInfo(profile.getUuid(), profile.getName());
}
@Override
@Nullable
public SenderInfo getOfflinePlayer(final UUID uuid) {
final ProxiedPlayer player = getProxy().getPlayer(uuid);
return player != null ? new BungeeSenderInfo(player) : null;
}
@Override
public String getServer(final SenderInfo sender) {
@Nullable
public String getServerNameOf(final SenderInfo sender) {
final ProxiedPlayer player = getProxy().getPlayer(sender.getUuid());
return player != null ? player.getServer().getInfo().getName() : "";
if (player == null || player.getServer() == null) return null;
return player.getServer().getInfo().getName();
}
@Override
@@ -174,6 +215,11 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
getProxy().getScheduler().runAsync(plugin, runnable);
}
@Override
protected void executeConsoleCommand(final String command) {
getProxy().getPluginManager().dispatchCommand(getProxy().getConsole(), command);
}
@Override
public void broadcast(final String message) {
getProxy().broadcast(message);
@@ -189,6 +235,16 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
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);
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -28,10 +27,15 @@ public final class MaintenanceBungeeCommandBase extends Command implements TabEx
private final MaintenanceCommand command;
public MaintenanceBungeeCommandBase(final MaintenanceCommand command) {
super("maintenance", "", "maintenancebungee");
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);
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -24,7 +23,6 @@ import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
public final class ProxyPingListener implements Listener {
private final MaintenanceBungeePlugin plugin;
@@ -35,26 +33,33 @@ public final class ProxyPingListener implements Listener {
this.settings = settings;
}
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(priority = 80)
public void proxyPing(final ProxyPingEvent event) {
if (!settings.isMaintenance()) return;
if (!settings.isMaintenance() || !settings.isEnablePingMessages()) 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.getVersion().setProtocol(1);
ping.getVersion().setName(settings.getPlayerCountMessage()
.replace("%ONLINE%", Integer.toString(ping.getPlayers().getOnline()))
.replace("%MAX%", Integer.toString(ping.getPlayers().getMax())));
ping.setVersion(new ServerPing.Protocol(settings.getPlayerCountMessage()
.replace("%ONLINE%", Integer.toString(players.getOnline()))
.replace("%MAX%", Integer.toString(players.getMax())), 1));
}
ping.setDescription(settings.getRandomPingMessage());
ping.getPlayers().setOnline(0);
ping.getPlayers().setMax(0);
ping.getPlayers().setSample(new ServerPing.PlayerInfo[]{
new ServerPing.PlayerInfo(settings.getPlayerCountHoverMessage().replace("%NEWLINE%", "\n"), "")
});
if (settings.hasCustomIcon() && plugin.getFavicon() != null)
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());
}
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,41 +15,60 @@
* 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.core.listener.JoinListenerBase;
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.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 extends JoinListenerBase implements Listener {
public final class ServerConnectListener extends ProxyJoinListenerBase implements Listener {
private final MaintenanceBungeePlugin plugin;
private final SettingsProxy settings;
private boolean warned;
public ServerConnectListener(final MaintenanceBungeePlugin plugin, final SettingsProxy settings) {
super(plugin, settings);
this.plugin = plugin;
this.settings = settings;
}
@EventHandler
public void initialServerConnect(final ServerConnectEvent event) {
// Global maintenance check
if (event.isCancelled() || event.getReason() != ServerConnectEvent.Reason.JOIN_PROXY) return;
if (kickPlayer(new BungeeSenderInfo(event.getPlayer()))) {
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());
}
}
}
@@ -59,49 +78,40 @@ public final class ServerConnectListener extends JoinListenerBase implements Lis
if (event.isCancelled()) return;
final ProxiedPlayer player = event.getPlayer();
final ServerInfo target = event.getTarget();
if (!plugin.isMaintenance(target)) return;
if (plugin.hasPermission(player, "bypass") || settings.getWhitelistedPlayers().containsKey(player.getUniqueId())
|| plugin.hasPermission(player, "singleserver.bypass." + target.getName().toLowerCase()))
return;
if (settings.isJoinNotifications()) {
final BaseComponent[] s = TextComponent.fromLegacyText(settings.getMessage("joinNotification").replace("%PLAYER%", player.getName()));
for (final ProxiedPlayer p : target.getPlayers()) {
if (plugin.hasPermission(p, "joinnotification")) {
p.sendMessage(s);
}
}
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);
}
// 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) {
if (connectResult.isCancelled()) {
event.setCancelled(true);
player.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(player) || plugin.isMaintenance(fallback)) {
event.setCancelled(true);
player.disconnect(settings.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", target.getName()));
if (!warned) {
plugin.getLogger().warning("Could not send player to the set fallback server; instead kicking player off the network!");
warned = true;
// Player has no server to connect to
if (player.getServer() == null) {
player.disconnect(settings.getKickMessage());
}
} else {
event.setTarget(fallback);
} else if (connectResult.getTarget() != null) {
event.setTarget(((BungeeServer) connectResult.getTarget()).getServer());
}
}
@Override
protected void broadcastJoinNotification(final String name) {
final BaseComponent[] s = TextComponent.fromLegacyText(settings.getMessage("joinNotification").replace("%PLAYER%", name));
for (final ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) {
if (plugin.hasPermission(p, "joinnotification")) {
p.sendMessage(s);
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();
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,17 +15,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.bungee.util;
import eu.kennytv.maintenance.core.util.SenderInfo;
import 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 SenderInfo {
public final class BungeeSenderInfo implements ProxySenderInfo {
private final CommandSender sender;
public BungeeSenderInfo(final CommandSender sender) {
@@ -60,4 +61,16 @@ public final class BungeeSenderInfo implements SenderInfo {
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);
}
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -49,6 +48,11 @@ public final class BungeeServer implements Server {
}
}
@Override
public boolean isRegisteredServer() {
return true;
}
public ServerInfo getServer() {
return server;
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -1,7 +1,7 @@
name: MaintenanceBungee
name: Maintenance
version: ${project.version}
main: eu.kennytv.maintenance.bungee.MaintenanceBungeeBase
author: KennyTV
author: kennytv
description: Enable maintenance mode with a custom maintenance motd and icon.
softDepends: [ServerListPlus]
website: https://www.spigotmc.org/resources/maintenance.40699/
+14 -2
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.3</version>
<version>3.0.7</version>
</parent>
<artifactId>maintenance-core-proxy</artifactId>
@@ -22,7 +22,7 @@
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
<version>4.0.3</version>
<scope>compile</scope>
<!-- Shade slf4j specifically and only in the Bungee module to prevent issues -->
<exclusions>
@@ -32,5 +32,17 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,25 +15,40 @@
* 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 com.google.common.io.CharStreams;
import com.google.gson.JsonObject;
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.server.DummyServer;
import eu.kennytv.maintenance.core.proxy.runnable.SingleMaintenanceScheduleRunnable;
import eu.kennytv.maintenance.core.proxy.util.ProfileLookup;
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.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
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.UUID;
import java.util.concurrent.TimeUnit;
/**
* @author KennyTV
* @author kennytv
* @since 3.0
*/
public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implements IMaintenanceProxy {
@@ -47,14 +62,16 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
@Override
public void disable() {
super.disable();
if (settingsProxy.getMySQL() != null)
if (settingsProxy.getMySQL() != null) {
settingsProxy.getMySQL().close();
}
}
@Override
public void setMaintenance(final boolean maintenance) {
if (settingsProxy.hasMySQL())
if (settingsProxy.hasMySQL()) {
settingsProxy.setMaintenanceToSQL(maintenance);
}
super.setMaintenance(maintenance);
}
@@ -75,18 +92,25 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
}
public void serverActions(final Server server, final boolean maintenance) {
if (server == null || server instanceof DummyServer) return;
if (maintenance) {
final Server fallback = getServer(settingsProxy.getFallbackServer());
if (fallback == null) {
if (server.hasPlayers())
getLogger().warning("The set fallback could not be found! Instead kicking players from that server off the network!");
} else if (fallback.getName().equals(server.getName()))
getLogger().warning("Maintenance has been enabled on the fallback server! If a player joins on a proxied server, they will be kicked completely instead of being sent to the fallback server!");
kickPlayers(server, fallback);
} else
server.broadcast(settingsProxy.getMessage("singleMaintenanceDeactivated").replace("%SERVER%", server.getName()));
cancelSingleTask(server);
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));
}
@@ -102,20 +126,31 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
public void cancelSingleTask(final Server server) {
final Task task = serverTasks.remove(server.getName());
if (task != null)
if (task != null) {
task.cancel();
}
}
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final Server server, final int minutes, final boolean enable) {
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, settingsProxy, minutes, enable, server);
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");
if (isMaintenance()) {
list.add("global");
}
list.addAll(settingsProxy.getMaintenanceServers());
return list.isEmpty() ? null : list;
}
@@ -125,11 +160,44 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
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();
}
protected ProfileLookup doUUIDLookup(final String name) throws IOException {
final URL url = new URL("https://api.ashcon.app/mojang/v2/user/" + name);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try (final InputStream in = connection.getInputStream()) {
final String output = CharStreams.toString(new InputStreamReader(in));
final JsonObject json = GSON.fromJson(output, JsonObject.class);
final UUID uuid = UUID.fromString(json.getAsJsonPrimitive("uuid").getAsString());
final String username = json.getAsJsonPrimitive("username").getAsString();
return new ProfileLookup(uuid, username);
}
}
public SettingsProxy getSettingsProxy() {
return settingsProxy;
}
public abstract String getServer(SenderInfo sender);
@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();
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,22 +15,26 @@
* 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 String fallbackServer;
private List<String> fallbackServers;
private String waitingServer;
private String mySQLTable;
private String serverTable;
@@ -44,6 +48,7 @@ public final class SettingsProxy extends Settings {
public SettingsProxy(final MaintenanceProxyPlugin plugin) {
super(plugin);
this.proxyPlugin = plugin;
}
private void setupMySQL() throws Exception {
@@ -54,11 +59,13 @@ public final class SettingsProxy extends Settings {
return;
}
mySQL = new MySQL(section.getString("host"),
mySQL = new MySQL(plugin.getLogger(),
section.getString("host"),
section.getInt("port"),
section.getString("username"),
section.getString("password"),
section.getString("database"));
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");
@@ -73,7 +80,7 @@ public final class SettingsProxy extends Settings {
@Override
protected void loadExtraSettings() {
// Open database connection if enabled and not already done
if (!hasMySQL() && (boolean) config.getDeep("mysql.use-mysql")) {
if (!hasMySQL() && config.getBoolean("mysql.use-mysql")) {
try {
setupMySQL();
} catch (final Exception e) {
@@ -83,7 +90,14 @@ public final class SettingsProxy extends Settings {
}
}
fallbackServer = config.getString("fallback", "lobby");
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();
@@ -116,16 +130,17 @@ public final class SettingsProxy extends Settings {
if (hasMySQL() && System.currentTimeMillis() - lastServerCheck > millisecondsToCheck) {
final Set<String> databaseValue = loadMaintenanceServersFromSQL();
if (!maintenanceServers.equals(databaseValue)) {
final MaintenanceProxyPlugin plugin = (MaintenanceProxyPlugin) super.plugin;
// Enable maintenance on yet unlisted servers
for (final String s : databaseValue) {
if (!maintenanceServers.contains(s))
plugin.serverActions(plugin.getServer(s), true);
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))
plugin.serverActions(plugin.getServer(s), false);
if (!databaseValue.contains(s)) {
proxyPlugin.serverActions(proxyPlugin.getServer(s), false);
}
}
maintenanceServers = databaseValue;
}
@@ -134,6 +149,23 @@ public final class SettingsProxy extends Settings {
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;
}
@@ -163,10 +195,12 @@ public final class SettingsProxy extends Settings {
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;
@@ -211,10 +245,23 @@ public final class SettingsProxy extends Settings {
return maintenanceServers;
}
public String getFallbackServer() {
return fallbackServer;
@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;
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -45,6 +44,7 @@ public abstract class MaintenanceProxyCommand extends MaintenanceCommand {
add(new SingleStarttimerCommand(plugin), "starttimer", "start");
add(new SingleEndtimerCommand(plugin), "endtimer", "end");
add(new SingleScheduleTimerCommand(plugin), "scheduletimer", "schedule");
add(new AbortSingleTimerCommand(plugin), "aborttimer", "abort");
}
@@ -59,8 +59,8 @@ public abstract class MaintenanceProxyCommand extends MaintenanceCommand {
return list;
}
public Server checkSingleTimerArgs(final SenderInfo sender, final String[] args) {
final Server server = plugin.getServer(args[1]);
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;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -26,6 +25,7 @@ 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 {
@@ -50,7 +50,8 @@ public final class SingleEndtimerCommand extends ProxyCommandInfo {
sender.sendMessage(getMessage("alreadyDisabled"));
return;
}
plugin.startMaintenanceRunnableForMinutes(Integer.parseInt(args[1]), false);
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;
@@ -59,16 +60,18 @@ public final class SingleEndtimerCommand extends ProxyCommandInfo {
return;
}
final Server server = plugin.getCommandManager().checkSingleTimerArgs(sender, args);
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]), false);
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, Integer.parseInt(args[2]), TimeUnit.MINUTES, false);
sender.sendMessage(getMessage("endtimerStarted").replace("%TIME%", runnable.getTime()));
} else
} else {
sender.sendMessage(getHelpMessage());
}
}
@Override
@@ -0,0 +1,83 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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();
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -26,6 +25,7 @@ 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 {
@@ -51,7 +51,7 @@ public final class SingleStarttimerCommand extends ProxyCommandInfo {
return;
}
plugin.startMaintenanceRunnableForMinutes(Integer.parseInt(args[1]), true);
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;
@@ -60,17 +60,18 @@ public final class SingleStarttimerCommand extends ProxyCommandInfo {
return;
}
final Server server = plugin.getCommandManager().checkSingleTimerArgs(sender, args);
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]), true);
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, Integer.parseInt(args[2]), TimeUnit.MINUTES, true);
sender.sendMessage(getMessage("starttimerStarted").replace("%TIME%", runnable.getTime()));
} else
} else {
sender.sendMessage(getHelpMessage());
}
}
@Override
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -67,12 +66,15 @@ public final class SingleToggleCommand extends ProxyCommandInfo {
}
if (plugin.setMaintenanceToServer(server, maintenance)) {
if (!sender.isPlayer() || !plugin.getServer(sender).equals(server.getName()))
if (!sender.isPlayer() || !server.getName().equals(plugin.getServerNameOf(sender))) {
sender.sendMessage(getMessage(maintenance ? "singleMaintenanceActivated" : "singleMaintenanceDeactivated").replace("%SERVER%", server.getName()));
} else
}
} else {
sender.sendMessage(getMessage(maintenance ? "singleServerAlreadyEnabled" : "singleServerAlreadyDisabled").replace("%SERVER%", server.getName()));
} else
}
} else {
sender.sendMessage(getHelpMessage());
}
}
@Override
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -32,11 +31,12 @@ public final class StatusCommand extends ProxyCommandInfo {
public void execute(final SenderInfo sender, final String[] args) {
if (getSettings().getMaintenanceServers().isEmpty()) {
sender.sendMessage(getMessage("singleServerMaintenanceListEmpty"));
} else {
sender.sendMessage(getMessage("singleServerMaintenanceList"));
for (final String server : getSettings().getMaintenanceServers()) {
sender.sendMessage("§8- §b" + server);
}
return;
}
sender.sendMessage(getMessage("singleServerMaintenanceList"));
for (final String server : getSettings().getMaintenanceServers()) {
sender.sendMessage("§8- §b" + server);
}
}
}
@@ -0,0 +1,121 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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,30 +1,70 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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;
import org.jetbrains.annotations.Nullable;
import java.sql.Connection;
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);
hikariConfig.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
String urlProperty = "jdbc:mysql://" + hostname + ":" + port + "/" + database;
if (!useSSL) {
urlProperty += "?useSSL=false";
}
hikariConfig.addDataSourceProperty("url", urlProperty);
hikariConfig.setJdbcUrl(urlProperty);
hikariConfig.setDataSourceClassName(findDriver("com.mysql.jdbc.jdbc2.optional.MysqlDataSource", "com.mysql.cj.jdbc.MysqlDataSource", "org.mariadb.jdbc.MariaDbDataSource"));
hikariDataSource = new HikariDataSource(hikariConfig);
}
@Nullable
private String findDriver(final String... classNames) {
for (final String name : classNames) {
try {
Class.forName(name);
return name;
} catch (final ClassNotFoundException ignored) {
}
}
throw new IllegalArgumentException("No sql driver class found");
}
public void executeUpdate(final String query, final Consumer<Integer> callback, final Object... objects) {
try (final Connection connection = hikariDataSource.getConnection()) {
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
@@ -37,7 +77,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();
}
}
@@ -51,12 +91,12 @@ public final class MySQL {
current++;
}
final ResultSet resultSet = preparedStatement.executeQuery();
callback.accept(resultSet);
resultSet.close();
try (final ResultSet resultSet = preparedStatement.executeQuery()) {
callback.accept(resultSet);
}
}
} 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();
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -24,26 +23,31 @@ import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
public final class SingleMaintenanceRunnable extends MaintenanceRunnableBase {
private final Server server;
public 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 startMessageKey() {
protected String getStartMessage() {
return settings.getMessage("singleStarttimerBroadcast").replace("%TIME%", getTime()).replace("%SERVER%", server.getName());
}
@Override
protected String endMessageKey() {
protected String getEndMessage() {
return settings.getMessage("singleEndtimerBroadcast").replace("%TIME%", getTime()).replace("%SERVER%", server.getName());
}
}
@@ -0,0 +1,46 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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);
}
@Override
protected String getStartMessage() {
return settings.getMessage("singleScheduletimerBroadcast").replace("%SERVER%", server.getName())
.replace("%TIME%", getTime()).replace("%DURATION%", plugin.getFormattedTime(maintenanceDuration));
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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;
@@ -38,6 +37,11 @@ public final class DummyServer implements Server {
}
@Override
public void broadcast(String s) {
public void broadcast(final String s) {
}
@Override
public boolean isRegisteredServer() {
return false;
}
}
@@ -0,0 +1,38 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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.util;
import java.util.UUID;
public final class ProfileLookup {
private final UUID uuid;
private final String name;
public ProfileLookup(final UUID uuid, final String name) {
this.uuid = uuid;
this.name = name;
}
public UUID getUuid() {
return uuid;
}
public String getName() {
return name;
}
}
@@ -0,0 +1,65 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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.util;
import eu.kennytv.maintenance.api.proxy.Server;
import java.util.UUID;
public final class ProxyOfflineSenderInfo implements ProxySenderInfo {
private final UUID uuid;
private final String name;
public ProxyOfflineSenderInfo(final UUID uuid, final String name) {
this.uuid = uuid;
this.name = name;
}
@Override
public boolean canAccess(final Server server) {
return false;
}
@Override
public void disconnect(final String message) {
}
@Override
public UUID getUuid() {
return uuid;
}
@Override
public String getName() {
return name;
}
@Override
public boolean hasPermission(final String permission) {
return false;
}
@Override
public void sendMessage(final String message) {
}
@Override
public boolean isPlayer() {
return true;
}
}
@@ -0,0 +1,28 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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.util;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.util.SenderInfo;
public interface ProxySenderInfo extends SenderInfo {
boolean canAccess(Server server);
void disconnect(String message);
}
@@ -0,0 +1,53 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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.util;
import eu.kennytv.maintenance.api.proxy.Server;
import org.jetbrains.annotations.Nullable;
public final class ServerConnectResult {
private final boolean cancel;
private final Server target;
public ServerConnectResult(final boolean cancel) {
this.cancel = cancel;
this.target = null;
}
public ServerConnectResult(final Server target) {
this.cancel = false;
this.target = target;
}
public boolean isCancelled() {
return cancel;
}
@Nullable
public Server getTarget() {
return target;
}
@Override
public String toString() {
return "ServerConnectResult{" +
"cancel=" + cancel +
", target=" + target +
'}';
}
}
+2 -2
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.3</version>
<version>3.0.7</version>
</parent>
<artifactId>maintenance-core</artifactId>
@@ -34,7 +34,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
<version>29.0-jre</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,12 +15,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.io.CharStreams;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import eu.kennytv.maintenance.api.IMaintenance;
@@ -32,12 +32,23 @@ import eu.kennytv.maintenance.core.dump.PluginDump;
import eu.kennytv.maintenance.core.event.EventManager;
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
import eu.kennytv.maintenance.core.runnable.MaintenanceScheduleRunnable;
import eu.kennytv.maintenance.core.util.SenderInfo;
import eu.kennytv.maintenance.core.util.ServerType;
import eu.kennytv.maintenance.core.util.Task;
import eu.kennytv.maintenance.core.util.Version;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
@@ -50,6 +61,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class MaintenancePlugin implements IMaintenance {
public static final Gson GSON = new GsonBuilder().create();
protected final EventManager eventManager;
protected final Version version;
protected Settings settings;
@@ -59,6 +71,7 @@ public abstract class MaintenancePlugin implements IMaintenance {
private final String prefix;
private final ServerType serverType;
private Version newestVersion;
private boolean debug;
protected MaintenancePlugin(final String version, final ServerType serverType) {
this.version = new Version(version);
@@ -76,29 +89,51 @@ public abstract class MaintenancePlugin implements IMaintenance {
settings.getConfig().set("maintenance-enabled", maintenance);
settings.saveConfig();
serverActions(maintenance);
for (final String command : (maintenance ? settings.getCommandsOnMaintenanceEnable() : settings.getCommandsOnMaintenanceDisable())) {
try {
executeConsoleCommand(command);
} catch (final Exception e) {
getLogger().severe("Error while executing extra maintenance " + (maintenance ? "enable" : "disable") + " command: " + command);
e.printStackTrace();
}
}
}
public void serverActions(final boolean maintenance) {
if (isTaskRunning())
if (isTaskRunning()) {
cancelTask();
if (serverListPlusHook != null)
}
if (serverListPlusHook != null && settings.isEnablePingMessages()) {
serverListPlusHook.setEnabled(!maintenance);
}
if (maintenance) {
broadcast(settings.getMessage("maintenanceActivated"));
if (settings.isKickOnlinePlayers()) {
kickPlayers();
}
broadcast(settings.getMessage("maintenanceActivated"));
} else
} else {
broadcast(settings.getMessage("maintenanceDeactivated"));
}
eventManager.callEvent(new MaintenanceChangedEvent(maintenance));
}
public String formatedTimer(final String s) {
return s.contains("%TIMER%") ? s.replace("%TIMER%", formatedTimer()) : s;
public String replacePingVariables(String s) {
if (s.contains("%TIMER%")) {
s = s.replace("%TIMER%", getTimerMessage());
}
if (s.contains("%ONLINE%")) {
s = s.replace("%ONLINE%", Integer.toString(getOnlinePlayers()));
}
if (s.contains("%MAX%")) {
s = s.replace("%MAX%", Integer.toString(getMaxPlayers()));
}
return s;
}
public String formatedTimer() {
public String getTimerMessage() {
if (!isTaskRunning()) return settings.getMessage("motdTimerNotRunning", "-");
final int preHours = runnable.getSecondsLeft() / 60;
final int minutes = preHours % 60;
@@ -109,21 +144,45 @@ public abstract class MaintenancePlugin implements IMaintenance {
.replace("%SECONDS%", String.format("%02d", seconds));
}
public void startMaintenanceRunnableForMinutes(final int minutes, final boolean enable) {
startMaintenanceRunnableForSeconds(minutes * 60, enable);
public String getFormattedTime(final int timeSeconds) {
final int preHours = timeSeconds / 60;
final int minutes = preHours % 60;
final int seconds = timeSeconds % 60;
final StringBuilder buider = new StringBuilder();
append(buider, "hour", preHours / 60);
append(buider, "minute", minutes);
append(buider, "second", seconds);
return buider.toString();
}
public void startMaintenanceRunnableForSeconds(final int seconds, final boolean enable) {
runnable = new MaintenanceRunnable(this, settings, seconds, enable);
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 void startMaintenanceRunnable(final long duration, final TimeUnit unit, final boolean enable) {
runnable = new MaintenanceRunnable(this, settings, (int) unit.toSeconds(duration), enable);
// Save the endtimer to be able to continue it after a server stop
if (settings.isSaveEndtimerOnStop() && !runnable.shouldEnable()) {
settings.setSavedEndtimer(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(runnable.getSecondsLeft()));
}
}
public void scheduleMaintenanceRunnable(final long duration, final int maintenanceDuration, final TimeUnit unit) {
runnable = new MaintenanceScheduleRunnable(this, settings, (int) unit.toSeconds(duration), (int) unit.toSeconds(maintenanceDuration));
}
public boolean updateAvailable() {
checkNewestVersion();
return version.compareTo(newestVersion) == -1;
try {
checkNewestVersion();
return version.compareTo(newestVersion) == -1;
} catch (final Exception e) {
return false;
}
}
protected void continueLastEndtimer() {
@@ -140,23 +199,27 @@ public abstract class MaintenancePlugin implements IMaintenance {
setMaintenance(false);
settings.setSavedEndtimer(0);
} else {
final int seconds = (int) TimeUnit.MILLISECONDS.toSeconds(settings.getSavedEndtimer() - current);
startMaintenanceRunnableForSeconds(seconds, false);
getLogger().info("The timer has been continued - maintenance will be disabled in: " + formatedTimer());
startMaintenanceRunnable(settings.getSavedEndtimer() - current, TimeUnit.MILLISECONDS, false);
getLogger().info("The timer has been continued - maintenance will be disabled in: " + getTimerMessage());
}
}
protected void sendEnableMessage() {
getLogger().info("Plugin by KennyTV");
if (!settings.hasUpdateChecks()) return;
async(() -> {
checkNewestVersion();
try {
checkNewestVersion();
} catch (final Exception e) {
getLogger().warning("An error occured during update checking!");
return;
}
final int compare = version.compareTo(newestVersion);
if (compare == -1) {
getLogger().info("§cNewest version available: §aVersion " + newestVersion + "§c, you're on §a" + version);
} else if (compare == 1) {
if (version.getTag().equalsIgnoreCase("snapshot")) {
getLogger().info("§cYou're running a development version, please report bugs on the Discord server (https://discord.gg/vGCUzHq) or the GitHub issue tracker (https://github.com/KennyTV/Maintenance/issues)");
getLogger().info("§cYou're running a development version, please report bugs on the Discord server (https://discord.gg/vGCUzHq) or the GitHub issue tracker (https://github.com/kennytv/Maintenance/issues)");
} else {
getLogger().info("§cYou're running a version, that doesn't exist! §cN§ai§dc§ee§5!");
}
@@ -169,7 +232,7 @@ public abstract class MaintenancePlugin implements IMaintenance {
Preconditions.checkArgument(serverType != ServerType.SPONGE);
try {
final String fileSuffix = serverType == ServerType.VELOCITY ? "Velocity" : "";
final URLConnection conn = new URL("https://github.com/KennyTV/Maintenance/releases/download/" + newestVersion + "/Maintenance" + fileSuffix + ".jar").openConnection();
final URLConnection conn = new URL("https://github.com/kennytv/Maintenance/releases/download/" + newestVersion + "/Maintenance" + fileSuffix + ".jar").openConnection();
writeFile(new BufferedInputStream(conn.getInputStream()), new BufferedOutputStream(new FileOutputStream(getPluginFolder() + "Maintenance.tmp")));
final File file = new File(getPluginFolder() + "Maintenance.tmp");
final long newlength = file.length();
@@ -197,49 +260,45 @@ public abstract class MaintenancePlugin implements IMaintenance {
os.close();
}
private void checkNewestVersion() {
try {
final HttpURLConnection c = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=40699").openConnection();
final BufferedReader reader = new BufferedReader(new InputStreamReader(c.getInputStream()));
private void checkNewestVersion() throws Exception {
final HttpURLConnection c = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=40699").openConnection();
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(c.getInputStream()))) {
final String newVersionString = reader.readLine();
reader.close();
final Version newVersion = new Version(newVersionString);
if (!newVersion.equals(version))
if (!newVersion.equals(version)) {
newestVersion = newVersion;
} catch (final Exception ignored) {
}
}
}
public String pasteDump() {
final MaintenanceDump dump = new MaintenanceDump(this, settings);
try {
final HttpURLConnection connection = (HttpURLConnection) new URL("https://hasteb.in/documents").openConnection();
final HttpURLConnection connection = (HttpURLConnection) new URL("https://hastebin.com/documents").openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("User-Agent", "Maintenance/" + getVersion());
connection.setRequestProperty("Content-Type", "text/plain");
final GsonBuilder gsonBuilder = new GsonBuilder();
final OutputStream out = connection.getOutputStream();
out.write(gsonBuilder.disableHtmlEscaping().setPrettyPrinting().create().toJson(dump).getBytes(StandardCharsets.UTF_8));
out.close();
try (final OutputStream out = connection.getOutputStream()) {
out.write(new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create().toJson(dump).getBytes(StandardCharsets.UTF_8));
}
if (connection.getResponseCode() == 503) {
getLogger().warning("Could not paste dump, hasteb.in down?");
getLogger().warning("Could not paste dump, hastebin.com down?");
return null;
}
final InputStream in = connection.getInputStream();
final String output = CharStreams.toString(new InputStreamReader(in));
in.close();
try (final InputStream in = connection.getInputStream()) {
final String output = CharStreams.toString(new InputStreamReader(in));
final JsonObject jsonOutput = GSON.fromJson(output, JsonObject.class);
if (!jsonOutput.has("key")) {
getLogger().log(Level.WARNING, "Could not paste dump, there was no key returned :(");
return null;
}
final JsonObject jsonOutput = gsonBuilder.create().fromJson(output, JsonObject.class);
if (!jsonOutput.has("key")) {
getLogger().log(Level.WARNING, "Could not paste dump, there was no key returned :(");
return null;
return jsonOutput.get("key").getAsString();
}
return jsonOutput.get("key").getAsString();
} catch (final IOException e) {
getLogger().log(Level.WARNING, "Could not paste dump :(");
e.printStackTrace();
@@ -263,12 +322,15 @@ public abstract class MaintenancePlugin implements IMaintenance {
}
public void cancelTask() {
if (settings.isSaveEndtimerOnStop() && !runnable.shouldEnable())
if (settings.isSaveEndtimerOnStop() && !runnable.shouldEnable()) {
settings.setSavedEndtimer(0);
}
runnable.getTask().cancel();
runnable = null;
}
@Nullable
public UUID checkUUID(final SenderInfo sender, final String s) {
final UUID uuid;
try {
@@ -315,10 +377,21 @@ public abstract class MaintenancePlugin implements IMaintenance {
return version.toString();
}
@Nullable
public List<String> getMaintenanceServersDump() {
return isMaintenance() ? Arrays.asList("global") : null;
}
@Override
public boolean isDebug() {
return debug;
}
@Override
public void setDebug(final boolean debug) {
this.debug = debug;
}
public int getSaltLevel() {
return Integer.MAX_VALUE;
}
@@ -331,6 +404,10 @@ public abstract class MaintenancePlugin implements IMaintenance {
return prefix;
}
/**
* @see #isTaskRunning()
*/
@Nullable
public MaintenanceRunnable getRunnable() {
return runnable;
}
@@ -349,14 +426,25 @@ public abstract class MaintenancePlugin implements IMaintenance {
public abstract void async(Runnable runnable);
protected abstract void executeConsoleCommand(String command);
public abstract void broadcast(String message);
public abstract void sendUpdateNotification(SenderInfo sender);
public abstract Task startMaintenanceRunnable(Runnable runnable);
/**
* Returns offline sender info of a player.
* This method may do a web lookup.
*
* @param name name of the player
* @return sender info if found, else null
*/
@Nullable
public abstract SenderInfo getOfflinePlayer(String name);
@Nullable
public abstract SenderInfo getOfflinePlayer(UUID uuid);
public abstract File getDataFolder();
@@ -374,4 +462,8 @@ public abstract class MaintenancePlugin implements IMaintenance {
protected abstract void kickPlayers();
protected abstract File getPluginFile();
protected abstract int getOnlinePlayers();
protected abstract int getMaxPlayers();
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,23 +15,29 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core;
import eu.kennytv.maintenance.api.ISettings;
import eu.kennytv.maintenance.api.event.MaintenanceReloadedEvent;
import eu.kennytv.maintenance.core.config.Config;
import eu.kennytv.maintenance.core.config.ConfigSection;
import eu.kennytv.maintenance.core.util.ServerType;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.*;
import java.util.logging.Level;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
public class Settings implements ISettings {
private static final int CURRENT_CONFIG_VERSION = 3;
private static final int CURRENT_CONFIG_VERSION = 5;
private static final Random RANDOM = new Random();
protected final MaintenancePlugin plugin;
private final Map<UUID, String> whitelistedPlayers = new HashMap<>();
@@ -40,9 +46,12 @@ public class Settings implements ISettings {
private Set<Integer> broadcastIntervals;
private List<String> pingMessages;
private List<String> timerSpecificPingMessages;
private List<String> commandsOnMaintenanceEnable;
private List<String> commandsOnMaintenanceDisable;
private String playerCountMessage;
private String playerCountHoverMessage;
private String languageName;
private boolean enablePingMessages;
private boolean customPlayerCountMessage;
private boolean customMaintenanceIcon;
private boolean joinNotifications;
@@ -59,8 +68,10 @@ public class Settings implements ISettings {
public Settings(final MaintenancePlugin plugin, final String... unsupportedFields) {
this.plugin = plugin;
this.unsupportedFields = unsupportedFields;
if (!plugin.getDataFolder().exists())
if (!plugin.getDataFolder().exists()) {
updatePluginDirectory();
plugin.getDataFolder().mkdirs();
}
createFile("config.yml");
createFile("WhitelistedPlayers.yml");
@@ -92,10 +103,19 @@ public class Settings implements ISettings {
updateLanguageFile();
// Directly save colored messages
for (final Map.Entry<String, Object> entry : language.getValues().entrySet()) {
if (!(entry.getValue() instanceof String)) continue;
entry.setValue(getColoredString((String) entry.getValue()));
// Directly cache colored messages - this should not be saved!
transformColoredMessages(language.getValues());
plugin.getEventManager().callEvent(new MaintenanceReloadedEvent());
}
private void transformColoredMessages(final Map<String, Object> map) {
for (final Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue() instanceof Map) {
transformColoredMessages((Map<String, Object>) entry.getValue());
} else if (entry.getValue() instanceof String) {
entry.setValue(getColoredString(replaceNewlineVar((String) entry.getValue())));
}
}
}
@@ -118,7 +138,7 @@ public class Settings implements ISettings {
try (final InputStream in = plugin.getResource(from)) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
throw new IllegalArgumentException("Unable to create " + name + " file for Maintenance!", e);
throw new RuntimeException("Unable to create " + name + " file for Maintenance!", e);
}
}
}
@@ -132,17 +152,19 @@ public class Settings implements ISettings {
}
private void createLanguageFile() {
final File file = new File(plugin.getDataFolder(), "language-" + languageName + ".yml");
if (!file.exists()) {
try (final InputStream in = plugin.getResource("language-" + languageName + ".yml")) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
plugin.getLogger().warning("Unable to provide language " + languageName);
if (!languageName.equals("en")) {
plugin.getLogger().warning("Falling back to default language: en");
languageName = "en";
createLanguageFile();
}
final String fileName = "language-" + languageName + ".yml";
final File file = new File(plugin.getDataFolder(), fileName);
if (file.exists()) return;
try (final InputStream in = plugin.getResource(fileName)) {
Files.copy(in, file.toPath());
} catch (final IOException e) {
plugin.getLogger().warning("Unable to provide language " + languageName);
// Fall back to English language (if not already selected)
if (!languageName.equals("en")) {
plugin.getLogger().warning("Falling back to default language: en");
languageName = "en";
createLanguageFile();
}
}
}
@@ -150,24 +172,31 @@ public class Settings implements ISettings {
private void loadSettings() {
updateConfig();
enablePingMessages = config.getBoolean("enable-pingmessages", true);
pingMessages = config.getStringList("pingmessages");
if (config.getBoolean("enable-timerspecific-messages"))
if (config.getBoolean("enable-timerspecific-messages")) {
timerSpecificPingMessages = config.getStringList("timerspecific-pingmessages");
}
maintenance = config.getBoolean("maintenance-enabled");
commandsOnMaintenanceEnable = config.getStringList("commands-on-maintenance-enable");
commandsOnMaintenanceDisable = config.getStringList("commands-on-maintenance-disable");
customPlayerCountMessage = config.getBoolean("enable-playercountmessage");
customMaintenanceIcon = config.getBoolean("custom-maintenance-icon");
joinNotifications = config.getBoolean("send-join-notification");
broadcastIntervals = new HashSet<>(config.getIntList("timer-broadcast-for-seconds"));
if (plugin.getServerType() != ServerType.SPONGE)
if (plugin.getServerType() != ServerType.SPONGE) {
playerCountMessage = getColoredString(getConfigString("playercountmessage"));
playerCountHoverMessage = getColoredString(getConfigString("playercounthovermessage"));
}
playerCountHoverMessage = replaceNewlineVar(getColoredString(getConfigString("playercounthovermessage")));
languageName = getConfigString("language").toLowerCase();
kickOnlinePlayers = config.getBoolean("kick-online-players", true);
updateChecks = config.getBoolean("update-checks", true);
debug = config.getBoolean("debug");
final ConfigSection section = config.getSection("continue-endtimer-after-restart");
saveEndtimerOnStop = section.getBoolean("enabled");
savedEndtimer = section.getLong("end");
if (customMaintenanceIcon) {
plugin.loadMaintenanceIcon();
}
@@ -180,39 +209,33 @@ public class Settings implements ISettings {
plugin.getLogger().warning("invalid WhitelistedPlayers entry: " + entry.getKey());
}
}
loadExtraSettings();
}
private void updatePluginDirectory() {
// All plugin identifiers were changed to 'Maintenance' ('maintenance' for Sponge and Velocity) in 3.0.5
// Don't worry, this is only checked if no plugin folder is found
String oldDirName = "Maintenance" + plugin.getServerType();
if (plugin.getServerType() == ServerType.SPONGE || plugin.getServerType() == ServerType.VELOCITY) {
oldDirName = oldDirName.toLowerCase();
}
final File oldDir = new File(plugin.getDataFolder().getParentFile(), oldDirName);
if (!oldDir.exists()) return;
try {
Files.move(oldDir.toPath(), plugin.getDataFolder().toPath());
plugin.getLogger().info("Moved old " + oldDirName + " to new " + plugin.getDataFolder().getName() + " directory!");
} catch (final IOException e) {
plugin.getLogger().severe("Error while copying " + oldDirName + " to new " + plugin.getDataFolder().getName() + " directory!");
e.printStackTrace();
}
}
private void updateConfig() {
boolean changed = false;
// 3.0 - update config format from 2.5
if (migrateConfig(new File(plugin.getDataFolder(), "bungee-config.yml"))
|| migrateConfig(new File(plugin.getDataFolder(), "spigot-config.yml"))) {
// Also rename old language file
final File file = new File(plugin.getDataFolder(), "language-" + languageName + ".yml");
if (file.exists()) {
if (file.renameTo(new File(plugin.getDataFolder(), "language-" + languageName + ".old")))
plugin.getLogger().info("Renamed old language file!");
else
plugin.getLogger().warning("Could not rename old language file! Please rename/delete it yourself as soon as possible!");
}
changed = true;
}
// 3.0 - move SpigotServer.yml fields to config
if (plugin.getServerType() == ServerType.BUNGEE && migrateSpigotServersFile()) {
changed = true;
}
// 3.0 - move maintenace-icon from server to plugin directory
final File icon = new File("maintenance-icon.png");
if (icon.exists()) {
if (icon.renameTo(new File(plugin.getDataFolder(), "maintenance-icon.png")))
plugin.getLogger().info("Moved maintenance-icon from server directory to the plugin's directory!");
else
plugin.getLogger().warning("Could not move maintenance-icon from server directory to the plugin's directory! Please do so yourself!");
}
// Update config to latest version (config version included since 3.0.1)
if (config.getInt("config-version") != CURRENT_CONFIG_VERSION) {
plugin.getLogger().info("Updating config to latest version...");
@@ -241,16 +264,19 @@ public class Settings implements ISettings {
}
private void updateLanguageFile() {
final String s = "language-" + languageName;
final String filePrefix = "language-" + languageName;
try {
createFile(s + "-new.yml", s + ".yml");
} catch (final IllegalArgumentException e) {
plugin.getLogger().warning("Couldn't update language file, as the " + s + ".yml wasn't found in the resource files!");
createFile(filePrefix + "-new.yml", filePrefix + ".yml");
} catch (final NullPointerException e) {
plugin.getLogger().info("Not checking for updated language strings, since there is no " + filePrefix + ".yml in the resource files (if your file is self translated and up to date, you can ignore this).");
return;
} catch (final Exception e) {
plugin.getLogger().warning("Couldn't update language file, as the " + filePrefix + ".yml could not be loaded from the resource files!");
e.printStackTrace();
return;
}
final File file = new File(plugin.getDataFolder(), s + "-new.yml");
final File file = new File(plugin.getDataFolder(), filePrefix + "-new.yml");
final Config tempConfig = new Config(file);
try {
tempConfig.load();
@@ -265,70 +291,13 @@ public class Settings implements ISettings {
if (updated) {
try {
language.save();
plugin.getLogger().info("Updated language file!");
} catch (final IOException e) {
e.printStackTrace();
return;
}
plugin.getLogger().info("Updated language file!");
}
}
private boolean migrateConfig(final File file) {
if (!file.exists()) return false;
plugin.getLogger().info("Migrating old config to new format...");
final Config oldConfig = new Config(file);
try {
oldConfig.load();
} catch (final IOException e) {
plugin.getLogger().log(Level.WARNING, "Error while trying to migrate old config file");
e.printStackTrace();
return false;
}
if (oldConfig.contains("pingmessage"))
config.set("pingmessages", Arrays.asList(oldConfig.getString("pingmessage")));
if (oldConfig.contains("enable-maintenance-mode"))
config.set("maintenance-enabled", oldConfig.getBoolean("enable-maintenance-mode"));
for (final Map.Entry<String, Object> entry : config.getValues().entrySet()) {
if (!oldConfig.contains(entry.getKey())) continue;
entry.setValue(oldConfig.get(entry.getKey()));
}
oldConfig.clear();
if (!file.delete())
plugin.getLogger().warning("Could not delete old config file! Please delete it as soon as possible.");
else
plugin.getLogger().info("Updated to new config file!");
return true;
}
private boolean migrateSpigotServersFile() {
final File file = new File(plugin.getDataFolder(), "SpigotServers.yml");
if (!file.exists()) return false;
final Config oldFile = new Config(file);
try {
oldFile.load();
} catch (final IOException e) {
plugin.getLogger().log(Level.WARNING, "Error while trying to migrate old SpigotServers file");
e.printStackTrace();
return false;
}
if (oldFile.contains("maintenance-on"))
config.set("proxied-maintenance-servers", oldFile.getStringList("maintenance-on"));
if (oldFile.contains("fallback"))
config.set("fallback", oldFile.getString("fallback"));
oldFile.clear();
if (!file.delete())
plugin.getLogger().warning("Could not delete old SpigotServers.yml file! Please delete it as soon as possible.");
else
plugin.getLogger().info("Deleted old SpigotServers.yml file!");
return true;
}
private static final String ALL_CODES = "0123456789AaBbCcDdEeFfKkLlMmNnOoRr";
public String getColoredString(final String s) {
@@ -344,11 +313,12 @@ public class Settings implements ISettings {
}
public String getConfigString(final String path) {
if (!config.contains(path)) {
final String s = config.getString(path);
if (s == null) {
plugin.getLogger().warning("The config is missing the following string: " + path);
return "null";
}
return config.getString(path);
return s;
}
public String getMessage(final String path) {
@@ -356,11 +326,12 @@ public class Settings implements ISettings {
}
public String getMessage(final String path, final String def) {
if (!language.contains(path)) {
final String s = language.getString(path);
if (s == null) {
plugin.getLogger().warning("The language file is missing the following string: " + path);
return def;
}
return language.getString(path);
return s;
}
public String getRandomPingMessage() {
@@ -373,7 +344,7 @@ public class Settings implements ISettings {
private String getPingMessage(final List<String> list) {
final String s = list.size() == 1 ? list.get(0) : list.get(RANDOM.nextInt(list.size()));
return getColoredString(plugin.formatedTimer(s).replace("%NEWLINE%", "\n"));
return getColoredString(replaceNewlineVar(plugin.replacePingVariables(s)));
}
@Override
@@ -395,6 +366,7 @@ public class Settings implements ISettings {
break;
}
}
if (uuid == null) return false;
whitelistedPlayers.remove(uuid);
@@ -417,6 +389,11 @@ public class Settings implements ISettings {
return whitelistedPlayers;
}
@Override
public boolean isWhitelisted(final UUID uuid) {
return whitelistedPlayers.containsKey(uuid);
}
@Override
public boolean isMaintenance() {
return maintenance;
@@ -426,6 +403,11 @@ public class Settings implements ISettings {
this.maintenance = maintenance;
}
@Override
public boolean isEnablePingMessages() {
return enablePingMessages;
}
@Override
public boolean isJoinNotifications() {
return joinNotifications;
@@ -472,13 +454,20 @@ public class Settings implements ISettings {
return config;
}
// The ping messages still contain the %NEWLINE% (if they have 2 lines)
public List<String> getPingMessages() {
return pingMessages;
}
/**
* May be null
*/
public List<String> getCommandsOnMaintenanceEnable() {
return commandsOnMaintenanceEnable;
}
public List<String> getCommandsOnMaintenanceDisable() {
return commandsOnMaintenanceDisable;
}
@Nullable
public List<String> getTimerSpecificPingMessages() {
return timerSpecificPingMessages;
}
@@ -488,15 +477,15 @@ public class Settings implements ISettings {
}
public String getPlayerCountMessage() {
return plugin.formatedTimer(playerCountMessage);
return plugin.replacePingVariables(playerCountMessage);
}
public String getPlayerCountHoverMessage() {
return plugin.formatedTimer(playerCountHoverMessage);
return plugin.replacePingVariables(playerCountHoverMessage);
}
public String getKickMessage() {
return plugin.formatedTimer(getMessage("kickmessage", "§cThe server is currently under maintenance!%NEWLINE%§cTry again later!").replace("%NEWLINE%", "\n"));
return plugin.replacePingVariables(getMessage("kickmessage"));
}
public String getLanguage() {
@@ -507,6 +496,20 @@ public class Settings implements ISettings {
return customPlayerCountMessage;
}
/*
* Note on why this even exists: Yaml will force save all strings containing line breaks '\n' in this rather chunky format:
* key: |-
* First line text
* Second line text.
* ...
*
* This also happens to string lists, making those practically unreadable (in partciular the motd list), as well as confusing for most users in general.
* Because of this, I replace %NEWLINE% manually, to spare users from these ugly breaks.
*/
protected String replaceNewlineVar(final String s) {
return s.replace("%NEWLINE%", "\n");
}
protected void loadExtraSettings() {
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,12 +15,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.util.SenderInfo;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
@@ -29,18 +29,28 @@ public abstract class CommandInfo {
protected final MaintenancePlugin plugin;
private final String helpMessageKey;
private final String permission;
private final boolean visible;
protected CommandInfo(final MaintenancePlugin plugin, final String permission) {
protected CommandInfo(final MaintenancePlugin plugin, @Nullable final String permission) {
this(plugin, permission, true);
}
protected CommandInfo(final MaintenancePlugin plugin, @Nullable final String permission, final boolean visible) {
this.plugin = plugin;
this.permission = permission;
// Just take the class name as the language key
this.helpMessageKey = "help" + getClass().getSimpleName().replace("Command", "");
this.visible = visible;
}
public boolean hasPermission(final SenderInfo sender) {
return sender.hasMaintenancePermission(permission);
}
public boolean isVisible() {
return visible;
}
public String getHelpMessage() {
return getMessage(helpMessageKey);
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,16 +15,34 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.command.subcommand.*;
import eu.kennytv.maintenance.core.command.subcommand.AbortTimerCommand;
import eu.kennytv.maintenance.core.command.subcommand.DebugCommand;
import eu.kennytv.maintenance.core.command.subcommand.DumpCommand;
import eu.kennytv.maintenance.core.command.subcommand.EndtimerCommand;
import eu.kennytv.maintenance.core.command.subcommand.HelpCommand;
import eu.kennytv.maintenance.core.command.subcommand.MotdCommand;
import eu.kennytv.maintenance.core.command.subcommand.ReloadCommand;
import eu.kennytv.maintenance.core.command.subcommand.RemoveMotdCommand;
import eu.kennytv.maintenance.core.command.subcommand.ScheduleTimerCommand;
import eu.kennytv.maintenance.core.command.subcommand.SetMotdCommand;
import eu.kennytv.maintenance.core.command.subcommand.StarttimerCommand;
import eu.kennytv.maintenance.core.command.subcommand.ToggleCommand;
import eu.kennytv.maintenance.core.command.subcommand.UpdateCommand;
import eu.kennytv.maintenance.core.command.subcommand.WhitelistAddCommand;
import eu.kennytv.maintenance.core.command.subcommand.WhitelistCommand;
import eu.kennytv.maintenance.core.command.subcommand.WhitelistRemoveCommand;
import eu.kennytv.maintenance.core.util.SenderInfo;
import eu.kennytv.maintenance.core.util.ServerType;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public abstract class MaintenanceCommand {
protected final MaintenancePlugin plugin;
@@ -55,6 +73,7 @@ public abstract class MaintenanceCommand {
add(new UpdateCommand(plugin), "update", "forceupdate");
add(new DumpCommand(plugin), "dump");
add(new DebugCommand(plugin), "debug");
}
protected void add(final CommandInfo command, final String... aliases) {
@@ -94,7 +113,8 @@ public abstract class MaintenanceCommand {
final List<String> list = new ArrayList<>();
for (final Map.Entry<String, CommandInfo> entry : commandExecutors.entrySet()) {
final String command = entry.getKey();
if (command.startsWith(s) && entry.getValue().hasPermission(sender)) {
final CommandInfo info = entry.getValue();
if (info.isVisible() && command.startsWith(s) && info.hasPermission(sender)) {
list.add(command);
}
}
@@ -120,7 +140,7 @@ public abstract class MaintenanceCommand {
return true;
}
if (minutes < 1) {
sender.sendMessage("§8§o[KennyTV whispers to you] §7§oThink about running a timer for a negative amount of minutes. Doesn't work §lthat §7§owell.");
sender.sendMessage("§8§o[kennytv whispers to you] §7§oThink about running a timer for a negative amount of minutes. Doesn't work §lthat §7§owell.");
return true;
}
return false;
@@ -135,6 +155,7 @@ public abstract class MaintenanceCommand {
add(new StarttimerCommand(plugin), "starttimer", "start");
add(new EndtimerCommand(plugin), "endtimer", "end");
add(new ScheduleTimerCommand(plugin), "scheduletimer", "schedule");
add(new AbortTimerCommand(plugin), "aborttimer", "abort");
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -0,0 +1,37 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
public final class DebugCommand extends CommandInfo {
public DebugCommand(final MaintenancePlugin plugin) {
super(plugin, "debug", false);
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 1)) return;
plugin.setDebug(!plugin.isDebug());
sender.sendMessage("Debug mode is now " + (plugin.isDebug() ? "enabled" : "disabled"));
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -44,15 +43,17 @@ public final class DumpCommand extends CommandInfo {
plugin.async(() -> {
final String key = plugin.pasteDump();
if (key == null) {
if (sender.isPlayer())
if (sender.isPlayer()) {
sender.sendMessage(plugin.getPrefix() + "§cCould not paste dump (see the console for details)");
}
return;
}
final String url = "https://hasteb.in/" + key;
final String url = "https://hastebin.com/" + key;
sender.sendMessage(plugin.getPrefix() + "§c" + url);
if (sender.isPlayer())
if (sender.isPlayer()) {
plugin.getCommandManager().sendDumpMessage(sender, url);
}
});
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,13 +15,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.concurrent.TimeUnit;
public final class EndtimerCommand extends CommandInfo {
public EndtimerCommand(final MaintenancePlugin plugin) {
@@ -40,7 +41,7 @@ public final class EndtimerCommand extends CommandInfo {
return;
}
plugin.startMaintenanceRunnableForMinutes(Integer.parseInt(args[1]), false);
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), TimeUnit.MINUTES, false);
sender.sendMessage(getMessage("endtimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import com.google.common.base.Preconditions;
@@ -42,15 +41,16 @@ public final class HelpCommand extends CommandInfo {
if (args.length == 1) {
sendUsage(sender);
} else {
if (!plugin.isNumeric(args[1])) {
sender.sendMessage(getHelpMessage());
return;
}
final int page = Integer.parseInt(args[1]);
sendUsage(sender, page == 0 ? 1 : page);
return;
}
if (!plugin.isNumeric(args[1])) {
sender.sendMessage(getHelpMessage());
return;
}
final int page = Integer.parseInt(args[1]);
sendUsage(sender, page == 0 ? 1 : page);
}
public void sendUsage(final SenderInfo sender) {
@@ -61,7 +61,7 @@ public final class HelpCommand extends CommandInfo {
Preconditions.checkArgument(page > 0);
final List<String> commands = new ArrayList<>();
for (final CommandInfo cmd : plugin.getCommandManager().getCommands()) {
if (cmd.hasPermission(sender)) {
if (cmd.isVisible() && cmd.hasPermission(sender)) {
commands.add(cmd.getHelpMessage());
}
}
@@ -70,11 +70,7 @@ public final class HelpCommand extends CommandInfo {
return;
}
final List<String> filteredCommands;
if (page * COMMANDS_PER_PAGE >= commands.size())
filteredCommands = commands.subList((page - 1) * COMMANDS_PER_PAGE, commands.size());
else
filteredCommands = commands.subList((page - 1) * COMMANDS_PER_PAGE, page * COMMANDS_PER_PAGE);
final List<String> filteredCommands = commands.subList((page - 1) * COMMANDS_PER_PAGE, Math.min(page * COMMANDS_PER_PAGE, commands.size()));
final String header = getMessage("helpHeader").replace("%NAME%", "Maintenance" + plugin.getServerType())
.replace("%PAGE%", Integer.toString(page)).replace("%MAX%", Integer.toString((commands.size() + getDivide(commands.size())) / COMMANDS_PER_PAGE));
@@ -83,10 +79,13 @@ public final class HelpCommand extends CommandInfo {
for (final String command : filteredCommands) {
sender.sendMessage(command);
}
if (page * COMMANDS_PER_PAGE < commands.size())
if (page * COMMANDS_PER_PAGE < commands.size()) {
sender.sendMessage(getMessage("helpNextPage").replace("%PAGE%", Integer.toString(page + 1)));
else
sender.sendMessage("§8× §eVersion " + plugin.getVersion() + " §7by §bKennyTV");
} else {
sender.sendMessage("§8× §eVersion " + plugin.getVersion() + " §7by §bkennytv");
}
sender.sendMessage(header);
sender.sendMessage("");
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -42,8 +41,9 @@ public final class MotdCommand extends CommandInfo {
}
sendList(sender, getSettings().getTimerSpecificPingMessages());
} else
} else {
sender.sendMessage(getHelpMessage());
}
}
private void sendList(final SenderInfo sender, final List<String> list) {
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -77,7 +76,7 @@ public final class RemoveMotdCommand extends CommandInfo {
final int size = (args.length == 3 ? plugin.getSettings().getTimerSpecificPingMessages() : plugin.getSettings().getPingMessages()).size();
final List<String> list = new ArrayList<>(size);
for (int i = 1; i <= size; i++) {
list.add(String.valueOf(i));
list.add(Integer.toString(i));
}
return list;
}
@@ -0,0 +1,48 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.concurrent.TimeUnit;
public final class ScheduleTimerCommand extends CommandInfo {
public ScheduleTimerCommand(final MaintenancePlugin plugin) {
super(plugin, "timer");
}
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 3)) 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()));
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -83,10 +82,12 @@ public final class SetMotdCommand extends CommandInfo {
oldMessage.split("%NEWLINE%", 2)[0] + "%NEWLINE%" + message : oldMessage + "%NEWLINE%" + message;
}
if (index > pingMessages.size())
if (index > pingMessages.size()) {
pingMessages.add(newMessage);
else
} else {
pingMessages.set(index - 1, newMessage);
}
settings.getConfig().set(timerPingMessages ? "timerspecific-pingmessages" : "pingmessages", pingMessages);
settings.saveConfig();
sender.sendMessage(settings.getMessage("setMotd").replace("%LINE%", args[2]).replace("%INDEX%", args[1])
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,13 +15,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.concurrent.TimeUnit;
public final class StarttimerCommand extends CommandInfo {
public StarttimerCommand(final MaintenancePlugin plugin) {
@@ -40,7 +41,7 @@ public final class StarttimerCommand extends CommandInfo {
return;
}
plugin.startMaintenanceRunnableForMinutes(Integer.parseInt(args[1]), true);
plugin.startMaintenanceRunnable(Integer.parseInt(args[1]), TimeUnit.MINUTES, true);
sender.sendMessage(getMessage("starttimerStarted").replace("%TIME%", plugin.getRunnable().getTime()));
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -46,10 +45,11 @@ public final class UpdateCommand extends CommandInfo {
}
sender.sendMessage(getMessage("updateDownloading"));
if (plugin.installUpdate())
if (plugin.installUpdate()) {
sender.sendMessage(getMessage("updateFinished"));
else
} else {
sender.sendMessage(getMessage("updateFailed"));
}
}
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,11 +15,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.command.CommandInfo;
import eu.kennytv.maintenance.core.util.DummySenderInfo;
import eu.kennytv.maintenance.core.util.SenderInfo;
import java.util.Collections;
@@ -34,13 +34,28 @@ public final class WhitelistAddCommand extends CommandInfo {
@Override
public void execute(final SenderInfo sender, final String[] args) {
if (checkArgs(sender, args, 2)) return;
if (args[1].length() == 36) {
if (args.length == 2) {
if (args[1].length() == 36) {
final UUID uuid = plugin.checkUUID(sender, args[1]);
if (uuid != null) {
addPlayerToWhitelist(sender, uuid);
}
} else {
addPlayerToWhitelist(sender, args[1]);
}
} else if (args.length == 3) {
if (args[1].length() != 36) {
sender.sendMessage(getHelpMessage());
return;
}
final UUID uuid = plugin.checkUUID(sender, args[1]);
if (uuid != null)
addPlayerToWhitelist(sender, uuid);
} else
addPlayerToWhitelist(sender, args[1]);
if (uuid != null) {
addPlayerToWhitelist(sender, new DummySenderInfo(uuid, args[2]));
}
} else {
sender.sendMessage(getHelpMessage());
}
}
@Override
@@ -55,7 +70,7 @@ public final class WhitelistAddCommand extends CommandInfo {
return;
}
whitelistAddMessage(sender, selected);
addPlayerToWhitelist(sender, selected);
}
private void addPlayerToWhitelist(final SenderInfo sender, final UUID uuid) {
@@ -65,13 +80,14 @@ public final class WhitelistAddCommand extends CommandInfo {
return;
}
whitelistAddMessage(sender, selected);
addPlayerToWhitelist(sender, selected);
}
private void whitelistAddMessage(final SenderInfo sender, final SenderInfo selected) {
if (getSettings().addWhitelistedPlayer(selected.getUuid(), selected.getName()))
private void addPlayerToWhitelist(final SenderInfo sender, final SenderInfo selected) {
if (getSettings().addWhitelistedPlayer(selected.getUuid(), selected.getName())) {
sender.sendMessage(getMessage("whitelistAdded").replace("%PLAYER%", selected.getName()));
else
} else {
sender.sendMessage(getMessage("whitelistAlreadyAdded").replace("%PLAYER%", selected.getName()));
}
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -38,13 +37,15 @@ public final class WhitelistCommand extends CommandInfo {
final Map<UUID, String> players = getSettings().getWhitelistedPlayers();
if (players.isEmpty()) {
sender.sendMessage(getMessage("whitelistEmpty"));
} else {
sender.sendMessage(getMessage("whitelistedPlayers"));
final String format = getMessage("whitelistedPlayersFormat");
for (final Map.Entry<UUID, String> entry : players.entrySet()) {
sender.sendMessage(format.replace("%NAME%", entry.getValue()).replace("%UUID%", entry.getKey().toString()));
}
sender.sendMessage("");
return;
}
sender.sendMessage(getMessage("whitelistedPlayers"));
final String format = getMessage("whitelistedPlayersFormat");
for (final Map.Entry<UUID, String> entry : players.entrySet()) {
sender.sendMessage(format.replace("%NAME%", entry.getValue()).replace("%UUID%", entry.getKey().toString()));
}
sender.sendMessage("");
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.command.subcommand;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -38,10 +37,12 @@ public final class WhitelistRemoveCommand extends CommandInfo {
if (checkArgs(sender, args, 2)) return;
if (args[1].length() == 36) {
final UUID uuid = plugin.checkUUID(sender, args[1]);
if (uuid != null)
if (uuid != null) {
removePlayerFromWhitelist(sender, uuid);
} else
}
} else {
removePlayerFromWhitelist(sender, args[1]);
}
}
@Override
@@ -60,28 +61,31 @@ public final class WhitelistRemoveCommand extends CommandInfo {
private void removePlayerFromWhitelist(final SenderInfo sender, final String name) {
final SenderInfo selected = plugin.getOfflinePlayer(name);
if (selected == null) {
if (getSettings().removeWhitelistedPlayer(name))
if (getSettings().removeWhitelistedPlayer(name)) {
sender.sendMessage(getMessage("whitelistRemoved").replace("%PLAYER%", name));
else
} else {
sender.sendMessage(getMessage("whitelistNotFound"));
}
return;
}
whitelistRemoveMessage(sender, selected.getUuid(), selected.getName());
removePlayerFromWhitelist(sender, selected.getUuid(), selected.getName());
}
private void removePlayerFromWhitelist(final SenderInfo sender, final UUID uuid) {
final SenderInfo selected = plugin.getOfflinePlayer(uuid);
if (selected == null)
whitelistRemoveMessage(sender, uuid, uuid.toString());
else
whitelistRemoveMessage(sender, selected.getUuid(), selected.getName());
if (selected == null) {
removePlayerFromWhitelist(sender, uuid, uuid.toString());
} else {
removePlayerFromWhitelist(sender, selected.getUuid(), selected.getName());
}
}
private void whitelistRemoveMessage(final SenderInfo sender, final UUID uuid, final String toReplace) {
if (getSettings().removeWhitelistedPlayer(uuid))
private void removePlayerFromWhitelist(final SenderInfo sender, final UUID uuid, final String toReplace) {
if (getSettings().removeWhitelistedPlayer(uuid)) {
sender.sendMessage(getMessage("whitelistRemoved").replace("%PLAYER%", toReplace));
else
} else {
sender.sendMessage(getMessage("whitelistNotFound"));
}
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,10 +15,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.config;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.Nullable;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
@@ -26,13 +26,17 @@ import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* Further modified version of the SimpleConfig project of PSandro (https://github.com/PSandro/SimpleConfig).
*
* @author PSandro on 26.01.19
* @author KennyTV
* @author kennytv
*/
public final class Config extends ConfigSection {
@@ -45,7 +49,7 @@ public final class Config extends ConfigSection {
"# |_| |_|\\__,_|_|_| |_|\\__\\___|_| |_|\\__,_|_| |_|\\___\\___| |_.__/ \\__, | |_|\\_\\___|_| |_|_| |_|\\__, ||_| \\_/ #\n" +
"# |___/ |___/ #\n" +
"#######################################################################################################################\n" +
"# You can report bugs here: https://github.com/KennyTV/Maintenance/issues\n" +
"# You can report bugs here: https://github.com/kennytv/Maintenance/issues\n" +
"# If you need any other help/support, you can also join my Discord server: https://discord.gg/vGCUzHq\n";
private final Yaml yaml = createYaml();
private final File file;
@@ -54,6 +58,7 @@ public final class Config extends ConfigSection {
private String header;
public Config(final File file, final String... unsupportedFields) {
super(null, "");
this.file = file;
this.unsupportedFields = unsupportedFields.length == 0 ? Collections.emptySet() : Sets.newHashSet(unsupportedFields);
}
@@ -63,26 +68,27 @@ public final class Config extends ConfigSection {
final Map<String, Object> map = yaml.load(data);
this.values = map != null ? map : new LinkedHashMap<>();
this.comments = ConfigSerializer.deserializeComments(data);
if (comments.containsKey(".header"))
this.header = String.join("\n", comments.remove(".header"));
final String[] header = comments.remove(".header");
if (header != null) {
this.header = String.join("\n", header);
}
final boolean removedFields = values.keySet().removeIf(key -> {
final String[] split = key.split("\\.");
String splitKey = "";
boolean remove = false;
for (final String s : split) {
splitKey += s;
if (!unsupportedFields.contains(splitKey)) {
splitKey += ".";
continue;
}
remove = true;
break;
}
if (remove)
// Unsupported field
comments.remove(key);
return remove;
return true;
}
return false;
});
if (removedFields) {
save();
@@ -90,10 +96,16 @@ public final class Config extends ConfigSection {
}
public void save() throws IOException {
final byte[] bytes = this.saveConfigToString().getBytes(StandardCharsets.UTF_8);
this.file.getParentFile().mkdirs();
this.file.createNewFile();
Files.write(this.file.toPath(), bytes);
saveTo(file);
}
public void saveTo(final File file) throws IOException {
final byte[] bytes = toString().getBytes(StandardCharsets.UTF_8);
if (file.getParentFile() != null) {
file.getParentFile().mkdirs();
}
file.createNewFile();
Files.write(file.toPath(), bytes);
}
public boolean addMissingFields(final Map<String, Object> fields, final Map<String, String[]> comments) {
@@ -122,35 +134,15 @@ public final class Config extends ConfigSection {
return changed;
}
@Override
public void set(final String key, final Object value, final String... comments) {
if (value == null) {
remove(key);
} else {
this.values.put(key, value);
this.comments.put(key, comments);
}
}
@Override
public void remove(final String key) {
this.values.remove(key);
this.comments.remove(key);
}
private static Yaml createYaml() {
final DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
options.setPrettyFlow(false);
options.setIndent(2);
options.setWidth(10_000); // be sneaky because autobreak on read/save looks disgusting
options.setWidth(10_000); // be sneaky because autobreak on saving looks disgusting
return new Yaml(options);
}
public String saveConfigToString() {
return ConfigSerializer.serialize(this.header, this.values, this.comments, this.yaml);
}
public void clear() {
this.values.clear();
this.comments.clear();
@@ -165,6 +157,12 @@ public final class Config extends ConfigSection {
return unsupportedFields;
}
@Override
public Config getRoot() {
return this;
}
@Nullable
public String getHeader() {
return header;
}
@@ -172,4 +170,9 @@ public final class Config extends ConfigSection {
public void resetAwesomeHeader() {
this.header = AWESOME_HEADER;
}
@Override
public String toString() {
return ConfigSerializer.serialize(this.header, this.values, this.comments, this.yaml);
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,9 +15,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.config;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -26,35 +27,61 @@ import java.util.Set;
/**
* Further modified version of the SimpleConfig project of PSandro (https://github.com/PSandro/SimpleConfig).
*
* @author KennyTV
* @author kennytv
*/
public class ConfigSection {
protected final Config root;
protected final String currentPath;
protected Map<String, Object> values;
ConfigSection() {
this(new HashMap<>());
ConfigSection(final Config root, final String currentPath) {
this(root, currentPath, new HashMap<>());
}
ConfigSection(final Map<String, Object> values) {
ConfigSection(final Config root, final String currentPath, final Map<String, Object> values) {
this.root = root;
this.currentPath = currentPath;
this.values = values;
}
@Nullable
public <E> E get(final String key) {
return (E) this.values.get(key);
return (E) getObject(key);
}
public <E> E get(final String key, final E def) {
final Object o = this.values.get(key);
@Nullable
public <E> E get(final String key, @Nullable final E def) {
final Object o = getObject(key);
return o != null ? (E) o : def;
}
@Nullable
public Object getObject(final String key) {
return this.values.get(key);
return getObject(key, null);
}
public <E> E getOrSet(final String key, final E def) {
final Object o = this.values.get(key);
@Nullable
public Object getObject(final String key, final Object def) {
int i1 = -1;
int i2;
ConfigSection section = this;
while ((i1 = key.indexOf('.', i2 = i1 + 1)) != -1) {
section = section.getSection(key.substring(i2, i1));
if (section == null) return def;
}
final String subKey = key.substring(i2);
if (section == this) {
final Object result = values.get(subKey);
return result != null ? result : def;
}
return section.getObject(subKey, def);
}
@Nullable
public <E> E getOrSet(final String key, @Nullable final E def) {
final Object o = getObject(key);
if (o != null) {
return (E) o;
} else {
@@ -63,50 +90,29 @@ public class ConfigSection {
}
}
/**
* Convenience method, not further established as currently not necessary.
*
* @see #getSection(String)
* @deprecated this config is only made for a quite simple use, only goes one level deeper
*/
@Deprecated
public Object getDeep(final String key) {
final String[] split = key.split("\\.", 2);
if (split.length != 2) return get(key);
final Object o = getObject(split[0]);
if (!(o instanceof Map)) return null;
final Map<String, Object> map = (Map<String, Object>) o;
return map.get(split[1]);
}
@Nullable
public ConfigSection getSection(final String key) {
final Object o = getObject(key);
return o instanceof Map ? new ConfigSection((Map<String, Object>) o) : null;
if (!(o instanceof Map)) return null;
return new ConfigSection(getRoot(), getFullKeyInPath(key), (Map<String, Object>) o);
}
public boolean contains(final String key) {
return this.values.containsKey(key);
return getObject(key) != null;
}
public void set(final String key, final Object value) {
public void set(final String key, @Nullable final Object value) {
//TODO go deep if necessary
if (value == null) {
remove(key);
} else
this.values.put(key, value);
}
public void set(final String key, final Object value, final String... comments) {
if (value == null) {
remove(key);
values.remove(key);
getRoot().getComments().remove(getFullKeyInPath(key));
} else {
this.values.put(key, value);
values.put(key, value);
}
}
public void remove(final String key) {
this.values.remove(key);
set(key, null);
}
public Set<String> getKeys() {
@@ -122,16 +128,18 @@ public class ConfigSection {
}
public boolean getBoolean(final String key, final boolean def) {
final Object o = values.get(key);
final Object o = getObject(key);
return o instanceof Boolean ? (boolean) o : def;
}
@Nullable
public String getString(final String key) {
return get(key);
}
public String getString(final String key, final String def) {
final Object o = get(key);
@Nullable
public String getString(final String key, @Nullable final String def) {
final Object o = getObject(key);
return o instanceof String ? (String) o : def;
}
@@ -140,7 +148,7 @@ public class ConfigSection {
}
public int getInt(final String key, final int def) {
final Object o = values.get(key);
final Object o = getObject(key);
return o instanceof Number ? ((Number) o).intValue() : def;
}
@@ -149,7 +157,7 @@ public class ConfigSection {
}
public double getDouble(final String key, final double def) {
final Object o = values.get(key);
final Object o = getObject(key);
return o instanceof Number ? ((Number) o).doubleValue() : def;
}
@@ -158,23 +166,47 @@ public class ConfigSection {
}
public long getLong(final String key, final long def) {
final Object o = values.get(key);
final Object o = getObject(key);
return o instanceof Number ? ((Number) o).longValue() : def;
}
@Nullable
public List<String> getStringList(final String key) {
return get(key);
}
public List<String> getStringList(final String key, final List<String> def) {
return values.containsKey(key) ? get(key) : def;
@Nullable
public List<String> getStringList(final String key, @Nullable final List<String> def) {
final List<String> list = get(key);
return list != null ? list : def;
}
@Nullable
public List<Integer> getIntList(final String key) {
return get(key);
}
public List<Integer> getIntList(final String key, final List<Integer> def) {
return values.containsKey(key) ? get(key) : def;
@Nullable
public List<Integer> getIntList(final String key, @Nullable final List<Integer> def) {
final List<Integer> list = get(key);
return list != null ? list : def;
}
/**
* @return root config
*/
public Config getRoot() {
return root;
}
/**
* @return current path, or empty string if root
*/
public String getCurrentPath() {
return currentPath;
}
protected String getFullKeyInPath(final String key) {
return currentPath.isEmpty() ? key : currentPath + "." + key;
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.config;
import org.yaml.snakeyaml.Yaml;
@@ -30,7 +29,7 @@ import java.util.regex.Pattern;
* Further modified version of the SimpleConfig project of PSandro (https://github.com/PSandro/SimpleConfig).
*
* @author PSandro on 26.01.19
* @author KennyTV
* @author kennytv
*/
public final class ConfigSerializer {
@@ -40,7 +39,9 @@ public final class ConfigSerializer {
private static final int INDENT_UNIT = 2;
public static String serialize(final String header, final Map<String, Object> data, final Map<String, String[]> comments, final Yaml yaml) {
if (data.isEmpty()) return yaml.dump(null);
if (data.isEmpty()) {
return yaml.dump(null);
}
final String rawYaml = yaml.dump(data);
final StringBuilder fileData = new StringBuilder();
@@ -61,46 +62,60 @@ public final class ConfigSerializer {
key = join(array, array.length - backspace);
keyLine = true;
} else {
keyLine = line.contains(":");
keyLine = line.indexOf(':') != -1;
}
if (keyLine) {
final String newKey = substring.split(Pattern.quote(":"))[0]; // Not sure about the quote thing, so I'll just keep it :aaa:
if (!key.isEmpty())
key += PATH_SEPARATOR_STRING;
key += newKey;
if (!keyLine) {
// Nothing to do, go to next line
fileData.append(line).append('\n');
continue;
}
final String newKey = substring.split(Pattern.quote(":"))[0]; // Not sure about the quote thing, so I'll just keep it :aaa:
if (!key.isEmpty()) {
key += PATH_SEPARATOR_STRING;
}
key += newKey;
// Add comments if present
if (comments != null) {
final String[] strings = comments.get(key);
if (strings != null) {
final String indentText = indent > 0 ? line.substring(0, indent) : "";
for (final String comment : strings) {
if (comment.isEmpty())
if (comment.isEmpty()) {
fileData.append('\n');
else
} else {
fileData.append(indentText).append(comment).append('\n');
}
}
}
currentKeyIndents = indents;
}
currentKeyIndents = indents;
fileData.append(line).append('\n');
}
return header != null && !header.isEmpty() ? header + fileData : fileData.toString();
}
public static Map<String, String[]> deserializeComments(final String data) {
//TODO go through known yaml keys and figure out comments from there instead of from line to line?
// ... tho everything here would benefit from a cleanup
final Map<String, String[]> comments = new HashMap<>();
final List<String> currentComments = new ArrayList<>();
boolean header = true;
boolean multiLineValue = false;
int currentIndents = 0;
String key = "";
for (final String line : data.split("\n")) {
final String s = line.trim();
// It's a comment!
if (s.startsWith("#")) {
currentComments.add(s);
continue;
}
// Header is over - save it!
if (header) {
if (!currentComments.isEmpty()) {
currentComments.add("");
@@ -109,21 +124,39 @@ public final class ConfigSerializer {
}
header = false;
}
// Save empty lines as well
if (s.isEmpty()) {
currentComments.add(s);
continue;
}
// Multi line values?
if (s.startsWith("- |")) {
multiLineValue = true;
continue;
}
final int indent = getIndents(line);
final int indents = indent / INDENT_UNIT;
// Check if the multi line value is over
if (multiLineValue) {
if (indents > currentIndents) continue;
multiLineValue = false;
}
// Check if this is a level lower
if (indents <= currentIndents) {
final String[] array = key.split(PATH_SEPARATOR_QUOTED);
final int backspace = currentIndents - indents + 1;
key = join(array, array.length - backspace);
final int delta = array.length - backspace;
key = delta >= 0 ? join(array, delta) : key;
}
// Finish current key
final String separator = key.isEmpty() ? "" : PATH_SEPARATOR_STRING;
final String lineKey = line.contains(":") ? line.split(Pattern.quote(":"))[0] : line;
final String lineKey = line.indexOf(':') != -1 ? line.split(Pattern.quote(":"))[0] : line;
key += separator + lineKey.substring(indent);
currentIndents = indents;
@@ -138,8 +171,11 @@ public final class ConfigSerializer {
private static int getIndents(final String line) {
int count = 0;
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == ' ') count++;
else break;
if (line.charAt(i) != ' ') {
break;
}
count++;
}
return count;
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,10 +15,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.dump;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
@@ -46,7 +44,7 @@ public final class MaintenanceDump {
configuration.put("icon-exists", new File(plugin.getDataFolder(), "maintenance-icon.png").exists());
final JsonObject jsonObject = new JsonObject();
jsonObject.add("plugins", new GsonBuilder().create().toJsonTree(plugin.getPlugins()));
jsonObject.add("plugins", MaintenancePlugin.GSON.toJsonTree(plugin.getPlugins()));
plugins = jsonObject;
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.dump;
import java.util.List;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.dump;
import java.util.List;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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.event;
import eu.kennytv.maintenance.api.event.manager.EventListener;
@@ -35,6 +34,7 @@ public final class EventManager implements IEventManager {
listeners.computeIfAbsent(eventClass.getSimpleName(), s -> new ArrayList<>()).add(listener);
}
@Override
public void callEvent(final MaintenanceEvent event) {
final List<EventListener> list = listeners.get(event.getClass().getSimpleName());
if (list != null) {
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.hook;
import net.minecrell.serverlistplus.core.ServerListPlusCore;
@@ -25,8 +24,9 @@ public final class ServerListPlusHook {
private final ServerListPlusCore serverListPlusCore;
public ServerListPlusHook(final Object serverListPlus) {
if (!(serverListPlus instanceof ServerListPlusPlugin))
if (!(serverListPlus instanceof ServerListPlusPlugin)) {
throw new IllegalArgumentException("Couldn't parse ServerListPlus instance!");
}
this.serverListPlusCore = ((ServerListPlusPlugin) serverListPlus).getCore();
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.listener;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -29,7 +28,6 @@ import java.util.UUID;
public abstract class JoinListenerBase {
protected final MaintenancePlugin plugin;
protected final Settings settings;
protected final UUID notifyUuid = new UUID(-6334418481592579467L, -4779835342378829761L);
private final Set<UUID> notifiedPlayers = new HashSet<>();
protected JoinListenerBase(final MaintenancePlugin plugin, final Settings settings) {
@@ -43,30 +41,27 @@ public abstract class JoinListenerBase {
* @param sender wrapper of the joining player
* @return true if the sender should be kicked
*/
protected boolean kickPlayer(final SenderInfo sender, final boolean updateCheck) {
if (settings.isMaintenance() && !sender.hasMaintenancePermission("bypass") && !settings.getWhitelistedPlayers().containsKey(sender.getUuid())) {
if (settings.isJoinNotifications())
broadcastJoinNotification(sender.getName());
return true;
protected boolean shouldKick(final SenderInfo sender, final boolean updateCheck) {
if (!settings.isMaintenance() || sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.getUuid())) {
if (updateCheck) {
updateCheck(sender);
}
return false;
}
if (updateCheck)
updateCheck(sender);
return false;
return true;
}
protected boolean kickPlayer(final SenderInfo sender) {
return kickPlayer(sender, true);
protected boolean shouldKick(final SenderInfo sender) {
return shouldKick(sender, true);
}
protected void updateCheck(final SenderInfo sender) {
if (sender.getUuid().equals(notifyUuid)) {
sender.sendMessage("§6Maintenance §aVersion " + plugin.getVersion());
return;
}
if (!settings.hasUpdateChecks()) return;
if (!sender.hasPermission("maintenance.admin") || notifiedPlayers.contains(sender.getUuid())) return;
plugin.async(() -> {
if (!plugin.updateAvailable()) return;
notifiedPlayers.add(sender.getUuid());
sender.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + plugin.getNewestVersion() + "§c, you're on §a" + plugin.getVersion());
plugin.sendUpdateNotification(sender);
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,13 +15,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.runnable;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
public final class MaintenanceRunnable extends MaintenanceRunnableBase {
public class MaintenanceRunnable extends MaintenanceRunnableBase {
public MaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final boolean enable) {
super(plugin, settings, seconds, enable);
@@ -33,12 +32,12 @@ public final class MaintenanceRunnable extends MaintenanceRunnableBase {
}
@Override
protected String startMessageKey() {
protected String getStartMessage() {
return settings.getMessage("starttimerBroadcast").replace("%TIME%", getTime());
}
@Override
protected String endMessageKey() {
protected String getEndMessage() {
return settings.getMessage("endtimerBroadcast").replace("%TIME%", getTime());
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.runnable;
import eu.kennytv.maintenance.core.MaintenancePlugin;
@@ -25,8 +24,8 @@ import eu.kennytv.maintenance.core.util.Task;
public abstract class MaintenanceRunnableBase implements Runnable {
protected final MaintenancePlugin plugin;
protected final Settings settings;
protected final boolean enable;
private final Task task;
protected boolean enable;
protected int seconds;
protected MaintenanceRunnableBase(final MaintenancePlugin plugin, final Settings settings, final int seconds, final boolean enable) {
@@ -42,32 +41,14 @@ public abstract class MaintenanceRunnableBase implements Runnable {
if (seconds == 0) {
finish();
} else if (settings.getBroadcastIntervals().contains(seconds)) {
if (enable)
plugin.broadcast(startMessageKey());
else
plugin.broadcast(endMessageKey());
broadcast(enable ? getStartMessage() : getEndMessage());
}
seconds--;
}
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"));
return plugin.getFormattedTime(seconds);
}
public boolean shouldEnable() {
@@ -82,9 +63,13 @@ public abstract class MaintenanceRunnableBase implements Runnable {
return task;
}
protected void broadcast(final String message) {
plugin.broadcast(message);
}
protected abstract void finish();
protected abstract String startMessageKey();
protected abstract String getStartMessage();
protected abstract String endMessageKey();
protected abstract String getEndMessage();
}
@@ -0,0 +1,46 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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.runnable;
import eu.kennytv.maintenance.core.MaintenancePlugin;
import eu.kennytv.maintenance.core.Settings;
import java.util.concurrent.TimeUnit;
public final class MaintenanceScheduleRunnable extends MaintenanceRunnable {
private final int maintenanceDuration;
public MaintenanceScheduleRunnable(final MaintenancePlugin plugin, final Settings settings, final int secondsToEnable, final int maintenanceDuration) {
super(plugin, settings, secondsToEnable, true);
this.maintenanceDuration = maintenanceDuration;
}
@Override
protected void finish() {
super.finish();
// Start the timer to disable maintenance again
plugin.startMaintenanceRunnable(maintenanceDuration, TimeUnit.SECONDS, false);
}
@Override
protected String getStartMessage() {
return settings.getMessage("scheduletimerBroadcast")
.replace("%TIME%", getTime()).replace("%DURATION%", plugin.getFormattedTime(maintenanceDuration));
}
}
@@ -0,0 +1,54 @@
/*
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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.util;
import java.util.UUID;
public final class DummySenderInfo implements SenderInfo {
private final UUID uuid;
private final String name;
public DummySenderInfo(final UUID uuid, final String name) {
this.uuid = uuid;
this.name = name;
}
@Override
public UUID getUuid() {
return uuid;
}
@Override
public String getName() {
return name;
}
@Override
public boolean hasPermission(final String permission) {
return false;
}
@Override
public void sendMessage(final String message) {
}
@Override
public boolean isPlayer() {
return false;
}
}
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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.util;
import java.util.UUID;
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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.util;
public enum ServerType {
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,7 +15,6 @@
* 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.util;
public interface Task {
@@ -1,6 +1,6 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
* 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
@@ -15,36 +15,37 @@
* 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.util;
import com.google.common.base.Preconditions;
import org.jetbrains.annotations.Nullable;
public final class Version implements Comparable<Version> {
private final int[] parts;
private final String version;
private final String tag;
/**
* Creates a new version object to be compared.
* The version format are numbers separated by '.', possibly followed by a '-' to include an extra tag after it.
*
* @param version string representation of the version
* @throws IllegalArgumentException if the given version string is null or empty
* @throws NumberFormatException if there are non-number characters in the version (before the tag)
*/
public Version(final String version) {
if (version == null || version.isEmpty()) {
this.version = "";
tag = "";
parts = new int[0];
System.out.println("Unknown Maintenance version detected!");
return;
}
final String[] split = version.split("-", 2)[0].split("\\.");
Preconditions.checkArgument(version != null && !version.isEmpty());
final int index = version.indexOf('-');
final String[] split = (index == -1 ? version : version.substring(0, index)).split("\\.");
parts = new int[split.length];
for (int i = 0; i < split.length; i++) {
if (!split[i].matches("[0-9]+")) {
this.version = "";
tag = "";
System.out.println("Unknown Maintenance version detected!");
return;
}
// Let this throw an exception if parsing fails
parts[i] = Integer.parseInt(split[i]);
}
this.version = version;
tag = version.contains("-") ? version.split("-", 2)[1] : "";
tag = index != -1 ? version.substring(index + 1) : "";
}
/**
@@ -54,20 +55,25 @@ public final class Version implements Comparable<Version> {
* @return 0 if they are the same, 1 if this instance is newer, -1 if older
*/
@Override
public int compareTo(final Version version) {
if (version == null || version.toString() == null) return 0;
public int compareTo(@Nullable final Version version) {
if (version == null) return 0;
final int max = Math.max(this.parts.length, version.parts.length);
for (int i = 0; i < max; i++) {
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 (partA < partB) {
return -1;
} else if (partA > partB) {
return 1;
}
}
if (this.tag.isEmpty() && !version.tag.isEmpty())
if (this.tag.isEmpty() && !version.tag.isEmpty()) {
return 1;
if (!this.tag.isEmpty() && version.tag.isEmpty())
} else if (!this.tag.isEmpty() && version.tag.isEmpty()) {
return -1;
}
return 0;
}
@@ -82,7 +88,9 @@ public final class Version implements Comparable<Version> {
@Override
public boolean equals(final Object o) {
if (o == null) return false;
return o instanceof Version && o == this || version.equals(o.toString());
if (o == this) return true;
if (!(o instanceof Version)) return false;
final Version other = (Version) o;
return version.equals(other.version);
}
}
@@ -1,3 +1,3 @@
# You can add and remove players with the '/maintenance <add/remove> <name/uuid>' command.
# Alternatively, you can just add their uuid and name here by hand in the following format:
# a8179ff3-c201-4a75-bdaa-9d14aca6f83f: KennyTV
# a8179ff3-c201-4a75-bdaa-9d14aca6f83f: kennytv
+19 -6
View File
@@ -6,7 +6,7 @@
# |_| |_|\__,_|_|_| |_|\__\___|_| |_|\__,_|_| |_|\___\___| |_.__/ \__, | |_|\_\___|_| |_|_| |_|\__, ||_| \_/ #
# |___/ |___/ #
#######################################################################################################################
# You can report bugs here: https://github.com/KennyTV/Maintenance/issues
# You can report bugs here: https://github.com/kennytv/Maintenance/issues
# If you need any other help/support, you can also join my Discord server: https://discord.gg/vGCUzHq
# Enables maintenance mode.
@@ -17,17 +17,27 @@ proxied-maintenance-servers:
- SpigotServer1
# - AnotherServer
# If maintenance is enabled on a proxied server with players on it,
# they will be sent to the fallback server instead of being kicked off the network.
# If maintenance is enabled on a proxied server with players on it, they will be sent to the fallback server instead of being kicked off the network.
# If the fallback server is not reachable/not set, they will just be kicked off the network.
# This can also be set to an array to set multiple fallback servers, in case one server is not always reachable: 'fallback: [s1, s2, s3, ...]'
fallback: lobby
# If maintenance is enabled globally, you can define a "waiting" lobby for players to be sent to instead of being kicked.
# Leave this empty to disable.
waiting-server: ""
# The message shown in the multiplayer server list motd when maintenance is enabled.
# If you put in multiple entries, one of them will be chosen randomly on every ping.
# If running an endtimer, the time left can be displayed by including '%TIMER%' in a pingmessage (also works in playercount(-hover) message).
pingmessages:
- "&cMaintenance mode!%NEWLINE%&6We will be back soon!"
# - "Other entry"
enable-pingmessages: true
# Any extra commands inside of the arrays will be executed when maintenance is enabled/disabled.
# Example: commands-on-maintenance-enable: ["say hello!", "stop"]
commands-on-maintenance-enable: []
commands-on-maintenance-disable: []
# If set to true and an endtimer is currently running, a pingmessage from this pool will be chosen
# instead of the ones above, so you can have different messages for when an endtimer is running/not running.
@@ -39,7 +49,7 @@ timerspecific-pingmessages:
# 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%").
# 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"
@@ -59,7 +69,8 @@ send-join-notification: false
kick-online-players: true
# Changes the language of command feedback/messages.
# Currently available are: en (English), de (German), fr (French), pt (Portuguese), es (Spanish)
# If you find missing translations or want to contribute a new language file, you are very welcome to message me on Spigot or my Discord server! :)
# Currently available are: en (English), de (German), fr (French), pt (Portuguese), es (Spanish), ru (Russian), zh (Chinese), it (Italian)
language: en
# If you have 2 or more proxy instances, the database connection will make sure all proxies
@@ -77,6 +88,8 @@ mysql:
# Set this to 0 to make a database request on (almost) every single ping.
# (0 is not recommended if having more than a hundred concurrent players, then I'd recommend keeping it from 10-60).
update-interval: 15
# If you for some reason cannot establish SSL connections to your database, you may disable it here (not recommended).
use-ssl: true
# If enabled and the server is restarted while running an endtimer, the timer will be continued after the restart.
# If the timer ends while the server is offline, maintenance will be disabled as soon as the server starts again.
@@ -95,4 +108,4 @@ timer-broadcast-for-seconds: [1200, 900, 600, 300, 120, 60, 30, 20, 10, 5, 4, 3,
update-checks: true
# Used for autoupdating the config, do not change this value.
config-version: 3
config-version: 5
@@ -1,4 +1,4 @@
# Maintenance Plugin by KennyTV
# Maintenance Plugin by kennytv
# Wörter zwischen dem '%'-Zeichen nur entfernen, wenn Du wirklich weißt, warum Du sie entfernen willst
noPermission: "&cDu hast nicht die erforderliche Berechtigung für diesen Befehl."
@@ -11,6 +11,7 @@ endtimerBroadcast: "&8[&eMaintenance&8] &7Der Wartungsmodus wird deaktiviert in:
endtimerStarted: "&8[&eMaintenance&8] &aGestarteter Timer: &7Der Wartungsmodus wird deaktiviert in: &6%TIME%&7."
starttimerBroadcast: "&8[&eMaintenance&8] &7Der Wartungsmodus wird aktiviert in: &6%TIME%&7."
starttimerStarted: "&8[&eMaintenance&8] &aGestarteter Timer: &7Der Wartungsmodus wird aktiviert in: &6%TIME%&7"
scheduletimerBroadcast: "&8[&eMaintenance&8] &7Der Wartungsmodus wird in &6%TIME% &7aktiviert und &6%DURATION% &7dauern."
timerAlreadyRunning: "&8[&eMaintenance&8] &cMomentan läuft bereits ein Timer!"
timerNotRunning: "&8[&eMaintenance&8] &cMomentan läuft kein Timer."
timerCancelled: "&8[&eMaintenance&8] &cDer laufende Timer wurde beendet."
@@ -43,12 +44,16 @@ playerNotOnline: "&8[&eMaintenance&8] &cEs ist momentan kein Spieler mit diesem
invalidUuid: "&8[&eMaintenance&8] &cUngültiges UUID Format!"
# Nachrichten für den Bungee/Velocity Teil des Plugins, einfach ignorieren, falls das Plugin auf Spigot/Sponge verwendet wird
sentToWaitingServer: "&8[&eMaintenance&8] &cDu wurdest auf den Warteserver verbunden!"
forceWaitingServer: "&8[&eMaintenance&8] &cDu kannst den Warteserver nicht verlassen solange der Wartungsmodus aktiviert ist!"
serverNotFound: "&8[&eMaintenance&8] &cEs wurde kein Server mit diesem Namen gefunden!"
singleTimerAlreadyRunning: "&8[&eMaintenance&8] &cMomentan läuft bereits ein Timer auf diesem Server!"
singleTimerNotRunning: "&8[&eMaintenance&8] &cMomentan läuft kein Timer auf diesem Server."
singleTimerCancelled: "&8[&eMaintenance&8] &cDer laufende Timer dieses Servers wurde beendet."
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7Der Wartungsmodus auf Server %SERVER% wird deaktiviert in: &6%TIME%&7."
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7Der Wartungsmodus auf Server %SERVER% wird aktiviert in: &6%TIME%&7."
singleScheduletimerBroadcast: "&8[&eMaintenance&8] &7Der Wartungsmodus auf Server %SERVER% wird aktiviert in &6%TIME% &7und wird &6%DURATION% &7dauern."
singleMaintenanceKick: "&8[&eMaintenance&8] &cDer Server %SERVER% befindet sich momentan im Wartungsmodus! Probier es später nochmal!"
singleMaintenanceKickComplete: "&cDer Server %SERVER% befindet sich in Wartung!%NEWLINE%&cDu kannst versuchen zu rejoinen, um andere Server zu betreten!"
singleMaintenanceActivated: "&8[&eMaintenance&8] &6Der Wartungsmodus wurde auf &e%SERVER% &6aktiviert."
@@ -71,6 +76,7 @@ helpNextPage: "&7Nutze &b/maintenance help %SEITE%&7, um zur nächsten Hilfeseit
helpAbortTimer: "&6/maintenance aborttimer &7(Falls momentan ein Timer läuft, wird dieser abgebrochen)"
helpEndtimer: "&6/maintenance endtimer <Minuten> &7(Sobald der Timer abläuft wird der Wartungsmodus deaktiviert)"
helpStarttimer: "&6/maintenance starttimer <minutes> &7(Sobald der Timer abläuft wird der Wartungsmodus aktiviert)"
helpDebug: "&6/maintenance debug &7(Aktiviert Debug Nachrichten in der Konsole)"
helpDump: "&6/maintenance dump &7(Sammelt wichtige Informationen für Bugreports)"
helpHelp: "&6/maintenance help [Seite] &7(Zeigt diese wunderschöne Hilfe)"
helpMotd: "&6/maintenance motd [timer] &7(Zeigt die momentan gesetzten Maintenance Motds an. Mit dem 'timer' Argument werden die timerspezifischen Motds angezeigt)"
@@ -87,5 +93,6 @@ helpWhitelistRemove: "&6/maintenance remove <Name/UUID> &7(Entfernt einen Spiele
helpAbortSingleTimer: "&6/maintenance aborttimer [Server] &7(Falls momentan ein Timer läuft, wird dieser abgebrochen)"
helpSingleEndtimer: "&6/maintenance endtimer [Server] <Minuten> &7(Sobald der Timer abläuft wird der Wartungsmodus deaktiviert)"
helpSingleStarttimer: "&6/maintenance starttimer [Server] <Minuten> &7(Sobald der Timer abläuft wird der Wartungsmodus aktiviert)"
helpSingleScheduleTimer: "&6/maintenance scheduletimer [Server] <Minuten> <Wartung in Minuten> &7(Sobald der Timer abläuft wird der Wartungsmodus für die gegebene Länge aktiviert)"
helpSingleToggle: "&6/maintenance <on/off> [Server] &7(Aktiviert/deaktiviert den Wartungsmodus)"
helpStatus: "&6/maintenance status &7(Zeigt alle Server an, auf denen momentan der Wartungsmodus aktiviert ist)"
@@ -1,4 +1,4 @@
# Maintenance Plugin by KennyTV
# 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."
@@ -11,6 +11,7 @@ endtimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode will be disabled in &
endtimerStarted: "&8[&eMaintenance&8] &aStarted timer: &7Maintenance mode will be deactivated in &6%TIME%&7."
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."
scheduletimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%TIME% &7and will last for &6%DURATION%&7."
timerAlreadyRunning: "&8[&eMaintenance&8] &cThere is already a timer scheduled!"
timerNotRunning: "&8[&eMaintenance&8] &cThere is currently no running timer."
timerCancelled: "&8[&eMaintenance&8] &cThe current timer has been disabled."
@@ -43,12 +44,16 @@ playerNotOnline: "&8[&eMaintenance&8] &cThere is no player online with that name
invalidUuid: "&8[&eMaintenance&8] &cInvalid uuid format!"
# Messages for the Bungee/Velocity part, just can ignore them if you use the plugin on Spigot/Sponge
sentToWaitingServer: "&8[&eMaintenance&8] &cYou have been sent to a waiting server!"
forceWaitingServer: "&8[&eMaintenance&8] &cYou cannot leave the waiting server while maintenance is enabled!"
serverNotFound: "&8[&eMaintenance&8] &cNo server with this name is registered on the proxy!"
singleTimerAlreadyRunning: "&8[&eMaintenance&8] &cThere is already a timer scheduled for that server!"
singleTimerCancelled: "&8[&eMaintenance&8] &cThe current timer for server &e%SERVER% &chas been disabled."
singleTimerNotRunning: "&8[&eMaintenance&8] &cThere is currently no running timer for that server."
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be disabled in &6%TIME%&7."
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be enabled in &6%TIME%&7."
singleScheduletimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be enabled in &6%TIME% &7and will last for &6%DURATION%&7."
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."
@@ -71,6 +76,8 @@ helpNextPage: "&7Use &b/maintenance help %PAGE% &7to get to the next help window
helpAbortTimer: "&6/maintenance aborttimer &7(If running, the current timer will be aborted)"
helpEndtimer: "&6/maintenance endtimer <minutes> &7(After the given time in minutes, maintenance mode will be disabled)"
helpStarttimer: "&6/maintenance starttimer <minutes> &7(After the given time in minutes, maintenance mode will be enabled)"
helpScheduleTimer: "&6/maintenance scheduletimer <timer minutes> <maintenance duration> &7(After the given time in minutes, maintenance mode will be enabled for the given duration in minutes)"
helpDebug: "&6/maintenance debug &7(Enables some debug logging)"
helpDump: "&6/maintenance dump &7(Dumps some server information, used for bug reports)"
helpHelp: "&6/maintenance help [page] &7(Shows this beautiful help window)"
helpMotd: "&6/maintenance motd [timer] &7(Lists the currently set maintenance motds. If specifying 'timer', the timer motds are shown)"
@@ -87,5 +94,6 @@ helpWhitelistRemove: "&6/maintenance remove <name/uuid> &7(Removes the player fr
helpAbortSingleTimer: "&6/maintenance aborttimer [server] &7(If running, the current timer will be aborted)"
helpSingleEndtimer: "&6/maintenance endtimer [server] <minutes> &7(After the given time in minutes, maintenance mode will be disabled)"
helpSingleStarttimer: "&6/maintenance starttimer [server] <minutes> &7(After the given time in minutes, maintenance mode will be enabled)"
helpSingleScheduleTimer: "&6/maintenance scheduletimer [server] <timer minutes> <maintenance duration> &7(After the given time in minutes, maintenance mode will be enabled for the given duration in minutes)"
helpSingleToggle: "&6/maintenance <on/off> [server] &7(Enables/disables maintenance mode)"
helpStatus: "&6/maintenance status &7(Lists all proxied servers, that are currently under maintenance)"
@@ -1,62 +1,68 @@
# Maintenance Plugin by KennyTV
# Maintenance Plugin by kennytv
# Translators: Vixo_Ulises
# Don't remove words inbetween the '%' if you don't exactly know why you're doing it
noPermission: "&4No tienes Permiso para ejecutar este comando."
kickmessage: "&cEl servidor se encuentra en &6Mantenimiento!%NEWLINE%&cIntentalo de nuevo mas tarde!"
maintenanceActivated: "&8[&eMaintenance&8] &6Mantenimiento &7Activado"
maintenanceDeactivated: "&8[&eMaintenance&8] &7Modo &6Mantenimiento &7Desactivado"
alreadyEnabled: "&8[&eMaintenance&8] &7Modo &6Mantenimiento &7se encuentra Habilitado!"
alreadyDisabled: "&8[&eMaintenance&8] &7Modo &6Mantenimiento &7se encuentra Deshabilitado!"
endtimerBroadcast: "&8[&eMaintenance&8] &7El Modo &6Mantenimiento &7se desactivara en &6%TIME%&7."
endtimerStarted: "&8[&eMaintenance&8] &7Temporizador Iniciado: El Modo &6Mantenimiento &7se desactivará en &6%TIME%&7."
starttimerBroadcast: "&8[&eMaintenance&8] &7El Modo &6Mantenimiento &7se habilitara en &6%TIME%&7."
starttimerStarted: "&8[&eMaintenance&8] &7Temporizador Iniciado: El Modo &6Mantenimiento &7se activará en &6%TIME%&7."
timerAlreadyRunning: "&8[&eMaintenance&8] &7Ya hay un temporizador programado!"
noPermission: "&8[&eMaintenance&8] &4No tienes permiso para ejecutar este comando."
kickmessage: "&cEl servidor se encuentra en mantenimiento!%NEWLINE%&cIntentalo de nuevo mas tarde!"
maintenanceActivated: "&8[&eMaintenance&8] Mantenimiento &7activado"
maintenanceDeactivated: "&8[&eMaintenance&8] &7Modo mantenimiento &7desactivado"
alreadyEnabled: "&8[&eMaintenance&8] &7Modo mantenimiento se encuentra habilitado!"
alreadyDisabled: "&8[&eMaintenance&8] &7Modo mantenimiento se encuentra deshabilitado!"
endtimerBroadcast: "&8[&eMaintenance&8] &7El modo mantenimiento se desactivara en &6%TIME%&7."
endtimerStarted: "&8[&eMaintenance&8] &7Temporizador iniciado: El modo mantenimiento se desactivará en &6%TIME%&7."
starttimerBroadcast: "&8[&eMaintenance&8] &7El modo mantenimiento se habilitara en &6%TIME%&7."
starttimerStarted: "&8[&eMaintenance&8] &7Temporizador iniciado: El modo mantenimiento se activará en &6%TIME%&7."
scheduletimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%TIME% &7and will last for &6%DURATION%&7."
timerAlreadyRunning: "&8[&eMaintenance&8] &cYa hay un temporizador programado!"
timerNotRunning: "&8[&eMaintenance&8] &7Actualmente no hay temporizador."
timerCancelled: "&8[&eMaintenance&8] &cEl Temporizador actual ha sido deshabilitado."
timerTooLong: "&8[&eMaintenance&8] &7El numero debe ser menor a 40320 &6(28 dias)"
timerMotdDisabled: "&8[&eMaintenance&8] &cTienes que configurar 'enable-timerspecific-messages' en la configuración en 'true', si quieres usar / editar motdspecers específicos."
timerTooLong: "&8[&eMaintenance&8] &7El numero debe ser menor a 40320 &8(&628 días&8)"
timerMotdDisabled: "&8[&eMaintenance&8] &cTienes que configurar &a'enable-timerspecific-messages'&c en la configuración en &a'true'&c, si quieres usar / editar motdspecers específicos."
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
motdTimerNotRunning: "-"
joinNotification: "&8[&eMaintenance&8] &c%PLAYER% &7Intenta unirse al servidor."
motdList: "&8[&eMaintenance&8] &7Lista de motds de &6Mantenimiento&7:"
motdListEmpty: "8[&eMaintenance&8] &c¡No tiene ningún juego de mantenimiento establecido!"
reload: "&8[&eMaintenance&8] &aConfiguracion Recargada"
removedMotd: "&8[&eMaintenance&8] &aNumero de Motd eliminado &6%INDEX%."
removeMotdError: "&8[&eMaintenance&8] &Solo tienes un Motd, por lo que no puedes eliminar ninguno!"
setMotd: "&8[&eMaintenance&8] &aEstablecer linea &6%LINE%&a del &6%INDEX%. &6Mantenimiento&a para %MOTD%"
setMotdIndexError: "&8[&eMaintenance&8] &aActualmente tiene &6%MOTDS%&a Motds, por lo que debe elegir un número entre 1 y %NEWAMOUNT%."
setMotdLineError: "&8[&eMaintenance&8] &7El segundo argumento tiene que ser el numero de línea.(1 ó 2)!"
updateDownloading: "&8[&eMaintenance&8] &aDescargando Actualizacion..."
updateFailed: "&8[&eMaintenance&8] &aActualizacion &cFallida!"
updateFinished: "&8[&eMaintenance&8] &aLa actualización fue exitosa!, Debes reiniciar el Servidor!"
motdList: "&8[&eMaintenance&8] &7Lista de motds de mantenimiento&7:"
motdListEmpty: "8[&eMaintenance&8] &c¡No tiene ningún motd(s&8) de mantenimiento establecido!"
reload: "&8[&eMaintenance&8] &aConfiguracion recargada"
removedMotd: "&8[&eMaintenance&8] &aNumero de motd eliminado &6%INDEX%&a."
removeMotdError: "&8[&eMaintenance&8] &Solo tienes un motd, por lo que no puedes eliminar ninguno!"
setMotd: "&8[&eMaintenance&8] &aEstablecer linea &6%LINE%&a sobre &6%INDEX%&a. Para mantenimiento para %MOTD%"
setMotdIndexError: "&8[&eMaintenance&8] &aActualmente tiene &6%MOTDS%&a Motd(s&8), por lo que debe elegir un número entre 1 y %NEWAMOUNT%."
setMotdLineError: "&8[&eMaintenance&8] &7El segundo argumento tiene que ser el numero de línea.(1 ó 2&8)!"
updateDownloading: "&8[&eMaintenance&8] &aDescargando actualización..."
updateFailed: "&8[&eMaintenance&8] &cActualizacion fallida!"
updateFinished: "&8[&eMaintenance&8] &aLa actualización fue exitosa!, debes reiniciar el servidor!"
whitelistedPlayers: "&8[&eMaintenance&8] &6Jugadores en lista blanca:"
whitelistedPlayersFormat: "&7- &a%NAME% &8(&7%UUID%&8)"
whitelistAdded: "&8[&eMaintenance&8] &a%PLAYER% &7Añadido a la lista de &6Mantenimiento!"
whitelistAlreadyAdded: "&8[&eMaintenance&8] &a%PLAYER% &7Se encuentra en la lista de &6Mantenimiento!"
whitelistRemoved: "&8[&eMaintenance&8] &c%PLAYER% &7Eliminado de la lista de &6Mantenimiento!"
whitelistNotFound: "&8[&eMaintenance&8] &7No se encuentra en la lista de &6Mantenimiento!"
whitelistEmpty: "&8[&eMaintenance&8] &7La lista de &6Mantenimiento está vacía! Usa '&6/Maintenance add <Player>' &7para agregar a alguien!"
playerNotFound: "&8[&eMaintenance&8] &7Ningun jugador con este nombre ha jugado en este servidor antes."
whitelistAdded: "&8[&eMaintenance&8] &a%PLAYER% &7Añadido a la lista de mantenimiento!"
whitelistAlreadyAdded: "&8[&eMaintenance&8] &a%PLAYER% &7Se encuentra en la lista de mantenimiento!"
whitelistRemoved: "&8[&eMaintenance&8] &c%PLAYER% &7Eliminado de la lista de mantenimiento!"
whitelistNotFound: "&8[&eMaintenance&8] &7No se encuentra en la lista de mantenimiento!"
whitelistEmpty: "&8[&eMaintenance&8] &7La lista de mantenimiento está vacía! Usa '&6/Maintenance add <Player>' &7para agregar a alguien!"
playerNotFound: "&8[&eMaintenance&8] &7Ningun jugador con este nombre ha jugado en este servidor antes!"
playerNotFoundUuid: "&8[&eMaintenance&8] &cNo se pudo encontrar el jugador con ese UUID."
playerNotOnline: "&8[&eMaintenance&8] &7No hay jugador en línea con ese nombre."
playerNotOnline: "&8[&eMaintenance&8] &7No hay jugador en línea con este nombre."
invalidUuid: "&8[&eMaintenance&8] &cFormato inválido!"
# Messages for the Bungee/Velocity part, just can ignore them if you use the plugin on Spigot/Sponge
sentToWaitingServer: "&8[&eMaintenance&8] &aHas sido enviado a un servidor de espera!"
forceWaitingServer: "&8[&eMaintenance&8] &cNo puedes dejar el servidor de espera mientras el mantenimiento está activado!"
serverNotFound: "&8[&eMaintenance&8] &cNingún servidor con este nombre está registrado en el proxy!"
singleTimerAlreadyRunning: "&8[&eMaintenance&8] &cYa hay un temporizador programado!"
singleTimerNotRunning: "&8[&eMaintenance&8] &cActualmente no hay ningún temporizador en ejecución para ese servidor."
singleTimerCancelled: "&8[&eMaintenance&8] &cEl temporizador actual para el servidor &6%SERVER% &c ha sido desactivado."
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7Modo &6Mantenimiento &7en el Servidor &6%SERVER% &cse desactivará en &6%TIME%"
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7Modo &6Mantenimiento &7en el Servidor &6%SERVER%&7se activará en &6%TIME%"
singleMaintenanceKick: "&8[&eMaintenance&8] &7El servidor &6%SERVER% &7se encuentra en &6Mantenimiento&7! Intentalo mas tarde!"
singleMaintenanceKickComplete: "&7El Servidor &6%SERVER% &7esta en &6Mantenimiento&7!%NEWLINE%&cVuelve Mas Tarde!"
singleMaintenanceActivated: "&8[&eMaintenance&8] &7El Modo&6Mantenimiento &7Esta Activado en el Servidor &6%SERVER%&7."
singleMaintenanceDeactivated: "&8[&eMaintenance&8] &7El Modo &6Mantenimiento &7Ahora esta deshabilitado en &6%SERVER%&7."
singleServerAlreadyEnabled: "&8[&eMaintenance&8] &7El Modo &6Mantenimiento &7se encuentra Habilitado en &6%SERVER%&7!"
singleServerAlreadyDisabled: "&8[&eMaintenance&8] 7El Modo &6Mantenimiento &7se encuentra Deshabilitado en &6%SERVER%&7!"
singleServerMaintenanceList: "&8[&eMaintenance&8] &7Servidores Proxy, que tienen habilitado el &6Mantenimiento:"
singleServerMaintenanceListEmpty: "&8[&eMaintenance&8] &7No hay servidores Proxy que están en &6Mantenimiento&7."
singleTimerCancelled: "&8[&eMaintenance&8] &cEl temporizador actual para el servidor &6%SERVER% &cha sido desactivado."
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7El modo mantenimiento en el Servidor &6%SERVER% &7se desactivará en &a%TIME%&7."
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7El modo mantenimiento en el servidor &6%SERVER%&7 se activará en &a%TIME%&7"
singleScheduletimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be enabled in &6%TIME% &7and will last for &6%DURATION%&7."
singleMaintenanceKick: "&8[&eMaintenance&8] &7El servidor &6%SERVER% &7se encuentra en mantenimiento&7! Intentalo mas tarde!"
singleMaintenanceKickComplete: "&7El Servidor &6%SERVER% &7esta en mantenimiento&7!%NEWLINE%&cVuelve Mas Tarde!"
singleMaintenanceActivated: "&8[&eMaintenance&8] &7El modo mantenimiento esta activado en el servidor &6%SERVER%&7."
singleMaintenanceDeactivated: "&8[&eMaintenance&8] &7El modo mantenimiento ahora esta deshabilitado en &6%SERVER%&7."
singleServerAlreadyEnabled: "&8[&eMaintenance&8] &7El modo mantenimiento se encuentra habilitado en &6%SERVER%&7!"
singleServerAlreadyDisabled: "&8[&eMaintenance&8] &7El modo mantenimiento se encuentra deshabilitado en &6%SERVER%&7!"
singleServerMaintenanceList: "&8[&eMaintenance&8] &7Servidores proxy, que tienen habilitado el mantenimiento:"
singleServerMaintenanceListEmpty: "&8[&eMaintenance&8] &7No hay servidores proxy que están en mantenimiento&7."
second: "Segundo"
seconds: "Segundos"
@@ -66,26 +72,28 @@ hour: "Hora"
hours: "Horas"
helpHeader: "&8========[ &e%NAME% &8| &e%PAGE%/%MAX% &8]========"
helpPageNotFound: "&8[&eMaintenance&8] &7No hay pagina con ese número!"
helpNextPage: "&7Utilice &b/maintenance help %PAGE% &7para pasar a la siguiente ventana de ayuda."
helpAbortTimer: "&6/maintenance aborttimer &7(Si se ejecuta, se abortará el temporizador actual)"
helpEndtimer: "&6/maintenance endtimer <minutes> &7(Después del tiempo en minutos, se desactivará el modo de mantenimiento)"
helpStarttimer: "&6/maintenance starttimer <minutes> &7(Después del tiempo en minutos, se habilitará el modo de mantenimiento)"
helpDump: "&6/maintenance dump &7(Vuelca información del servidor, usada para informes de errores)"
helpHelp: "&6/maintenance help [page] &7(Muestra esta hermosa ventana de ayuda)"
helpMotd: "&6/maintenance motd [timer] &7(Enumera los motivos de mantenimiento establecidos actualmente. Si se especifica el 'temporizador', se muestran los motivos del temporizador)"
helpRemoveMotd: "&6/maintenance removemotd [timer] <index> &7(Elimina un mantenimiento motd. Si se usa 'timer' como argumento, se eliminará un pingmessage de temporizador específico)"
helpSetMotd: "&6/maintenance setmotd [timer] <index> <1/2> <message> &7(Establece un motd para el modo de mantenimiento. Si usa 'timer' como argumento, se establecerá un mensaje de ping específico para el tiempo)"
helpReload: "&6/maintenance reload &7(Vuelve a cargar el archivo de configuración, el archivo de la lista blanca y el ícono del servidor)"
helpToggle: "&6/maintenance <on/off> &7(Habilita / deshabilita el modo de mantenimiento)"
helpUpdate: "&6/maintenance update &7(Descarga de forma remota la versión más reciente del complemento en su servidor)"
helpWhitelist: "&6/maintenance whitelist &7(Muestra todos los reproductores en lista blanca para el modo de mantenimiento)"
helpWhitelistAdd: "&6/maintenance add <name/uuid> &7(Agrega el reproductor a la lista blanca de mantenimiento, para que puedan unirse al servidor aunque el mantenimiento esté habilitado)"
helpWhitelistRemove: "&6/maintenance remove <name/uuid> &7(Quita el reproductor de la lista blanca de mantenimiento)"
helpPageNotFound: "&8[&eMaintenance&8] &7No hay pagina con ese número."
helpNextPage: "&7Utilice &b/maintenance help %PAGE% &7Para pasar a la siguiente ventana de ayuda."
helpAbortTimer: "&6/maintenance aborttimer &8(&7Si se ejecuta, se abortará el temporizador actual&8)"
helpEndtimer: "&6/maintenance endtimer <minutes> &8(&7Después del tiempo en minutos, se desactivará el modo de mantenimiento&8)"
helpStarttimer: "&6/maintenance starttimer <minutes> &8(&7Después del tiempo en minutos, se habilitará el modo de mantenimiento&8)"
helpDebug: "&6/maintenance debug &7(Enables some debug logging)"
helpDump: "&6/maintenance dump &8(&7Descarga información del servidor, usada para informes de errores&8)"
helpHelp: "&6/maintenance help [page] &8(&7Muestra la pagina de ayuda&8)"
helpMotd: "&6/maintenance motd [timer] &8(&7Enumera los motivos de mantenimiento establecidos actualmente. Si se especifica el 'temporizador', se muestran los motivos del temporizador&8)"
helpRemoveMotd: "&6/maintenance removemotd [timer] <index> &8(&7Elimina un mantenimiento motd. Si se usa 'timer' como argumento, se eliminará un pingmessage de temporizador específico&8)"
helpSetMotd: "&6/maintenance setmotd [timer] <index> <1/2> <message> &8(&7Establece un motd para el modo de mantenimiento. Si usa 'timer' como argumento, se establecerá un mensaje de ping específico para el tiempo&8)"
helpReload: "&6/maintenance reload &8(&7Vuelve a cargar el archivo de configuración, el archivo de la lista blanca y el ícono del servidor&8)"
helpToggle: "&6/maintenance <on/off> &8(&7Habilita / deshabilita el modo de mantenimiento&8)"
helpUpdate: "&6/maintenance update &8(&7Descarga de forma remota la versión más reciente del complemento en su servidor&8)"
helpWhitelist: "&6/maintenance whitelist &8(&7Muestra todos los jugadores en lista blanca para el modo de mantenimiento&8)"
helpWhitelistAdd: "&6/maintenance add <name/uuid> &8(&7Agrega al jugador a la lista blanca de mantenimiento, para que puedan unirse al servidor aunque el mantenimiento esté habilitado&8)"
helpWhitelistRemove: "&6/maintenance remove <name/uuid> &8(&7Quita al jugador de la lista blanca de mantenimiento&8)"
# Messages for the Bungee/Velocity part, just can ignore them if you use the plugin on Spigot/Sponge
helpAbortSingleTimer: "&6/maintenance aborttimer [servidor] &7(Si está funcionando, se abortará el temporizador actual)"
helpSingleEndtimer: "&6/maintenance endtimer [server] <minutes> &7(Después del tiempo en minutos, se desactivará el modo de mantenimiento)"
helpSingleStarttimer: "&6/maintenance starttimer [server] <minutes> &7(Después del tiempo en minutos, el modo de mantenimiento habilitado)"
helpSingleToggle: "&6/maintenance <on/off> [server] &7(Habilita / deshabilita el modo de mantenimiento)"
helpStatus: "&6/maintenance status &7(Enumera todos los servidores proxy, que están actualmente en mantenimiento)"
helpAbortSingleTimer: "&6/maintenance aborttimer [servidor] &8(&7Si está funcionando, se abortará el temporizador actual&8)"
helpSingleEndtimer: "&6/maintenance endtimer [server] <minutes> &8(&7Después del tiempo en minutos, se desactivará el modo de mantenimiento&8)"
helpSingleStarttimer: "&6/maintenance starttimer [server] <minutes> &8(&7Después del tiempo en minutos, se activara el modo de mantenimiento&8)"
helpSingleScheduleTimer: "&6/maintenance scheduletimer [server] <timer minutes> <maintenance duration> &7(After the given time in minutes, maintenance mode will be enabled for the given duration in minutes)"
helpSingleToggle: "&6/maintenance <on/off> [server] &8(&7Habilita / deshabilita el modo de mantenimiento&8)"
helpStatus: "&6/maintenance status &8(&7Enumera todos los servidores proxy, que están actualmente en mantenimiento&8)"
@@ -1,91 +1,98 @@
# Maintenance Plugin par KennyTV
# Ne supprime pas des mots entre les '%' si tu ne sait pas pourqoi exactement
# Plugin Maintenance par kennytv, traduit en Français par Zendrique & Aurelien30000.
# Ne supprimez pas de mots entre les '%' si vous ne savez pas exactement pourquoi, ils correspondent à des référencements de valeurs changeantes.
noPermission: "&cVous n'avez pas la permission d'exécuter cette commande."
kickmessage: "&cLe serveur est actuellement en maintenance!%NEWLINE%&cRéessayez plus tard!"
kickmessage: "&cLe serveur est actuellement en maintenance !%NEWLINE%&cRéessayez plus tard !"
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!"
alreadyEnabled: "&8[&eMaintenance&8] &cLa maintenance est déjà activée !"
alreadyDisabled: "&8[&eMaintenance&8] &cLa maintenance est déjà désactivée !"
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."
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."
timerAlreadyRunning: "&8[&eMaintenance&8] &cIl y a déjà un horaire prévu!"
endtimerStarted: "&8[&eMaintenance&8] &aMinuterie : &7Le mode maintenance sera désactivé dans &6%TIME%&7."
starttimerBroadcast: "&8[&eMaintenance&8] &7Le mode de maintenance sera activé dans &6%TIME%&7."
starttimerStarted: "&8[&eMaintenance&8] &aMinuterie : &7Le mode maintenance sera activé dans &6%TIME%&7."
scheduletimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%TIME% &7and will last for &6%DURATION%&7."
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)!"
timerMotdDisabled: "&8[&eMaintenance&8] &cVous devez définir 'enable-timerspecific-messages' dans la configuration sur 'true', si vous voulez utiliser / éditer des timerspecific motd."
timerTooLong: "&8[&eMaintenance&8] &cLe nombre doit être inférieur à 40320 (28 jours) !"
timerMotdDisabled: "&8[&eMaintenance&8] &cVous devez définir 'enable-timerspecific-messages' sur 'true' au sein de la configuration si vous souhaitez utiliser / éditer des motds spécifiques au timer."
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
motdTimerNotRunning: "-"
joinNotification: "&8[&eMaintenance&8] &e%PLAYER% &ca essayé de rejoindre le serveur."
motdList: "&8[&eMaintenance&8] &7Liste de vos motd pour la maintenance:"
motdListEmpty: "8[&eMaintenance&8] &cVous n'avez pas de motds d'entretien fixés!"
reload: "&8[&eMaintenance&8] &afichier config, liste blanche (whitelist) joueurs, fichier de langue et l'icône de maintenance, recharger."
joinNotification: "&8[&eMaintenance&8] &e%PLAYER% &ca essayé de rejoindre le serveur !"
motdList: "&8[&eMaintenance&8] &7Liste de vos motds pour la maintenance :"
motdListEmpty: "8[&eMaintenance&8] &cVous n'avez pas de motds d'entretien fixés !"
reload: "&8[&eMaintenance&8] &aFichier de configuration, liste blanche (whitelist) des joueurs autorisés, fichier de langue et icône de maintenance rechargés avec succès."
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!"
setMotd: "&8[&eMaintenance&8] &aLigne fixe %LINE% du %INDEX%. maintenance motd à %MOTD%"
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)!"
removeMotdError: "&8[&eMaintenance&8] &cVous n’avez qu’un motd, vous ne pouvez donc pas en supprimer !"
setMotd: "&8[&eMaintenance&8] &aLigne %LINE% du motd %INDEX%. fixée à %MOTD%"
setMotdIndexError: "&8[&eMaintenance&8] &cVous avez actuellement %MOTDS% motd(s), 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:"
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!"
whitelistEmpty: "&8[&eMaintenance&8] &cLa liste blanche de maintenance est vide! Utilisation &e/maintenance add <joueur/uuid> &cajouter quelqu'un!"
playerNotFound: "&8[&eMaintenance&8] &cAucun joueur avec ce nom n'a joué sur ce serveur auparavant."
playerNotFoundUuid: "&8[&eMaintenance&8] &cAucun joueur avec cet uuid n'a pu être trouvé."
whitelistAdded: "&8[&eMaintenance&8] &b%PLAYER% &aa été ajouté la liste blanche de maintenance !"
whitelistAlreadyAdded: "&8[&eMaintenance&8] &b%PLAYER% &cest déjà dans la liste blanche de maintenance !"
whitelistRemoved: "&8[&eMaintenance&8] &b%PLAYER% &aa été retiré de la liste blanche de maintenance !"
whitelistNotFound: "&8[&eMaintenance&8] &cCe joueur n'est pas dans la liste blanche de maintenance !"
whitelistEmpty: "&8[&eMaintenance&8] &cLa liste blanche de maintenance est vide : Utilisation &e/maintenance add <joueur/uuid> &c afin d'ajouter quelqu'un !"
playerNotFound: "&8[&eMaintenance&8] &cAucun joueur avec ce nom n'a auparavant joué sur ce serveur."
playerNotFoundUuid: "&8[&eMaintenance&8] &cAucun joueur avec cet UUID n'a pu être trouvé."
playerNotOnline: "&8[&eMaintenance&8] &cIl n'y a pas de joueur en ligne avec ce nom."
invalidUuid: "&8[&eMaintenance&8] &cLe format de l'uuid est invalide!"
invalidUuid: "&8[&eMaintenance&8] &cLe format de l'UUID est invalide !"
# Quelques messages pour la partie Bungee/Velocity, ignorez-les si vous utilisez le plugin sur Spigot/Sponge
serverNotFound: "&8[&eMaintenance&8] &cAucun serveur avec ce nom n'est enregistré sur le proxy!"
singleTimerAlreadyRunning: "&8[&eMaintenance&8] &cIl y a déjà un horaire prévu sur ce server!"
singleTimerNotRunning: "&8[&eMaintenance&8] &cIl n'y a actuellement aucune maintenance prévue sur ce server."
singleTimerCancelled: "&8[&eMaintenance&8] &cLa minuterie actuelle a été désactivée sur ce server."
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7maintenance sur serveur %SERVER% sera désactivé dans &6%TIME%&7."
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7Maintenance sur le serveur %SERVER% sera activé dans &6%TIME%&7."
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:"
sentToWaitingServer: "&8[&eMaintenance&8] &cVous avez été redirigé(e) vers un serveur d'attente !"
forceWaitingServer: "&8[&eMaintenance&8] &cVous ne pouvez pas quitter le serveur d'attente tant que la maintenance est activée !"
serverNotFound: "&8[&eMaintenance&8] &cAucun serveur avec ce nom n'est enregistré sur le proxy !"
singleTimerAlreadyRunning: "&8[&eMaintenance&8] &cIl y a déjà un horaire prévu sur ce serveur !"
singleTimerNotRunning: "&8[&eMaintenance&8] &cIl n'y a actuellement aucune maintenance prévue sur ce serveur."
singleTimerCancelled: "&8[&eMaintenance&8] &cLa minuterie actuelle a été désactivée sur ce serveur."
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7La maintenance sur le serveur %SERVER% sera désactivée dans &6%TIME%&7."
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7La maintenance sur le serveur %SERVER% sera activée dans &6%TIME%&7."
singleScheduletimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be enabled in &6%TIME% &7and will last for &6%DURATION%&7."
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ée sur le serveur &e%SERVER%&6."
singleMaintenanceDeactivated: "&8[&eMaintenance&8] &6La maintenance est maintenant désactivée 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 ayant la maintenance activée :"
singleServerMaintenanceListEmpty: "&8[&eMaintenance&8] &7Il n'y a pas de serveurs proxy en maintenance."
second: "second"
seconds: "seconds"
second: "seconde"
seconds: "secondes"
minute: "minute"
minutes: "minutes"
hour: "heur"
hours: "heurs"
hour: "heure"
hours: "heures"
helpHeader: "&8========[ &e%NAME% &8| &e%PAGE%/%MAX% &8]========"
helpPageNotFound: "&8[&eMaintenance&8] &cIl n'y a pas cette page!"
helpPageNotFound: "&8[&eMaintenance&8] &cIl n'y a pas cette page !"
helpNextPage: "&7Utilisez &b/maintenance help %PAGE% &7pour accéder à la fenêtre d’aide suivante."
helpAbortTimer: "&6/maintenance aborttimer &7(Si en cours d'exécution, le minuteur actuel sera abandonné)"
helpEndtimer: "&6/maintenance endtimer <minutes> &7(Après le temps imparti en minutes, le mode maintenance sera désactivé)"
helpStarttimer: "&6/maintenance starttimer <minutes> &7(Après le temps imparti en minutes, le mode maintenance sera activé)"
helpDump: "&6/maintenance dump &7(Dépose certaines informations sur le serveur, utilisées pour les rapports de bug)"
helpDebug: "&6/maintenance debug &7(Enables some debug logging)"
helpDump: "&6/maintenance dump &7(Enregistre certaines informations sur le serveur, utilisées pour les rapports de bug)"
helpHelp: "&6/maintenance help [page] &7(Montre cette belle fenêtre d'aide)"
helpMotd: "&6/maintenance motd [timer] &7(Répertorie les paramètres de maintenance actuellement définis. Si vous spécifiez 'timer', les mots de la minuterie sont affichés)"
helpMotd: "&6/maintenance motd [timer] &7(Répertorie les paramètres de maintenance actuellement définis. Si vous spécifiez 'timer', les mots de la minuterie seront affichés)"
helpRemoveMotd: "&6/maintenance removemotd [timer] <index> &7(Supprime un motd de maintenance. Si vous utilisez 'timer' comme argument, un message ping spécifique au temporisateur sera supprimé)"
helpSetMotd: "&6/maintenance setmotd [timer] <index> <1/2> <message> &7(Définit un motd pour le mode maintenance. Si vous utilisez 'timer' comme argument, un message ping spécifique à un temporisateur sera défini)"
helpReload: "&6/maintenance reload &7(Recharge le fichier de configuration, le fichier de liste blanche et l'icône du serveur)"
helpReload: "&6/maintenance reload &7(Recharge le fichier de configuration, la liste blanche, le fichier de langue et l'icône du serveur)"
helpToggle: "&6/maintenance <on/off> &7(Active/désactive le mode maintenance)"
helpUpdate: "&6/maintenance update &7(Télécharger la dernière version du plugin sur votre serveur)"
helpUpdate: "&6/maintenance update &7(Télécharge la dernière version du plugin sur votre serveur)"
helpWhitelist: "&6/maintenance whitelist &7(Affiche les joueurs de la liste blanche pour le mode maintenance)"
helpWhitelistAdd: "&6/maintenance add <name/uuid> &7(Ajoute un joueur à la liste blanche de la maintenance afin qu'il puisse rejoindre le serveur même si la maintenance est activée)"
helpWhitelistRemove: "&6/maintenance remove <name/uuid> &7(Supprime un joueur de la liste blanche de la maintenance)"
helpWhitelistAdd: "&6/maintenance add <name/uuid> &7(Ajoute un joueur à la liste blanche de maintenance afin qu'il puisse rejoindre le serveur même si la maintenance est activée)"
helpWhitelistRemove: "&6/maintenance remove <name/uuid> &7(Supprime un joueur de la liste blanche de maintenance)"
# Quelques messages pour la partie Bungee/Velocity, ignorez-les si vous utilisez le plugin sur Spigot/Sponge
helpAbortSingleTimer: "&6/maintenance aborttimer [server] &7(Si en cours d'exécution, le minuteur actuel sera abandonné)"
helpSingleEndtimer: "&6/maintenance endtimer [server] <minutes> &7(Après le temps imparti en minutes, le mode maintenance sera désactivé)"
helpSingleStarttimer: "&6/maintenance starttimer [server] <minutes> &7(Après le temps imparti en minutes, le mode maintenance sera activé)"
helpSingleScheduleTimer: "&6/maintenance scheduletimer [server] <timer minutes> <maintenance duration> &7(Après le temps imparti en minutes, le mode maintenance sera activé pour la durée spécifiée en minutes)"
helpSingleToggle: "&6/maintenance <on/off> [server] &7(Active/désactive le mode maintenance)"
helpStatus: "&6/maintenance status &7(Répertorie tout les serveurs mandatés, actuellement en maintenance)"
helpStatus: "&6/maintenance status &7(Répertorie tous les serveurs mandatés actuellement en maintenance)"
@@ -0,0 +1,99 @@
# Maintenance Plugin by kennytv
# Translators: TheViperShow
# Don't remove words inbetween the '%' if you don't exactly know why you're doing it
noPermission: "&cNon hai i permessi necessari per eseguire quel comando."
kickmessage: "&cIl server è momentaneamente in manutenzione!%NEWLINE%&cRiprova più tardi!"
maintenanceActivated: "&8[&eMaintenance&8] &6Modalità manutenzione ora attivata."
maintenanceDeactivated: "&8[&eMaintenance&8] &6Modalità manutenzione ora disattivata."
alreadyEnabled: "&8[&eMaintenance&8] &cLa modalità manutenzione è già attiva!"
alreadyDisabled: "&8[&eMaintenance&8] &cLa modalità mantenzione è già disattivata!"
endtimerBroadcast: "&8[&eMaintenance&8] &7La modalità manutenzione verrà disattivata tra &6%TIME%&7."
endtimerStarted: "&8[&eMaintenance&8] &aTimer avviato: &7La modalità manutenzione verrà disattivata tra &6%TIME%&7."
starttimerBroadcast: "&8[&eMaintenance&8] &7La modalità manutenzione verrà attivata tra &6%TIME%&7."
starttimerStarted: "&8[&eMaintenance&8] &aTimer avviato: &7La modalità manutenzione verrà attivata tra &6%TIME%&7."
scheduletimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%TIME% &7and will last for &6%DURATION%&7."
timerAlreadyRunning: "&8[&eMaintenance&8] &cC'è già un timer programmato!"
timerNotRunning: "&8[&eMaintenance&8] &cNon c'è nessun timer attivo al momento."
timerCancelled: "&8[&eMaintenance&8] &cIl timer attuale è stato disattivato."
timerTooLong: "&8[&eMaintenance&8] &cIl numero deve essere inferiore a 40320 (28 giorni)!"
timerMotdDisabled: "&8[&eMaintenance&8] &cDevi impostare 'enable-timerspecific-messages' nella config su 'true', se desideri usare/modificare motds specifiche di un timer."
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
motdTimerNotRunning: "-"
joinNotification: "&8[&eMaintenance&8] &e%PLAYER% &cha tentato di accedere al server."
motdList: "&8[&eMaintenance&8] &7Lista delle tue motds di manutenzione:"
motdListEmpty: "8[&eMaintenance&8] &cNon hai ancora nessuna motds di manutenzione!"
reload: "&8[&eMaintenance&8] &aRicaricata config, whitelistedplayers, file dei linguaggi e la icona di manutenzione."
removedMotd: "&8[&eMaintenance&8] &aRimossa motd numero %INDEX%."
removeMotdError: "&8[&eMaintenance&8] &cHai soltanto una motd, quindi non puoi rimuoverla!"
setMotd: "&8[&eMaintenance&8] &aImpostata linea %LINE% in %INDEX%. motd manutenzione a %MOTD%"
setMotdIndexError: "&8[&eMaintenance&8] &cHai attualmente %MOTDS% motds, quindi devi scegliere un numero fra 1 e %NEWAMOUNT%."
setMotdLineError: "&8[&eMaintenance&8] &cIl secondo argomento deve corrispondere alla linea (1 o 2)!"
updateDownloading: "&8[&eMaintenance&8] &c&lScaricando aggiornamento..."
updateFailed: "&8[&eMaintenance&8] &4&lAggiornamento non riuscito!"
updateFinished: "&8[&eMaintenance&8] &a&lL'aggiornamento è completato! Per prevenire problemi e completare l'aggiornamento dovresti riavviare il server!"
whitelistedPlayers: "&8[&eMaintenance&8] &6Player in whitelist per la manutenzione:"
whitelistedPlayersFormat: "&8- &e%NAME% &8(&7%UUID%&8)"
whitelistAdded: "&8[&eMaintenance&8] &aAggiunto &b%PLAYER% &aalla whitelist della manutenzione!"
whitelistAlreadyAdded: "&8[&eMaintenance&8] &b%PLAYER% &cè già nella whitelist della manutenzione!"
whitelistRemoved: "&8[&eMaintenance&8] &aRimosso &b%PLAYER% &adalla lista della manutenzione!"
whitelistNotFound: "&8[&eMaintenance&8] &cQuesto giocatore non fa parte della whitelist della manutenzione!"
whitelistEmpty: "&8[&eMaintenance&8] &cLa whitelist di manutenzione è vuota! Usa &e/maintenance add <player/uuid> &cper aggiungere qualcuno!"
playerNotFound: "&8[&eMaintenance&8] &cNessun giocatore con questo username è mai entrato nel server."
playerNotFoundUuid: "&8[&eMaintenance&8] &cNessun player con quell'uuid è stato trovato."
playerNotOnline: "&8[&eMaintenance&8] &cNon c'è nessun giocatore online con quell'username."
invalidUuid: "&8[&eMaintenance&8] &cL'uuid presenta un formato invalido!"
# Messages for the Bungee/Velocity part, just can ignore them if you use the plugin on Spigot/Sponge
sentToWaitingServer: "&8[&eMaintenance&8] &cSei stato inviato su un server d'attesa!"
forceWaitingServer: "&8[&eMaintenance&8] &cNon puoi abbandonare il server d'attesa durante una manutenzione!"
serverNotFound: "&8[&eMaintenance&8] &cNessun server con questo nome è registrato sulla proxy!"
singleTimerAlreadyRunning: "&8[&eMaintenance&8] &cÈ già presente un timer pianificato per quel server!"
singleTimerCancelled: "&8[&eMaintenance&8] &cIl timer attuale per il server &e%SERVER% &cè stato rimosso."
singleTimerNotRunning: "&8[&eMaintenance&8] &cNon c'è nessun timer correntemente attivo per quel server."
singleEndtimerBroadcast: "&8[&eMaintenance&8] &7La modalità manutenzione per il server %SERVER% verrà disabilitata tra &6%TIME%&7."
singleStarttimerBroadcast: "&8[&eMaintenance&8] &7La modalità manutenzione per il server %SERVER% verrà disabilitata tra &6%TIME%&7."
singleScheduletimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be enabled in &6%TIME% &7and will last for &6%DURATION%&7."
singleMaintenanceKick: "&8[&eMaintenance&8] &cIl server %SERVER% è in manutenzione al momento! Ritenta più tardi!"
singleMaintenanceKickComplete: "&cIl server %SERVER% è in manutenzione!%NEWLINE%&cProva a rientrare per accedere ad un'altro server!"
singleMaintenanceActivated: "&8[&eMaintenance&8] &6La modalità manutenzione è ora attiva sul server &e%SERVER%&6."
singleMaintenanceDeactivated: "&8[&eMaintenance&8] &6La modalità manutenzione è ora disattivata sul server &e%SERVER%&6."
singleServerAlreadyEnabled: "&8[&eMaintenance&8] &cLa modalità manutenzione è già attiva sul server &e%SERVER%&c!"
singleServerAlreadyDisabled: "&8[&eMaintenance&8] &cLa modalità manutenzione è già disattivata sul server &e%SERVER%&c!"
singleServerMaintenanceList: "&8[&eMaintenance&8] &7Servers sotto proxy che hanno la modalità manutenzione attiva:"
singleServerMaintenanceListEmpty: "&8[&eMaintenance&8] &7Nessun server sotto proxy ha la modalità manutenzione attiva."
second: "secondo"
seconds: "secondi"
minute: "minuto"
minutes: "minuti"
hour: "ora"
hours: "ore"
helpHeader: "&8========[ &e%NAME% &8| &e%PAGE%/%MAX% &8]========"
helpPageNotFound: "&8[&eMaintenance&8] &cNon c'è alcuna pagina con quel numero!"
helpNextPage: "&7Usa &b/maintenance help %PAGE% &7per andare alla prossima pagina d'aiuto."
helpAbortTimer: "&6/maintenance aborttimer &7(Se attivo, l'attuale timer verrà fermato)"
helpEndtimer: "&6/maintenance endtimer <minutes> &7(Dopo il tempo fornito in minuti, la modalità manutenzione sarà rimossa)"
helpStarttimer: "&6/maintenance starttimer <minutes> &7(Dopo il tempo fornito in minuti, la modalità manutenzione sarà attivata)"
helpDebug: "&6/maintenance debug &7(Enables some debug logging)"
helpDump: "&6/maintenance dump &7(Copia alcune informazioni dal server, usato per segnalare problemi)"
helpHelp: "&6/maintenance help [page] &7(Mostra questa fantastica pagina d'aiuto)"
helpMotd: "&6/maintenance motd [timer] &7(Elenca le attuali motds di manutenzione impostate. Se specifichi 'timer', verranno mostrati i motds dei timer)"
helpRemoveMotd: "&6/maintenance removemotd [timer] <index> &7(Rimuove una motd di manutenzione. Se specifichi 'timer' come argomento, un messaggio specifico al timer verrà rimosso)"
helpSetMotd: "&6/maintenance setmotd [timer] <index> <1/2> <message> &7(Imposta il motd per la manutenzione. Se specifichi 'timer' come argomento, un messaggio specifico al timer verrà impostato)"
helpReload: "&6/maintenance reload &7(Ricarica il file di configurazione, whitelist server e icona)"
helpToggle: "&6/maintenance <on/off> &7(Abilita/Disabilita modalità manutenzione)"
helpUpdate: "&6/maintenance update &7(Scarica dall'esterno l'ultima versione del plugin nel server)"
helpWhitelist: "&6/maintenance whitelist &7(Elenca tutti i giocatori nella whitelist per la manutenzione)"
helpWhitelistAdd: "&6/maintenance add <name/uuid> &7(Aggiunge il giocatore alla whitelist di manutenzione, così possono entrare in un server durante la manutenzione)"
helpWhitelistRemove: "&6/maintenance remove <name/uuid> &7(Rimuovi il player dalla whitelist della manutenzione)"
# Messages for the Bungee/Velocity part, just can ignore them if you use the plugin on Spigot/Sponge
helpAbortSingleTimer: "&6/maintenance aborttimer [server] &7(Se attivo, il timer attuale verrà fermato)"
helpSingleEndtimer: "&6/maintenance endtimer [server] <minutes> &7(Dopo il tempo fornito in minuti, la modalità manutenzione sarà rimossa)"
helpSingleStarttimer: "&6/maintenance starttimer [server] <minutes> &7(Dopo il tempo fornito in minuti, la modalità manutenzione sarà attivata)"
helpSingleScheduleTimer: "&6/maintenance scheduletimer [server] <timer minutes> <maintenance duration> &7(After the given time in minutes, maintenance mode will be enabled for the given duration in minutes)"
helpSingleToggle: "&6/maintenance <on/off> [server] &7(Abilita/Disabilita la modalità manutenzione)"
helpStatus: "&6/maintenance status &7(Elenca tutti i server sotto proxy che hanno la modalità manutenzione attiva)"
@@ -1,4 +1,5 @@
# Maintenance Plugin by KennyTV
# Maintenance Plugin by kennytv
# Translators: JoaoPinto
# Nao removas o '%' se nao souberes exatamente o que estas a fazer
noPermission: "&cNao tens permissao para executar este comando."
@@ -11,23 +12,24 @@ endtimerBroadcast: "&8[&cManutencao&8] &7Manutencao vai ser desativada em &6%TIM
endtimerStarted: "&8[&cManutencao&8] &aTemporizador: &7Manutencao vai ser desativada em &6%TIME%&7"
starttimerBroadcast: "&8[&cManutencao&8] &7Manutencao vai ser ativada em &6%TIME%&7"
starttimerStarted: "&8[&cManutencao&8] &7Manutencao vai ser ativada em &6%TIME%&7"
scheduletimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode will be enabled in &6%TIME% &7and will last for &6%DURATION%&7."
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)!"
timerMotdDisabled: "&8[&eMaintenance&8] &cYou have to set 'enable-timerspecific-messages' in the config to 'true', if you want to use/edit timerspecific motds."
timerMotdDisabled: "&8[&eMaintenance&8] &cDefine 'enable-timerspecific-messages' no config a 'true', se queres definir/editar motds de manutenção."
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
motdTimerNotRunning: "-"
joinNotification: "&8[&cManutencao&8] &e%PLAYER% &ctentou entrar no servidor."
motdList: "&8[&cManutencao&8] &7Lista de motds de manutencao:"
motdListEmpty: "8[&eMaintenance&8] &cYou don't have any maintenance motds set!"
motdListEmpty: "8[&eMaintenance&8] &cNão tens motds de manutenção!"
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!"
setMotd: "&8[&eManutencao&8] &aLinha %LINE% do %INDEX%. Motd de manutencao %MOTD%"
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..."
updateDownloading: "&8[&cManutencao&8] &c&lA dar download do 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:"
@@ -43,12 +45,16 @@ playerNotOnline: "&8[&cManutencao&8] &cNao esta ninguem online com esse nome"
invalidUuid: "&8[&eMaintenance&8] &cFormato de uuid invalido!"
# Algumas mensagens para o Bungee/Velocity, ignora-as se estas a usar Spigot/Sponge
sentToWaitingServer: "&8[&eMaintenance&8] &cYou have been sent to a waiting server!"
forceWaitingServer: "&8[&eMaintenance&8] &cYou cannot leave the waiting server while maintenance is enabled!"
serverNotFound: "&8[&cManutencao&8] &cServidor nao encontrado!"
singleTimerAlreadyRunning: "&8[&cManutencao&8] &cO Timer ja esta a decorrer!"
singleTimerNotRunning: "&8[&cManutencao&8] &cO Timer nao esta a decorrer!"
singleTimerCancelled: "&8[&cManutencao&8] &cO Timer foi cancelado no!"
singleEndtimerBroadcast: "&8[&cManutencao&8] &7Manutencao no %SERVER% vai ser desativada em &6%TIME%&7."
singleStarttimerBroadcast: "&8[&cManutencao&8] &7Manutencao no %SERVER% vai ser ativada em &6%TIME%&7."
singleScheduletimerBroadcast: "&8[&eMaintenance&8] &7Maintenance mode on server %SERVER% will be enabled in &6%TIME% &7and will last for &6%DURATION%&7."
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."
@@ -67,25 +73,27 @@ hours: "horas"
helpHeader: "&8========[ &e%NAME% &8| &e%PAGE%/%MAX% &8]========"
helpPageNotFound: "&8[&eManutencao&8] &cNao existe nenhuma pagina com esse numero!"
helpNextPage: "&7Use &b/maintenance help %PAGE% &7to get to the next help window."
helpAbortTimer: "&6/maintenance aborttimer &7(If running, the current timer will be aborted)"
helpEndtimer: "&6/maintenance endtimer <minutes> &7(After the given time in minutes, maintenance mode will be disabled)"
helpStarttimer: "&6/maintenance starttimer <minutes> &7(After the given time in minutes, maintenance mode will be enabled)"
helpDump: "&6/maintenance dump &7(Dumps some server information, used for bug reports)"
helpHelp: "&6/maintenance help [page] &7(Shows this beautiful help window)"
helpMotd: "&6/maintenance motd [timer] &7(Lists the currently set maintenance motds. If specifying 'timer', the timer motds are shown)"
helpRemoveMotd: "&6/maintenance removemotd [timer] <index> &7(Removes a maintenance motd. If using \"timer\" as an argument, a timerspecific pingmessage will be removed)"
helpSetMotd: "&6/maintenance setmotd [timer] <index> <1/2> <message> &7(Sets a motd for maintenance mode. If using \"timer\" as an argument, a timerspecific pingmessage will be set)"
helpReload: "&6/maintenance reload &7(Reloads the config file, whitelist file and the server-icon)"
helpToggle: "&6/maintenance <on/off> &7(Enables/disables maintenance mode)"
helpUpdate: "&6/maintenance update &7(Remotely downloads the newest version of the plugin onto your server)"
helpWhitelist: "&6/maintenance whitelist &7(Shows all whitelisted players for the maintenance mode)"
helpWhitelistAdd: "&6/maintenance add <name/uuid> &7(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)"
helpWhitelistRemove: "&6/maintenance remove <name/uuid> &7(Removes the player from the maintenance whitelist)"
helpNextPage: "&7Use &b/maintenance help %PAGE% &7para ir para a próxima págin."
helpAbortTimer: "&6/maintenance aborttimer &7(Se estiver a correr o temporizador vai ser abortado)"
helpEndtimer: "&6/maintenance endtimer <minutes> &7(Depois do temporizador acabar a manutenção vai ser desativada)"
helpStarttimer: "&6/maintenance starttimer <minutes> &7(Depois do temporizador acabar a manutenção vai ser ativa)"
helpDebug: "&6/maintenance debug &7(Enables some debug logging)"
helpDump: "&6/maintenance dump &7(Discarta alguma informação do server, usado para bugs)"
helpHelp: "&6/maintenance help [page] &7(Mostra o help da manutenção)"
helpMotd: "&6/maintenance motd [timer] &7(Lista as motd currentes. Se usar 'timer', os temporizadores vão ser mostrados)"
helpRemoveMotd: "&6/maintenance removemotd [timer] <index> &7(Remove a motd da manutenção. Se usar \"timer\" como argumento uma mensagem com tempo vai ser eliminada)"
helpSetMotd: "&6/maintenance setmotd [timer] <index> <1/2> <message> &7(Define a motd da manutenção. Se usar \"timer\" como argumento uma mensagem com tempo vai aparecer)"
helpReload: "&6/maintenance reload &7(Dá reload ao plugin de manutenção)"
helpToggle: "&6/maintenance <on/off> &7(Ativa/Desativa a manutenção)"
helpUpdate: "&6/maintenance update &7(Arualiza o plugin de manutenção)"
helpWhitelist: "&6/maintenance whitelist &7(Mostra os payers que estão na whitelist)"
helpWhitelistAdd: "&6/maintenance add <name/uuid> &7(Adiciona o player à whitelist para poder entrar durante a manutenção)"
helpWhitelistRemove: "&6/maintenance remove <name/uuid> &7(Remove o player da whitelist)"
# Algumas mensagens para o Bungee/Velocity, ignora-as se estas a usar Spigot/Sponge
helpAbortSingleTimer: "&6/maintenance aborttimer [server] &7(If running, the current timer will be aborted)"
helpSingleEndtimer: "&6/maintenance endtimer [server] <minutes> &7(After the given time in minutes, maintenance mode will be disabled)"
helpSingleStarttimer: "&6/maintenance starttimer [server] <minutes> &7(After the given time in minutes, maintenance mode will be enabled)"
helpSingleToggle: "&6/maintenance <on/off> [server] &7(Enables/disables maintenance mode)"
helpStatus: "&6/maintenance status &7(Lists all proxied servers, that are currently under maintenance)"
helpAbortSingleTimer: "&6/maintenance aborttimer [server] &7(Se o timer estiver ativado este vai ser abortado)"
helpSingleEndtimer: "&6/maintenance endtimer [server] <minutes> &7(Depois do tempo dado a manutenção vai ser desativada)"
helpSingleStarttimer: "&6/maintenance starttimer [server] <minutes> &7(Depois do tempo dado a manutenção vai ser ativa)"
helpSingleScheduleTimer: "&6/maintenance scheduletimer [server] <timer minutes> <maintenance duration> &7(After the given time in minutes, maintenance mode will be enabled for the given duration in minutes)"
helpSingleToggle: "&6/maintenance <on/off> [server] &7(Ativa/Desativa a manutenção)"
helpStatus: "&6/maintenance status &7(Lista os servers em proxy que estão em manutenção)"
Loaded 100 of 137 files, more files were not shown because too many files have changed in this diff. Show more