From cc6a78c12f82343ea52591cbb271d4be05f4f9c0 Mon Sep 17 00:00:00 2001 From: xGinko Date: Thu, 29 Feb 2024 23:12:57 +0100 Subject: [PATCH] improvements --- build.gradle.kts | 2 +- .../serverrestarts/ServerRestartsPaper.java | 4 +- .../commands/RestartGracefullyCmd.java | 12 +- .../config/PaperConfigImpl.java | 2 +- .../config/PaperLangCacheImpl.java | 11 +- .../serverrestarts/modules/FireWatch.java | 131 ++++++++++-------- .../modules/PlayerCountDelay.java | 19 ++- 7 files changed, 108 insertions(+), 73 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index cfefa02..8a451ef 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,6 @@ plugins { allprojects { group = "me.xginko.serverrestarts" - version = "1.0.0" + version = "1.1.0" description = "Simple server restarting plugin for modern server setups." } diff --git a/paper/src/main/java/me/xginko/serverrestarts/ServerRestartsPaper.java b/paper/src/main/java/me/xginko/serverrestarts/ServerRestartsPaper.java index cb3af0d..4b7f684 100644 --- a/paper/src/main/java/me/xginko/serverrestarts/ServerRestartsPaper.java +++ b/paper/src/main/java/me/xginko/serverrestarts/ServerRestartsPaper.java @@ -181,7 +181,7 @@ private void reloadLang() { } } } catch (Exception e) { - logger.error("Error loading language files! Language files will not reload to avoid errors, make sure to correct this before restarting the server!", e); + logger.error("Error loading language files!", e); } } @@ -192,7 +192,7 @@ private Set getDefaultLanguageFiles() { .filter(name -> name.startsWith("lang/") && name.endsWith(".yml")) .collect(Collectors.toSet()); } catch (IOException e) { - logger.error("Failed getting default lang files!", e); + logger.error("Failed getting default language files!", e); return Collections.emptySet(); } } diff --git a/paper/src/main/java/me/xginko/serverrestarts/commands/RestartGracefullyCmd.java b/paper/src/main/java/me/xginko/serverrestarts/commands/RestartGracefullyCmd.java index 5386334..957f125 100644 --- a/paper/src/main/java/me/xginko/serverrestarts/commands/RestartGracefullyCmd.java +++ b/paper/src/main/java/me/xginko/serverrestarts/commands/RestartGracefullyCmd.java @@ -42,7 +42,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command activeRestart.cancel(); sender.sendMessage(Component.text("Cancelled graceful restart.").color(NamedTextColor.GREEN)); } else { - sender.sendMessage(Component.text("There is no pending graceful restart.")); + sender.sendMessage(Component.text("There is no pending restart scheduled by this command.")); } return true; } @@ -82,10 +82,12 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command return; } - for (Player player : plugin.getServer().getOnlinePlayers()) { - switch (ServerRestartsPaper.getConfiguration().message_mode) { - case ACTIONBAR -> player.sendActionBar(ServerRestartsPaper.getLang(player.locale()).time_until_restart(remaining)); - case BROADCAST -> player.sendMessage(ServerRestartsPaper.getLang(player.locale()).time_until_restart(remaining)); + if (ServerRestartsPaper.getConfiguration().notification_times.stream().anyMatch(notifyTimeLeft -> notifyTimeLeft.equals(remaining))) { + for (Player player : plugin.getServer().getOnlinePlayers()) { + switch (ServerRestartsPaper.getConfiguration().message_mode) { + case ACTIONBAR -> player.sendActionBar(ServerRestartsPaper.getLang(player.locale()).time_until_restart(remaining)); + case BROADCAST -> player.sendMessage(ServerRestartsPaper.getLang(player.locale()).time_until_restart(remaining)); + } } } diff --git a/paper/src/main/java/me/xginko/serverrestarts/config/PaperConfigImpl.java b/paper/src/main/java/me/xginko/serverrestarts/config/PaperConfigImpl.java index 4662817..77cfafe 100755 --- a/paper/src/main/java/me/xginko/serverrestarts/config/PaperConfigImpl.java +++ b/paper/src/main/java/me/xginko/serverrestarts/config/PaperConfigImpl.java @@ -48,7 +48,7 @@ public PaperConfigImpl(File parentDirectory) throws Exception { "If set to true, will display messages based on client language"); // General Settings - this.tick_report_cache_time = Duration.ofMillis(Math.max(getInt("general.tps-cache-time-ticks", 40, + this.tick_report_cache_time = Duration.ofMillis(Math.max(getInt("general.tps-cache-time-ticks", 60, "How long a checked tps is cached to save resources in ticks (1 sec = 20 ticks)"), 20) * 50L); RestartMethod method = RestartMethod.BUKKIT_SHUTDOWN; String configuredMethod = getString("general.restart-method", RestartMethod.BUKKIT_SHUTDOWN.name(), diff --git a/paper/src/main/java/me/xginko/serverrestarts/config/PaperLangCacheImpl.java b/paper/src/main/java/me/xginko/serverrestarts/config/PaperLangCacheImpl.java index f7fc30c..0ff853a 100755 --- a/paper/src/main/java/me/xginko/serverrestarts/config/PaperLangCacheImpl.java +++ b/paper/src/main/java/me/xginko/serverrestarts/config/PaperLangCacheImpl.java @@ -41,7 +41,7 @@ public PaperLangCacheImpl(String locale) throws Exception { this.restart_delayed_playercount = getTranslation("messages.restart-delayed-high-playercount", "Delaying restart for %time% due to high playercount."); - this.restart_in = getTranslation("countdown.timed", "Restarting in %time% ..."); + this.restart_in = getTranslation("countdown.timed", "Restarting in %time%"); this.countdown_now = getTranslation("countdown.now", "Restarting now"); try { @@ -51,11 +51,14 @@ public PaperLangCacheImpl(String locale) throws Exception { } } + public @NotNull Component restart_delayed_playercount(final Duration delayTime) { + return this.restart_delayed_playercount.replaceText(TextReplacementConfig.builder() + .match("%time%").replacement(CommonUtil.formatDuration(delayTime)).build()); + } + public @NotNull Component time_until_restart(final Duration remainingTime) { return this.restart_in.replaceText(TextReplacementConfig.builder() - .match("%time%") - .replacement(CommonUtil.formatDuration(remainingTime)) - .build()); + .match("%time%").replacement(CommonUtil.formatDuration(remainingTime)).build()); } @Override diff --git a/paper/src/main/java/me/xginko/serverrestarts/modules/FireWatch.java b/paper/src/main/java/me/xginko/serverrestarts/modules/FireWatch.java index 5ef90f3..46e7f32 100644 --- a/paper/src/main/java/me/xginko/serverrestarts/modules/FireWatch.java +++ b/paper/src/main/java/me/xginko/serverrestarts/modules/FireWatch.java @@ -9,6 +9,8 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.Server; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,9 +18,11 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -public class FireWatch implements ServerRestartModule, Runnable { +public class FireWatch implements ServerRestartModule { - private @Nullable ScheduledTask HEARTBEAT; + private final @NotNull ServerRestartsPaper plugin; + private final @NotNull Server server; + private @Nullable ScheduledTask heartbeat; private final @NotNull CachedTickReport tickReports; private final @NotNull AtomicLong millis_spent_lagging; private final long max_millis_lagging, initial_delay_millis, interval_millis; @@ -27,8 +31,10 @@ public class FireWatch implements ServerRestartModule, Runnable { public FireWatch() { shouldEnable(); + this.plugin = ServerRestartsPaper.getInstance(); this.tickReports = ServerRestartsPaper.getTickReports(); - this.millis_spent_lagging = new AtomicLong(); + this.server = plugin.getServer(); + this.millis_spent_lagging = new AtomicLong(0L); PaperConfigImpl config = ServerRestartsPaper.getConfiguration(); config.master().addComment("fire-watch.enable", "Reboot the server when lagging for a configurable amount of time."); @@ -39,23 +45,79 @@ public FireWatch() { "The TPS (ticks per seconds) at which to start taking measures.")); this.restart_mspt = Math.abs(config.getDouble("fire-watch.restart-MSPT", 100.0, "The MSPT (milliseconds per tick) at which to start taking measures.")); - this.max_millis_lagging = TimeUnit.SECONDS.toMillis(Math.max(1, config.getInt("fire-watch.min-lag-duration", 10, + this.max_millis_lagging = TimeUnit.SECONDS.toMillis(Math.max(1, config.getInt("fire-watch.min-lag-duration-seconds", 30, "How long in seconds the server needs to be lower than the configured tps to restart."))); - this.initial_delay_millis = TimeUnit.SECONDS.toMillis(Math.max(1, config.getInt("fire-watch.check-timer.initial-delay-seconds", 30))); - this.interval_millis = TimeUnit.SECONDS.toMillis(Math.max(1, config.getInt("fire-watch.check-timer.interval-seconds", 3))); + this.initial_delay_millis = TimeUnit.SECONDS.toMillis(Math.max(1, config.getInt("fire-watch.check-timer.initial-delay-seconds", 30, + "Time until firewatch check task will start after a fresh restart."))); + this.interval_millis = TimeUnit.SECONDS.toMillis(Math.max(1, config.getInt("fire-watch.check-timer.interval-seconds", 3, + "Lag check interval in seconds."))); } @Override public boolean shouldEnable() { - return ServerRestartsPaper.getConfiguration().getBoolean("fire-watch.enable", true); + return ServerRestartsPaper.getConfiguration().getBoolean("fire-watch.enable", false); } @Override public void enable() { - ServerRestartsPaper plugin = ServerRestartsPaper.getInstance(); - this.HEARTBEAT = plugin.getServer().getAsyncScheduler().runAtFixedRate( + this.heartbeat = server.getAsyncScheduler().runAtFixedRate( plugin, - BEAT_TASK -> this.run(), + task -> { + if (ServerRestartsPaper.isRestarting) { + disable(); + return; + } + + final double tps = tickReports.getTPS(); + final double mspt = tickReports.getMSPT(); + + if (tps > restart_tps && mspt < restart_mspt) { + millis_spent_lagging.set(0L); // No lag, reset time + return; + } + + final long millis_lagging = millis_spent_lagging.addAndGet(interval_millis); + + for (Player player : server.getOnlinePlayers()) { + switch (ServerRestartsPaper.getConfiguration().message_mode) { + case ACTIONBAR -> player.sendActionBar(ServerRestartsPaper.getLang(player.locale()) + .time_until_restart(Duration.ofMillis(max_millis_lagging - millis_lagging))); + case BROADCAST -> player.sendMessage(ServerRestartsPaper.getLang(player.locale()) + .time_until_restart(Duration.ofMillis(max_millis_lagging - millis_lagging))); + } + } + + if (millis_lagging <= max_millis_lagging) { + return; // Not lagging for long enough yet + } + + RestartEvent restartEvent = new RestartEvent( + true, + RestartEvent.RestartType.ON_FIRE, + ServerRestartsPaper.getConfiguration().restart_method, + do_safe_restart, + do_safe_restart + ); + + if (!restartEvent.callEvent()) { + return; + } + + ServerRestartsPaper.joiningAllowed = false; + + ServerRestartsPaper.getLog().error(Component.text("Restarting server because on fire! -> " + + "Lag Duration: " + CommonUtil.formatDuration(Duration.ofMillis(millis_spent_lagging.get())) + " · " + + "TPS: " + String.format("%.2f", tps) + " · " + + "MSPT: " + String.format("%.2f", mspt)) + .color(TextColor.color(255, 81, 112)).decorate(TextDecoration.BOLD)); + + ServerRestartsPaper.restart( + restartEvent.getType(), + restartEvent.getMethod(), + restartEvent.getDisableJoin(), + restartEvent.getKickAll() + ); + }, initial_delay_millis, interval_millis, TimeUnit.MILLISECONDS @@ -64,53 +126,6 @@ public void enable() { @Override public void disable() { - if (this.HEARTBEAT != null) this.HEARTBEAT.cancel(); - } - - @Override - public void run() { - if (ServerRestartsPaper.isRestarting) { - disable(); - return; - } - - final double tps = tickReports.getTPS(); - final double mspt = tickReports.getMSPT(); - - if (tps > restart_tps && mspt < restart_mspt) { - millis_spent_lagging.set(0L); // No lag, reset time - return; - } - - if (millis_spent_lagging.addAndGet(interval_millis) <= max_millis_lagging) { - return; // Not lagging for long enough yet - } - - RestartEvent restartEvent = new RestartEvent( - true, - RestartEvent.RestartType.ON_FIRE, - ServerRestartsPaper.getConfiguration().restart_method, - do_safe_restart, - do_safe_restart - ); - - if (!restartEvent.callEvent()) { - return; - } - - ServerRestartsPaper.joiningAllowed = false; - - ServerRestartsPaper.getLog().error(Component.text("Restarting server because on fire! -> " + - "Lag Duration: " + CommonUtil.formatDuration(Duration.ofMillis(millis_spent_lagging.get())) + " · " + - "TPS: " + String.format("%.2f", tps) + " · " + - "MSPT: " + String.format("%.2f", mspt)) - .color(TextColor.color(255, 81, 112)).decorate(TextDecoration.BOLD)); - - ServerRestartsPaper.restart( - restartEvent.getType(), - restartEvent.getMethod(), - restartEvent.getDisableJoin(), - restartEvent.getKickAll() - ); + if (this.heartbeat != null) this.heartbeat.cancel(); } } diff --git a/paper/src/main/java/me/xginko/serverrestarts/modules/PlayerCountDelay.java b/paper/src/main/java/me/xginko/serverrestarts/modules/PlayerCountDelay.java index c61ffdc..142a181 100644 --- a/paper/src/main/java/me/xginko/serverrestarts/modules/PlayerCountDelay.java +++ b/paper/src/main/java/me/xginko/serverrestarts/modules/PlayerCountDelay.java @@ -7,6 +7,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Server; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; @@ -19,7 +20,7 @@ public class PlayerCountDelay implements ServerRestartModule, Listener { private final Server server; private final long delay_ticks; private final int min_players_for_delay; - private final boolean should_log; + private final boolean should_log, notify_players; public PlayerCountDelay() { shouldEnable(); @@ -28,6 +29,7 @@ public PlayerCountDelay() { config.master().addComment("player-count-delay.enable", "If enabled, will only restart once playercount is below the configured number."); this.should_log = config.getBoolean("player-count-delay.log", true); + this.notify_players = config.getBoolean("player-count-delay.notify-players", false); this.min_players_for_delay = Math.max(1, config.getInt("player-count-delay.min-players-for-delay", 20, "If the player count is this value or bigger, restart logic will be delayed.")); this.delay_ticks = Math.max(1, config.getInt("player-count-delay.delay-seconds", 300, @@ -58,8 +60,21 @@ private void onPreRestart(PreRestartEvent event) { if (server.getOnlinePlayers().size() >= min_players_for_delay) { event.setDelayTicks(delay_ticks); + final Duration delayDuration = Duration.ofMillis(delay_ticks * 50L); + + if (notify_players) { + for (Player player : server.getOnlinePlayers()) { + switch (ServerRestartsPaper.getConfiguration().message_mode) { + case ACTIONBAR -> player.sendActionBar(ServerRestartsPaper.getLang(player.locale()) + .restart_delayed_playercount(delayDuration)); + case BROADCAST -> player.sendMessage(ServerRestartsPaper.getLang(player.locale()) + .time_until_restart(delayDuration)); + } + } + } + if (should_log) ServerRestartsPaper.getLog().info(Component.text("Server restart has been delayed by " + - CommonUtil.formatDuration(Duration.ofMillis(delay_ticks * 50L)) + " due to high player count.").color(NamedTextColor.GOLD)); + CommonUtil.formatDuration(delayDuration) + " due to high player count.").color(NamedTextColor.GOLD)); } } }