Skip to content

Commit

Permalink
improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
xGinko committed Feb 29, 2024
1 parent 8a2e5ef commit cc6a78c
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 73 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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."
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -192,7 +192,7 @@ private Set<String> 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();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public PaperLangCacheImpl(String locale) throws Exception {
this.restart_delayed_playercount = getTranslation("messages.restart-delayed-high-playercount",
"<gray>Delaying restart for %time% due to high playercount.");

this.restart_in = getTranslation("countdown.timed", "<gold>Restarting in %time% ...");
this.restart_in = getTranslation("countdown.timed", "<gold>Restarting in %time%");
this.countdown_now = getTranslation("countdown.now", "<bold><red>Restarting now");

try {
Expand All @@ -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
Expand Down
131 changes: 73 additions & 58 deletions paper/src/main/java/me/xginko/serverrestarts/modules/FireWatch.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@
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;

import java.time.Duration;
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;
Expand All @@ -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.");
Expand All @@ -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
Expand All @@ -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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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,
Expand Down Expand Up @@ -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));
}
}
}

0 comments on commit cc6a78c

Please sign in to comment.