Improve action bar loading bar for server start

This commit is contained in:
2026-10-19 09:59:02 +02:00
parent 21d0a4359d
commit 37f017b84c
@@ -22,6 +22,7 @@ package de.steamwar.persistent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerInfo;
import com.velocitypowered.api.scheduler.ScheduledTask;
import lombok.Getter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
@@ -32,7 +33,10 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.logging.Level;
@@ -98,7 +102,13 @@ public class Subserver {
@Getter
private boolean started;
private final List<Player> cachedPlayers = new LinkedList<>();
private static final int MAX_PROGRESS = 10;
private static final Pattern PLUGIN_COUNT = Pattern.compile("Bukkit plugins \\((\\d+)\\)");
private final List<Player> cachedPlayers = new CopyOnWriteArrayList<>();
private volatile int progress = 0;
private int pluginCount = 0;
private int enabledPlugins = 0;
@Getter
private final Map<Player, String> tablistNames = new HashMap<>();
@@ -127,7 +137,7 @@ public class Subserver {
public void sendPlayer(Player p) {
if (!started) {
p.sendActionBar(generateBar(0));
p.sendActionBar(generateBar(progress));
cachedPlayers.add(p);
} else {
p.createConnectionRequest(registeredServer).connect();
@@ -246,31 +256,32 @@ public class Subserver {
private void run() {
Exception ex = null;
try {
if (checkpoint) {
start(process.getErrorStream(), line -> line.contains("Restore finished successfully."));
start(process.getInputStream(), line -> line.contains("Checkpoint restored"));
Thread.sleep(100);
} else {
sendProgress(0);
start(process.getInputStream(), line -> {
if (line.contains("Loading libraries, please wait")) {
sendProgress(2);
} else if (line.contains("Starting Minecraft server on")) {
sendProgress(5);
} else if (line.contains("Preparing start region")) {
sendProgress(8);
}
return line.contains("Done (");
});
}
ScheduledTask refresh = Persistent.getInstance().getProxy().getScheduler()
.buildTask(Persistent.getInstance(), () -> sendProgress(progress))
.repeat(2, TimeUnit.SECONDS).schedule();
if (!started) return;
try {
if (checkpoint) {
start(process.getErrorStream(), line -> line.contains("Restore finished successfully."));
start(process.getInputStream(), line -> line.contains("Checkpoint restored"));
Thread.sleep(100);
} else {
start(process.getInputStream(), line -> {
updateProgress(line);
return line.contains("Done (");
});
}
sendProgress(10);
for (Player cachedPlayer : cachedPlayers) {
sendPlayer(cachedPlayer);
if (!started) return;
setProgress(MAX_PROGRESS);
for (Player cachedPlayer : cachedPlayers) {
sendPlayer(cachedPlayer);
}
cachedPlayers.clear();
} finally {
refresh.cancel();
}
cachedPlayers.clear();
process.waitFor();
} catch (IOException e) {
@@ -285,6 +296,39 @@ public class Subserver {
}
}
private void updateProgress(String line) {
if (line.startsWith("Loading Paper")) {
setProgress(1);
} else if (line.startsWith("Bukkit plugins (")) {
Matcher matcher = PLUGIN_COUNT.matcher(line);
if (matcher.find()) pluginCount = Integer.parseInt(matcher.group(1));
} else if (line.startsWith("Starting minecraft server version")) {
setProgress(2);
} else if (line.contains("Starting Minecraft server on")) {
setProgress(3);
} else if (line.contains("libraries... please wait")) {
setProgress(4);
} else if (line.startsWith("Loading server plugin")) {
setProgress(5);
} else if (line.startsWith("Preparing level")) {
setProgress(6);
} else if (line.startsWith("Preparing start region")) {
setProgress(7);
} else if (line.startsWith("Enabling ")) {
enabledPlugins++;
// 7 -> 9 over all plugins, 9 is reached with the last plugin
setProgress(7 + (pluginCount > 0 ? Math.min(2, 2 * enabledPlugins / pluginCount) : 0));
} else if (line.startsWith("Done preparing level")) {
setProgress(9);
}
}
private void setProgress(int newProgress) {
if (newProgress <= progress) return;
progress = newProgress;
sendProgress(newProgress);
}
private Component generateBar(int progress) {
return Component.text("⬛".repeat(Math.max(0, progress))).color(NamedTextColor.YELLOW)
.append(Component.text("⬛".repeat(Math.max(0, 10 - progress))).color(NamedTextColor.DARK_GRAY));