Compare commits

...
17 Commits
Author SHA1 Message Date
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
46 changed files with 787 additions and 360 deletions

No files matched your search

+14 -2
View File
@@ -1,7 +1,19 @@
# 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.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 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 +27,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
+1 -1
View File
@@ -20,7 +20,7 @@ Its features include:
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)
* [Development builds](https://kennytv.eu/maintenance/snapshot/) (out of order at the moment)
* [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)
+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.4</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.15-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.15.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -52,6 +52,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.
*
+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.4</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.4</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.15-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>
@@ -116,9 +116,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());
}
}
@@ -127,15 +127,32 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
@Override
protected void kickPlayers(final Server server, final Server fallback) {
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);
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
p.disconnect(settingsProxy.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", server.getName()));
player.disconnect(settingsProxy.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", 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) {
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());
}
}
}
@@ -166,7 +183,8 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
@Override
public String getServer(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
@@ -18,38 +18,49 @@
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 (shouldKick(sender)) {
final Server waitingServer = shouldConnectToWaitingServer(sender);
if (waitingServer != null) {
event.setTarget(((BungeeServer) waitingServer).getServer());
sender.sendMessage(settings.getMessage("sentToWaitingServer"));
return;
}
event.setCancelled(true);
event.getPlayer().disconnect(settings.getKickMessage());
if (settings.isJoinNotifications()) {
broadcastJoinNotification(sender.getName());
}
}
}
@@ -59,49 +70,36 @@ 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);
}
}
}
// 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) {
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 (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;
@@ -79,6 +80,7 @@ public final class MetricsLite {
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 +94,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 +149,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 +159,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 +201,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 +210,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 +223,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 +239,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 +262,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();
}
@@ -18,14 +18,16 @@
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 +62,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);
}
}
}
+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.4</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>3.4.2</version>
<scope>compile</scope>
<!-- Shade slf4j specifically and only in the Bungee module to prevent issues -->
<exclusions>
@@ -47,14 +47,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);
}
@@ -79,13 +81,16 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
if (maintenance) {
final Server fallback = getServer(settingsProxy.getFallbackServer());
if (fallback == null) {
if (server.hasPlayers())
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()))
}
} 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);
eventManager.callEvent(new ServerMaintenanceChangedEvent(server, maintenance));
}
@@ -107,7 +112,7 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
}
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final Server server, final int minutes, final boolean enable) {
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, settingsProxy, minutes, enable, server);
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, settingsProxy, minutes * 60, enable, server);
serverTasks.put(server.getName(), runnable.getTask());
return runnable;
}
@@ -125,6 +130,21 @@ 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();
}
public SettingsProxy getSettingsProxy() {
return settingsProxy;
}
@@ -132,4 +152,8 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
public abstract String getServer(SenderInfo sender);
protected abstract void kickPlayers(Server server, Server fallback);
protected abstract void kickPlayersTo(Server server);
protected abstract void kickPlayersFromProxy();
}
@@ -31,6 +31,7 @@ import java.util.Set;
public final class SettingsProxy extends Settings {
private Set<String> maintenanceServers;
private String fallbackServer;
private String waitingServer;
private String mySQLTable;
private String serverTable;
@@ -54,11 +55,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");
@@ -84,6 +87,11 @@ public final class SettingsProxy extends Settings {
}
fallbackServer = config.getString("fallback", "lobby");
waitingServer = config.getString("waiting-server", "");
if (waitingServer.isEmpty() || waitingServer.equalsIgnoreCase("none")) {
waitingServer = null;
}
if (hasMySQL()) {
maintenance = loadMaintenance();
maintenanceServers = loadMaintenanceServersFromSQL();
@@ -215,6 +223,10 @@ public final class SettingsProxy extends Settings {
return fallbackServer;
}
public String getWaitingServer() {
return waitingServer;
}
MySQL getMySQL() {
return mySQL;
}
@@ -67,10 +67,12 @@ 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.getServer(sender))) {
sender.sendMessage(getMessage(maintenance ? "singleMaintenanceActivated" : "singleMaintenanceDeactivated").replace("%SERVER%", server.getName()));
} else
}
} else {
sender.sendMessage(getMessage(maintenance ? "singleServerAlreadyEnabled" : "singleServerAlreadyDisabled").replace("%SERVER%", server.getName()));
}
} else
sender.sendMessage(getHelpMessage());
}
@@ -0,0 +1,120 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.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;
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.getServer(sender);
if (currentServer != null && currentServer.equals(waitingServer.getName())) {
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.getMessage("singleMaintenanceKick").replace("%SERVER%", 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 = plugin.getServer(settings.getFallbackServer());
if (fallback == null || !sender.canAccess(fallback) || plugin.isMaintenance(fallback)) {
// Nothing to redirect to, player has to be kicked from the proxy
sender.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;
}
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
*/
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);
}
@@ -8,19 +8,30 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
public final class MySQL {
private final Logger logger;
private final HikariDataSource hikariDataSource;
// Excuse me and everything to do with the MySQL stuff, I have little to no idea of how to use databases
public MySQL(final String hostname, final int port, final String username, final String password, final String database) {
public MySQL(final Logger logger, final String hostname, final int port, final String username, final String password, final String database, final boolean useSSL) {
this.logger = logger;
final HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setMaximumPoolSize(10);
hikariConfig.addDataSourceProperty("serverName", hostname);
hikariConfig.addDataSourceProperty("user", username);
hikariConfig.addDataSourceProperty("password", password);
hikariConfig.addDataSourceProperty("url", "jdbc:mysql://" + hostname + ":" + port + "/" + database);
hikariConfig.setJdbcUrl("jdbc:mysql://" + hostname + ":" + port + "/" + database);
String urlProperty = "jdbc:mysql://" + hostname + ":" + port + "/" + database;
if (useSSL) {
urlProperty += "?useSSL=false";
}
hikariConfig.addDataSourceProperty("url", urlProperty);
hikariConfig.setJdbcUrl(urlProperty);
hikariConfig.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
hikariDataSource = new HikariDataSource(hikariConfig);
}
@@ -37,7 +48,7 @@ public final class MySQL {
callback.accept(preparedStatement.executeUpdate());
}
} catch (final SQLException e) {
System.out.println("Error while executing update method: " + query);
logger.log(Level.SEVERE, "Error while executing update method: " + query);
e.printStackTrace();
}
}
@@ -56,7 +67,7 @@ public final class MySQL {
resultSet.close();
}
} catch (final SQLException e) {
System.out.println("Error while executing query method: " + query);
logger.log(Level.SEVERE, "Error while executing query method: " + query);
e.printStackTrace();
}
}
@@ -32,6 +32,11 @@ public final class SingleMaintenanceRunnable extends MaintenanceRunnableBase {
this.server = server;
}
@Override
protected void broadcast(final String message) {
server.broadcast(message);
}
@Override
protected void finish() {
((IMaintenanceProxy) plugin).setMaintenanceToServer(server, enable);
@@ -38,6 +38,6 @@ public final class DummyServer implements Server {
}
@Override
public void broadcast(String s) {
public void broadcast(final String s) {
}
}
@@ -0,0 +1,29 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.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,44 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.core.proxy.util;
import eu.kennytv.maintenance.api.proxy.Server;
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;
}
public Server getTarget() {
return target;
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.3</version>
<version>3.0.4</version>
</parent>
<artifactId>maintenance-core</artifactId>
@@ -79,18 +79,22 @@ public abstract class MaintenancePlugin implements IMaintenance {
}
public void serverActions(final boolean maintenance) {
if (isTaskRunning())
if (isTaskRunning()) {
cancelTask();
if (serverListPlusHook != null)
}
if (serverListPlusHook != null) {
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));
}
@@ -204,8 +208,9 @@ public abstract class MaintenancePlugin implements IMaintenance {
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) {
}
}
@@ -31,7 +31,7 @@ import java.util.*;
import java.util.logging.Level;
public class Settings implements ISettings {
private static final int CURRENT_CONFIG_VERSION = 3;
private static final int CURRENT_CONFIG_VERSION = 4;
private static final Random RANDOM = new Random();
protected final MaintenancePlugin plugin;
private final Map<UUID, String> whitelistedPlayers = new HashMap<>();
@@ -118,7 +118,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 +132,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();
}
}
}
@@ -151,23 +153,27 @@ public class Settings implements ISettings {
updateConfig();
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");
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"));
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,6 +186,7 @@ public class Settings implements ISettings {
plugin.getLogger().warning("invalid WhitelistedPlayers entry: " + entry.getKey());
}
}
loadExtraSettings();
}
@@ -192,10 +199,11 @@ public class Settings implements ISettings {
// 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")))
if (file.renameTo(new File(plugin.getDataFolder(), "language-" + languageName + ".old"))) {
plugin.getLogger().info("Renamed old language file!");
else
} else {
plugin.getLogger().warning("Could not rename old language file! Please rename/delete it yourself as soon as possible!");
}
}
changed = true;
@@ -207,10 +215,11 @@ public class Settings implements ISettings {
// 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")))
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
} 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)
@@ -241,16 +250,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,11 +277,10 @@ 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!");
}
}
@@ -296,10 +307,11 @@ public class Settings implements ISettings {
}
oldConfig.clear();
if (!file.delete())
if (!file.delete()) {
plugin.getLogger().warning("Could not delete old config file! Please delete it as soon as possible.");
else
} else {
plugin.getLogger().info("Updated to new config file!");
}
return true;
}
@@ -316,16 +328,19 @@ public class Settings implements ISettings {
return false;
}
if (oldFile.contains("maintenance-on"))
if (oldFile.contains("maintenance-on")) {
config.set("proxied-maintenance-servers", oldFile.getStringList("maintenance-on"));
if (oldFile.contains("fallback"))
}
if (oldFile.contains("fallback")) {
config.set("fallback", oldFile.getString("fallback"));
}
oldFile.clear();
if (!file.delete())
if (!file.delete()) {
plugin.getLogger().warning("Could not delete old SpigotServers.yml file! Please delete it as soon as possible.");
else
} else {
plugin.getLogger().info("Deleted old SpigotServers.yml file!");
}
return true;
}
@@ -417,6 +432,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;
@@ -43,19 +43,19 @@ 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) {
@@ -42,10 +42,7 @@ 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 ? startMessageKey() : endMessageKey());
}
seconds--;
@@ -82,6 +79,10 @@ 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();
@@ -22,6 +22,10 @@ proxied-maintenance-servers:
# If the fallback server is not reachable/not set, they will just be kicked off the network.
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).
@@ -59,7 +63,7 @@ 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)
# Currently available are: en (English), de (German), fr (French), pt (Portuguese), es (Spanish), ru (Russian)
language: en
# If you have 2 or more proxy instances, the database connection will make sure all proxies
@@ -77,6 +81,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 +101,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: 4
@@ -43,7 +43,10 @@ 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."
@@ -43,7 +43,10 @@ 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."
@@ -43,7 +43,10 @@ playerNotOnline: "&8[&eMaintenance&8] &7No hay jugador en línea con ese 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] &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] &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."
@@ -43,7 +43,10 @@ playerNotOnline: "&8[&eMaintenance&8] &cIl n'y a pas de joueur en ligne avec ce
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
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] &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."
@@ -15,19 +15,19 @@ 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,7 +43,10 @@ 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!"
@@ -67,25 +70,25 @@ 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)"
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)"
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)"
@@ -0,0 +1,94 @@
# Maintenance Plugin by KennyTV
# Don't remove words inbetween the '%' if you don't exactly know why you're doing it
noPermission: "&cУ вас недостаточно прав!"
kickmessage: "&cСервер закрыт на тех. работы!"
maintenanceActivated: "&aРежим тех. работ включен!"
maintenanceDeactivated: "&7Режим тех. работ выключен!"
alreadyEnabled: "&cРежим тех. работ уже включен!"
alreadyDisabled: "&cРежим тех. работ не был включен."
endtimerBroadcast: "&aСервер будет открыт через &f%TIME% &aминут."
endtimerStarted: "&aТаймер успешно запущен! &aСервер будет открыт через &f%TIME% &aминут."
starttimerBroadcast: "&aСервер будет закрыт на тех. работы через &f%TIME% &aминут."
starttimerStarted: "&aТаймер успешно запущен! &aСервер будет закрыт на тех. работы через &f%TIME% &aминут."
timerAlreadyRunning: "&cТаймер уже запущен!"
timerNotRunning: "&cТаймер не был запущен."
timerCancelled: "&7Таймер был остановлен."
timerTooLong: "&cЧисло должно быть не больше чем &f40320 &c(&f28 &cдней)."
timerMotdDisabled: "&cСообщения по таймеру выключены в настройках плагина."
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
motdTimerNotRunning: "-"
joinNotification: "&cИгрок &f%PLAYER% &cпытался зайти на сервер."
motdList: "&7Список титульных строк в режиме тех. работ:"
motdListEmpty: "&cСписок пуст."
reload: "&aПлагин успешно перезагружен!"
removedMotd: "&aТитульная строка с индексом &f%INDEX% &aуспешно удалена!"
removeMotdError: "&cВы не можете удалить последние 2 титульные строки."
setMotd: "&aТитульная строка &f%LINE% &aс индексом &f%INDEX% &aуспешно изменена: &f%MOTD%"
setMotdIndexError: "&cНеверный индекс, допустимые значения: 1 - %NEWAMOUNT%."
setMotdLineError: "&cВторой аргумент должен быть номером строки (1 или 2)!"
updateDownloading: "&aОбновление загружается..."
updateFailed: "&cОбновление не удалось!"
updateFinished: "&aОбновление успешно пройдено! Перезагрузите сервер, чтобы избежать возможных проблем."
whitelistedPlayers: "&7Белый лист в режиме тех. работ:"
whitelistedPlayersFormat: "&7- &f%NAME% &7(&f%UUID%&7)"
whitelistAdded: "&aИгрок &f%PLAYER% &aуспешно добавлен в белый лист!"
whitelistAlreadyAdded: "&cИгрок &f%PLAYER% &cуже в белом листе!"
whitelistRemoved: "&aИгрок &f%PLAYER% &aуспешно удалён из белого листа!"
whitelistNotFound: "&cДанный игрок не находится в белом листе!"
whitelistEmpty: "&cБелый лист пуст! Используйте /maintenance add [игрок|uuid] чтобы добавить кого-нибудь."
playerNotFound: "&cИгрок не найден!"
playerNotFoundUuid: "&cИгрок с таким UUID не найден!"
playerNotOnline: "&cИгрок должен быть онлайн!"
invalidUuid: "&cНеверный формат UUID!"
# Messages for the Bungee/Velocity part, just can ignore them if you use the plugin on Spigot/Sponge
sentToWaitingServer: "&cYou have been sent to a waiting server!"
forceWaitingServer: "&cYou cannot leave the waiting server while maintenance is enabled!"
serverNotFound: "&cСервер не найден!"
singleTimerAlreadyRunning: "&cТаймер сервера &f%SERVER% &cуже запущен!"
singleTimerCancelled: "&7Таймер сервера &f%SERVER% &7был остановлен."
singleTimerNotRunning: "&cТаймер сервера &f%SERVER% &cне был запущен."
singleEndtimerBroadcast: "&aСервер &f%SERVER% &aбудет открыт через &f%TIME% &aминут."
singleStarttimerBroadcast: "&cВнимание! Сервер &f%SERVER% &cбудет закрыт на тех. работы через &f%TIME%&c."
singleMaintenanceKick: "&cДанный сервер закрыт на тех. работы! Попробуйте позже."
singleMaintenanceKickComplete: "&cДанный сервер закрыт на тех. работы!%NEWLINE%&cПопробуйте позже."
singleMaintenanceActivated: "&aРежим тех. работ на сервере &f%SERVER% &aвключен!"
singleMaintenanceDeactivated: "&aРежим тех. работ на сервере &f%SERVER% &aвыключен!"
singleServerAlreadyEnabled: "&cРежим тех. работ на сервере &f%SERVER% &cуже включен!"
singleServerAlreadyDisabled: "&cРежим тех. работ на сервере &f%SERVER% &cне был включен."
singleServerMaintenanceList: "&7Сервера на которых включен режим тех. работ:"
singleServerMaintenanceListEmpty: "&7Сервера на которых включен режим тех. работ: &fпусто"
second: "секунда"
seconds: "секунд"
minute: "минута"
minutes: "минут"
hour: "час"
hours: "часов"
helpHeader: "&7========[ &f%NAME% &7| &6%PAGE%&f/&6%MAX% &7]========"
helpPageNotFound: "&cСтраница не найдена."
helpNextPage: "&fИспользуйте &6/maintenance help %PAGE% &fчтобы перейти на следующую страницу."
helpAbortTimer: "&6/maintenance aborttimer &7- &fОстановить таймер включения/выключения режима тех. работ."
helpEndtimer: "&6/maintenance endtimer [время в минутах] &7- &fЗапустить таймер выключения режима тех. работ."
helpStarttimer: "&6/maintenance starttimer [время в минутах] &7- &fЗапустить таймер включения режима тех. работ."
helpDump: "&6/maintenance dump &7- &fСоздать дамп."
helpHelp: "&6/maintenance help [страница] &7- &fОтобразить список доступных команд."
helpMotd: "&6/maintenance motd <timer> &7- &fОтобразить список титульных сообщений."
helpRemoveMotd: "&6/maintenance removemotd <timer> [индекс] &7- &fУдалить титульное сообщение."
helpSetMotd: "&6/maintenance setmotd <timer> [индекс] [1|2] [сообщение] &7- &fДобавить новое титульное сообщение."
helpReload: "&6/maintenance reload &7- &fПерезагрузить плагин."
helpToggle: "&6/maintenance [on|off] &7- &fВключить/выключить режим тех. работ."
helpUpdate: "&6/maintenance update &7- &fОбновить плагин."
helpWhitelist: "&6/maintenance whitelist &7- &fОтобразить всех игроков из белого списка."
helpWhitelistAdd: "&6/maintenance add [ник|uuid] &7- &fДобавить игрока в белый список."
helpWhitelistRemove: "&6/maintenance remove [ник|uuid] &7- &fУдалить игрока из белого списка."
# Messages for the Bungee/Velocity part, just can ignore them if you use the plugin on Spigot/Sponge
helpAbortSingleTimer: "&6/maintenance aborttimer [сервер] &7- &fОстановить таймер включения/выключения режима тех. работ."
helpSingleEndtimer: "&6/maintenance endtimer [сервер] [время в минутах] &7- &fЗапустить таймер выключения режима тех. работ."
helpSingleStarttimer: "&6/maintenance starttimer [сервер] [время в минутах] &7- &fЗапустить таймер включения режима тех. работ."
helpSingleToggle: "&6/maintenance [on|off] [сервер] &7- &fВключить/выключить режим тех. работы."
helpStatus: "&6/maintenance status &7- &fСписок всех серверов закрытых на тех. работы."
+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.4</version>
</parent>
<artifactId>maintenance-spigot</artifactId>
@@ -22,7 +22,7 @@
<dependency>
<groupId>com.destroystokyo.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.14.4-R0.1-SNAPSHOT</version>
<version>1.15.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Needed for backwards compatibility with Paper -->
@@ -69,7 +69,7 @@ public final class MaintenanceSpigotPlugin extends MaintenancePlugin {
super(plugin.getDescription().getVersion(), ServerType.SPIGOT);
this.plugin = plugin;
settings = new Settings(this, "mysql", "proxied-maintenance-servers", "fallback");
settings = new Settings(this, "mysql", "proxied-maintenance-servers", "fallback", "waiting-server");
sendEnableMessage();
@@ -82,13 +82,11 @@ public final class MaintenanceSpigotPlugin extends MaintenancePlugin {
if (canUsePaperListener()) {
pm.registerEvents(new PaperServerListPingListener(this, settings), plugin);
} else if (pm.isPluginEnabled("ProtocolLib")) {
pm.registerEvents(new ServerInfoPacketListener(this, plugin, settings), plugin);
} else {
if (pm.isPluginEnabled("ProtocolLib")) {
pm.registerEvents(new ServerInfoPacketListener(this, plugin, settings), plugin);
} else {
pm.registerEvents(new ServerListPingListener(this, settings), plugin);
getLogger().warning("To use this plugin on Spigot to its full extend, you need the plugin ProtocolLib!");
}
pm.registerEvents(new ServerListPingListener(this, settings), plugin);
getLogger().warning("To use this plugin on Spigot to its full extend, you need the plugin ProtocolLib!");
}
continueLastEndtimer();
@@ -164,7 +162,7 @@ public final class MaintenanceSpigotPlugin extends MaintenancePlugin {
@Override
protected void kickPlayers() {
for (final Player p : getServer().getOnlinePlayers()) {
if (!hasPermission(p, "bypass") && !settings.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
if (!hasPermission(p, "bypass") && !settings.isWhitelisted(p.getUniqueId())) {
p.kickPlayer(settings.getKickMessage());
}
}
@@ -38,9 +38,12 @@ public final class PlayerLoginListener extends JoinListenerBase implements Liste
@EventHandler
public void postLogin(final PlayerLoginEvent event) {
final BukkitSenderInfo sender = new BukkitSenderInfo(event.getPlayer());
if (kickPlayer(sender)) {
if (shouldKick(sender)) {
event.setResult(PlayerLoginEvent.Result.KICK_OTHER);
event.setKickMessage(settings.getKickMessage());
if (settings.isJoinNotifications()) {
broadcastJoinNotification(sender.getName());
}
}
}
@@ -29,6 +29,7 @@ import java.util.zip.GZIPOutputStream;
public final class MetricsLite {
public static final int B_STATS_VERSION = 1;
private static final int PLUGIN_ID = 2205;
private static final String URL = "https://bStats.org/submitData/bukkit";
private final boolean enabled;
private static boolean logFailedRequests;
@@ -113,6 +114,7 @@ public final class MetricsLite {
final String pluginVersion = plugin.getDescription().getVersion();
data.addProperty("pluginName", pluginName);
data.addProperty("id", PLUGIN_ID);
data.addProperty("pluginVersion", pluginVersion);
data.add("customCharts", new JsonArray());
@@ -221,21 +223,18 @@ 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);
} else {
connection.getInputStream().close();
@@ -247,9 +246,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 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.3</version>
<version>3.0.4</version>
</parent>
<artifactId>maintenance-sponge</artifactId>
@@ -94,7 +94,7 @@ public final class MaintenanceSpongePlugin extends MaintenancePlugin {
public void onEnable(final GameInitializationEvent event) {
logger = new LoggerWrapper(container.getLogger());
settings = new Settings(this, "mysql", "proxied-maintenance-servers", "fallback",
settings = new Settings(this, "mysql", "proxied-maintenance-servers", "fallback", "waiting-server",
"playercountmessage", "enable-playercountmessage");
sendEnableMessage();
@@ -178,7 +178,7 @@ public final class MaintenanceSpongePlugin extends MaintenancePlugin {
@Override
protected void kickPlayers() {
for (final Player p : getServer().getOnlinePlayers()) {
if (!hasPermission(p, "bypass") && !settings.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
if (!hasPermission(p, "bypass") && !settings.isWhitelisted(p.getUniqueId())) {
p.kick(Text.of(settings.getKickMessage()));
}
}
@@ -38,9 +38,13 @@ public final class ClientConnectionListener extends JoinListenerBase {
@Listener
public void login(final ClientConnectionEvent.Login event) {
if (kickPlayer(new SpongeSenderInfo(event.getTargetUser().getPlayer().get()), false)) {
final Player player = event.getTargetUser().getPlayer().get();
if (shouldKick(new SpongeSenderInfo(player), false)) {
event.setCancelled(true);
event.setMessage(Text.of(settings.getKickMessage()));
if (settings.isJoinNotifications()) {
broadcastJoinNotification(player.getName());
}
}
}
+3 -3
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.3</version>
<version>3.0.4</version>
</parent>
<artifactId>maintenance-velocity</artifactId>
@@ -29,7 +29,7 @@
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>1.0.4-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>
@@ -23,7 +23,6 @@ import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.EventManager;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.player.ServerPreConnectEvent;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
import com.velocitypowered.api.event.proxy.ProxyReloadEvent;
@@ -45,7 +44,6 @@ 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.velocity.command.MaintenanceVelocityCommand;
import eu.kennytv.maintenance.velocity.listener.LoginListener;
import eu.kennytv.maintenance.velocity.listener.ProxyPingListener;
import eu.kennytv.maintenance.velocity.listener.ServerConnectListener;
import eu.kennytv.maintenance.velocity.util.LoggerWrapper;
@@ -74,7 +72,7 @@ import java.util.stream.Collectors;
* @since 3.0
*/
@Plugin(id = "maintenancevelocity", name = "MaintenanceVelocity", version = MaintenanceVersion.VERSION, authors = "KennyTV",
description = "Enable maintenance mode with a custom maintenance motd and icon.", url = "https://www.spigotmc.org/resources/maintenance.40699/",
description = "Enable maintenance mode with a custom maintenance motd and icon.", url = "https://forums.velocitypowered.com/t/maintenance/129",
dependencies = @Dependency(id = "serverlistplus", optional = true))
public final class MaintenanceVelocityPlugin extends MaintenanceProxyPlugin {
private final ProxyServer server;
@@ -102,8 +100,7 @@ public final class MaintenanceVelocityPlugin extends MaintenanceProxyPlugin {
server.getCommandManager().register(command, "maintenance", "maintenancevelocity");
final EventManager em = server.getEventManager();
em.register(this, ProxyPingEvent.class, PostOrder.LAST, new ProxyPingListener(this, settingsProxy));
em.register(this, ServerPreConnectEvent.class, PostOrder.LAST, new ServerConnectListener(this, settingsProxy));
em.register(this, new LoginListener(this, settingsProxy));
em.register(this, new ServerConnectListener(this, settingsProxy));
continueLastEndtimer();
@@ -143,9 +140,9 @@ public final class MaintenanceVelocityPlugin extends MaintenanceProxyPlugin {
}
@Override
protected void kickPlayers() {
protected void kickPlayersFromProxy() {
for (final Player p : server.getAllPlayers()) {
if (!hasPermission(p, "bypass") && !settingsProxy.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
if (!hasPermission(p, "bypass") && !settingsProxy.isWhitelisted(p.getUniqueId())) {
p.disconnect(TextComponent.of(settingsProxy.getKickMessage()));
}
}
@@ -154,19 +151,43 @@ public final class MaintenanceVelocityPlugin extends MaintenanceProxyPlugin {
@Override
protected void kickPlayers(final Server server, final Server fallback) {
final RegisteredServer fallbackServer = fallback != null ? ((VelocityServer) fallback).getServer() : null;
for (final Player p : ((VelocityServer) server).getServer().getPlayersConnected()) {
if (!hasPermission(p, "bypass") && !settingsProxy.getWhitelistedPlayers().containsKey(p.getUniqueId())) {
if (fallbackServer != null && !isMaintenance(fallback)) {
p.sendMessage(translate(settingsProxy.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName())));
final boolean checkForFallback = fallbackServer != null && !isMaintenance(fallback);
for (final Player player : ((VelocityServer) server).getServer().getPlayersConnected()) {
if (!hasPermission(player, "bypass") && !settingsProxy.isWhitelisted(player.getUniqueId())) {
if (checkForFallback) {
player.sendMessage(translate(settingsProxy.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName())));
// Kick the player if fallback server is not reachable
p.createConnectionRequest(fallbackServer).connect().whenComplete((result, e) -> {
if (!result.isSuccessful())
p.disconnect(TextComponent.of(settingsProxy.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", server.getName())));
player.createConnectionRequest(fallbackServer).connect().whenComplete((result, e) -> {
if (!result.isSuccessful()) {
player.disconnect(TextComponent.of(settingsProxy.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", server.getName())));
}
});
} else
p.disconnect(TextComponent.of(settingsProxy.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", server.getName())));
player.disconnect(TextComponent.of(settingsProxy.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n").replace("%SERVER%", server.getName())));
} else {
p.sendMessage(translate(settingsProxy.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName())));
player.sendMessage(translate(settingsProxy.getMessage("singleMaintenanceActivated").replace("%SERVER%", server.getName())));
}
}
}
@Override
protected void kickPlayersTo(final Server server) {
final RegisteredServer waitingServer = ((VelocityServer) server).getServer();
// Notifications done in global method
for (final Player player : this.server.getAllPlayers()) {
if (hasPermission(player, "bypass") || settingsProxy.isWhitelisted(player.getUniqueId())) continue;
if (player.getCurrentServer().isPresent() && player.getCurrentServer().get().getServerInfo().getName().equals(waitingServer.getServerInfo().getName()))
continue;
if (!isMaintenance(waitingServer)) {
player.createConnectionRequest(waitingServer).connect().whenComplete((result, e) -> {
if (result.isSuccessful()) {
player.sendMessage(translate(settingsProxy.getMessage("sentToWaitingServer").replace("%SERVER%", server.getName())));
} else {
player.disconnect(TextComponent.of(settingsProxy.getKickMessage()));
}
});
} else {
player.disconnect(TextComponent.of(settingsProxy.getKickMessage()));
}
}
}
@@ -197,7 +218,7 @@ public final class MaintenanceVelocityPlugin extends MaintenanceProxyPlugin {
@Override
public String getServer(final SenderInfo sender) {
final Optional<Player> player = server.getPlayer(sender.getUuid());
if (!player.isPresent() || player.get().getCurrentServer().isPresent()) return "";
if (!player.isPresent() || !player.get().getCurrentServer().isPresent()) return null;
return player.get().getCurrentServer().get().getServerInfo().getName();
}
@@ -81,7 +81,7 @@ public final class MaintenanceVelocityCommand extends MaintenanceProxyCommand im
final List<String> list = new ArrayList<>();
for (final RegisteredServer server : plugin.getServer().getAllServers()) {
final String name = server.getServerInfo().getName();
if (name.toLowerCase().startsWith(s) && !plugin.getSettingsProxy().getFallbackServer().contains(name)) {
if (name.toLowerCase().startsWith(s) && !plugin.getSettingsProxy().getMaintenanceServers().contains(name)) {
list.add(name);
}
}
@@ -1,61 +0,0 @@
/*
* Maintenance - https://git.io/maintenancemode
* Copyright (C) 2018 KennyTV (https://github.com/KennyTV)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.maintenance.velocity.listener;
import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.LoginEvent;
import com.velocitypowered.api.event.connection.PostLoginEvent;
import com.velocitypowered.api.proxy.Player;
import eu.kennytv.maintenance.core.Settings;
import eu.kennytv.maintenance.core.listener.JoinListenerBase;
import eu.kennytv.maintenance.velocity.MaintenanceVelocityPlugin;
import eu.kennytv.maintenance.velocity.util.VelocitySenderInfo;
import net.kyori.text.TextComponent;
public final class LoginListener extends JoinListenerBase {
private final MaintenanceVelocityPlugin plugin;
public LoginListener(final MaintenanceVelocityPlugin plugin, final Settings settings) {
super(plugin, settings);
this.plugin = plugin;
}
@Subscribe
public void login(final LoginEvent event) {
if (!event.getResult().isAllowed()) return;
if (kickPlayer(new VelocitySenderInfo(event.getPlayer()), false))
event.setResult(ResultedEvent.ComponentResult.denied(plugin.translate(settings.getKickMessage())));
}
@Subscribe
public void postLogin(final PostLoginEvent event) {
updateCheck(new VelocitySenderInfo(event.getPlayer()));
}
@Override
protected void broadcastJoinNotification(final String name) {
final TextComponent s = plugin.translate(settings.getMessage("joinNotification").replace("%PLAYER%", name));
for (final Player p : plugin.getServer().getAllPlayers()) {
if (plugin.hasPermission(p, "joinnotification")) {
p.sendMessage(s);
}
}
}
}
@@ -18,72 +18,94 @@
package eu.kennytv.maintenance.velocity.listener;
import com.velocitypowered.api.event.EventHandler;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.LoginEvent;
import com.velocitypowered.api.event.connection.PostLoginEvent;
import com.velocitypowered.api.event.player.ServerPreConnectEvent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
import eu.kennytv.maintenance.core.proxy.listener.ProxyJoinListenerBase;
import eu.kennytv.maintenance.core.proxy.util.ServerConnectResult;
import eu.kennytv.maintenance.velocity.MaintenanceVelocityPlugin;
import eu.kennytv.maintenance.velocity.util.VelocitySenderInfo;
import eu.kennytv.maintenance.velocity.util.VelocityServer;
import net.kyori.text.TextComponent;
import java.util.Optional;
public final class ServerConnectListener implements EventHandler<ServerPreConnectEvent> {
public final class ServerConnectListener extends ProxyJoinListenerBase {
private final MaintenanceVelocityPlugin plugin;
private final SettingsProxy settings;
private boolean warned;
public ServerConnectListener(final MaintenanceVelocityPlugin plugin, final SettingsProxy settings) {
super(plugin, settings);
this.plugin = plugin;
this.settings = settings;
}
@Subscribe
public void login(final LoginEvent event) {
if (!event.getResult().isAllowed()) return;
final VelocitySenderInfo sender = new VelocitySenderInfo(event.getPlayer());
if (shouldKick(sender, false)) {
final Server waitingServer = shouldConnectToWaitingServer(sender);
// Do the actual connecting in the ServerPreConnectEvent handler if a waiting server exists
if (waitingServer != null) return;
event.setResult(ResultedEvent.ComponentResult.denied(plugin.translate(settings.getKickMessage())));
if (settings.isJoinNotifications()) {
broadcastJoinNotification(event.getPlayer().getUsername());
}
}
}
@Subscribe
public void postLogin(final PostLoginEvent event) {
updateCheck(new VelocitySenderInfo(event.getPlayer()));
}
@Subscribe(order = PostOrder.LAST)
public void preConnect(final ServerPreConnectEvent event) {
if (!event.getResult().isAllowed()) return;
final Optional<RegisteredServer> optionalTarget = event.getResult().getServer();
if (!optionalTarget.isPresent()) return;
final Player player = event.getPlayer();
final boolean hasCurrentServer = player.getCurrentServer().isPresent();
final ServerConnectResult connectResult = serverConnect(new VelocitySenderInfo(player), new VelocityServer(optionalTarget.get()), hasCurrentServer);
if (connectResult.isCancelled()) {
event.setResult(ServerPreConnectEvent.ServerResult.denied());
// Player has no server to connect to
if (!hasCurrentServer) {
player.disconnect(TextComponent.of(settings.getKickMessage()));
}
} else if (connectResult.getTarget() != null) {
final RegisteredServer newTarget = ((VelocityServer) connectResult.getTarget()).getServer();
event.setResult(ServerPreConnectEvent.ServerResult.allowed(newTarget));
}
}
@Override
public void execute(final ServerPreConnectEvent event) {
if (!event.getResult().isAllowed()) return;
final Player player = event.getPlayer();
if (!event.getResult().getServer().isPresent()) return;
final RegisteredServer target = event.getResult().getServer().get();
if (!plugin.isMaintenance(target)) return;
if (plugin.hasPermission(player, "bypass") || settings.getWhitelistedPlayers().containsKey(player.getUniqueId())
|| plugin.hasPermission(player, "singleserver.bypass." + target.getServerInfo().getName().toLowerCase()))
return;
event.setResult(ServerPreConnectEvent.ServerResult.denied());
if (settings.isJoinNotifications()) {
final TextComponent s = plugin.translate(settings.getMessage("joinNotification").replace("%PLAYER%", player.getUsername()));
for (final Player p : target.getPlayersConnected()) {
if (plugin.hasPermission(p, "joinnotification")) {
p.sendMessage(s);
}
}
}
// Normal serverconnect
if (player.getCurrentServer().isPresent()) {
player.sendMessage(plugin.translate(settings.getMessage("singleMaintenanceKick").replace("%SERVER%", target.getServerInfo().getName())));
return;
}
// If it's the initial proxy join or a kick from another server, go back to fallback server
final Optional<RegisteredServer> fallback = plugin.getServer().getServer(settings.getFallbackServer());
if (!fallback.isPresent() || plugin.isMaintenance(fallback.get())) {
disconnect(player, target);
if (!warned) {
plugin.getLogger().warning("Could not send player to the set fallback server! Instead kicking player off the network!");
warned = true;
}
} else {
player.createConnectionRequest(fallback.get()).connect().whenComplete((result, throwable) -> {
if (!result.isSuccessful()) disconnect(player, target);
});
}
protected void broadcastJoinNotification(final String name) {
sendJoinMessage(plugin.getServer().getAllPlayers(), name);
}
private void disconnect(final Player player, final RegisteredServer target) {
player.disconnect(TextComponent.of(settings.getMessage("singleMaintenanceKickComplete").replace("%NEWLINE%", "\n")
.replace("%SERVER%", target.getServerInfo().getName())));
@Override
protected void broadcastJoinNotification(final String name, final Server server) {
sendJoinMessage(((VelocityServer) server).getServer().getPlayersConnected(), name);
}
private void sendJoinMessage(final Iterable<Player> players, final String name) {
final TextComponent message = plugin.translate(settings.getMessage("joinNotification").replace("%PLAYER%", name));
for (final Player player : players) {
if (plugin.hasPermission(player, "joinnotification")) {
player.sendMessage(message);
}
}
}
}
@@ -20,13 +20,14 @@ package eu.kennytv.maintenance.velocity.util;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import eu.kennytv.maintenance.core.util.SenderInfo;
import eu.kennytv.maintenance.api.proxy.Server;
import eu.kennytv.maintenance.core.proxy.util.ProxySenderInfo;
import net.kyori.text.TextComponent;
import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
import java.util.UUID;
public final class VelocitySenderInfo implements SenderInfo {
public final class VelocitySenderInfo implements ProxySenderInfo {
private final CommandSource sender;
public VelocitySenderInfo(final CommandSource sender) {
@@ -61,4 +62,14 @@ public final class VelocitySenderInfo implements SenderInfo {
public void sendMessage(final TextComponent textComponent) {
sender.sendMessage(textComponent);
}
@Override
public boolean canAccess(final Server server) {
return true;
}
@Override
public void disconnect(final String message) {
((Player) sender).disconnect(TextComponent.of(message));
}
}
+6 -6
View File
@@ -6,7 +6,7 @@
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-parent</artifactId>
<version>3.0.3</version>
<version>3.0.4</version>
<packaging>pom</packaging>
<name>Maintenance</name>
@@ -39,14 +39,14 @@
</properties>
<repositories>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>spigotmc</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>sponge</id>
<url>http://repo.spongepowered.org/maven</url>
@@ -71,7 +71,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>