fix(velocity): 休眠服 MOTD 按唤醒策略说明谁能唤醒,闲置回收期间加入给出回收提示

This commit is contained in:
Lemon-miaow committed 2026-09-27 15:02:16 +08:00
1 parent 249d675bd7
commit 1e42e9a87b
10 files changed
+76 -7

No files matched your search

@@ -84,7 +84,7 @@ public final class FelisApiClient {
* joining player (spec §9.1, §14). The reply (202) carries the current phase
* and ready flag so the caller can decide whether to wait. A 403 (policy gate),
* 409 {@code maintenance_in_progress} (a restore, backup or file write holds the
* world), 429 (cooldown), or 503 {@code at_capacity} (running cap) arrives as a
* world) or {@code world_reclaiming} (the idle reaper is archiving it), 429 (cooldown), or 503 {@code at_capacity} (running cap) arrives as a
* LinkException the caller branches on.
*/
public ServerView wake(String name, UUID mcUuid) throws LinkException {
@@ -74,7 +74,16 @@ public final class MotdResponder {
if ("Running".equals(v.desiredState())) {
return "启动中… / starting…";
}
return "休眠中,加入即唤醒 / sleeping — join to wake";
// The ping carries no identity either, so a sleeping server says who can wake
// it, by the same autostartPolicy gate the join runs into: ownerOnly or unset
// admits the owner alone.
if ("public".equals(v.autostartPolicy())) {
return "休眠中,加入即唤醒 / sleeping — join to wake";
}
if ("allowlist".equals(v.autostartPolicy())) {
return "休眠中,名单内玩家加入即唤醒 / sleeping — allowlisted players can wake it";
}
return "休眠中,仅服主可唤醒 / sleeping — only the owner can wake it";
}
static NamedTextColor statusColor(ServerView v) {
@@ -727,6 +727,18 @@ public final class WaitingRouter {
NamedTextColor.YELLOW));
return;
}
if ("world_reclaiming".equals(e.errorCode())) {
// The idle reaper is archiving the world. When it is done the
// server is released with an empty world, so there is nothing
// to wait for, and "try again shortly" would mislead.
player.sendMessage(Component.text(
zh ? "「" + serverName + "」闲置太久,世界正在归档回收,现在不能启动。"
+ "回收后它会变成可认领的空服,旧世界留在归档里。"
: "« " + serverName + " » sat idle too long and its world is being archived, so it can't start."
+ " Afterwards it becomes a claimable empty server; the old world stays in the archive.",
NamedTextColor.YELLOW));
return;
}
if ("server_retiring".equals(e.errorCode())) {
// The owner gave the server up or an admin is deleting it: it
// stays down until the reaper archives it, unless that is
@@ -156,8 +156,16 @@ public final class ServerRegistryTest {
assertEq("motd: retries spent", "启动失败,等服主处理 / failed to start — the owner has to restart it",
MotdResponder.statusLine(gaveUp));
assertEq("motd: retries spent is red", NamedTextColor.RED, MotdResponder.statusColor(gaveUp));
assertEq("motd: sleeping", "休眠中,加入即唤醒 / sleeping — join to wake",
// A sleeping server says who can wake it: a stranger reading "join to wake" on
// an ownerOnly server joined only to be refused.
assertEq("motd: sleeping, ownerOnly", "休眠中,仅服主可唤醒 / sleeping — only the owner can wake it",
MotdResponder.statusLine(down("a", "a")));
assertEq("motd: sleeping, public", "休眠中,加入即唤醒 / sleeping — join to wake",
MotdResponder.statusLine(sleeping("public")));
assertEq("motd: sleeping, allowlist", "休眠中,名单内玩家加入即唤醒 / sleeping — allowlisted players can wake it",
MotdResponder.statusLine(sleeping("allowlist")));
assertEq("motd: sleeping, no policy", "休眠中,仅服主可唤醒 / sleeping — only the owner can wake it",
MotdResponder.statusLine(sleeping(null)));
System.out.println("ServerRegistryTest OK (" + checks + " checks)");
}
@@ -170,6 +178,10 @@ public final class ServerRegistryTest {
return new ServerView(name, sub, "Stopped", false, "ownerOnly", "Stopped", "fallback", "login", 0, 0);
}
private static ServerView sleeping(String policy) {
return new ServerView("a", "a", "Stopped", false, policy, "Stopped", "fallback", "login", 0, 0);
}
private static ServerView unstarted(String name, String sub) {
return new ServerView(name, sub, "", false, "ownerOnly", "Stopped", null, null, 0, 0);
}
@@ -234,6 +234,7 @@ public final class WaitingRouterTest {
{"retries spent", "« gamma » failed to start and its automatic retries are spent", null},
{"409 maintenance_in_progress", "« gamma » is under maintenance", null},
{"409 server_retiring", "« gamma » has been given up or is being deleted", null},
{"409 world_reclaiming", "« gamma » sat idle too long and its world is being archived", null},
{"409 conflict", "Couldn't start « gamma » right now", "wake gamma failed (status=409)"},
{"503 at_capacity", "The cluster is at capacity right now", null},
{"503 unavailable", "Couldn't start « gamma » right now", "wake gamma failed (status=503)"},
@@ -259,6 +260,8 @@ public final class WaitingRouterTest {
assertEq(c[0] + ": no promise of a start", false, p.said("Starting « gamma »"));
if (c[2] != null) {
assertEq(c[0] + ": logged", warned + 1, log.count("WARN", c[2]));
} else {
assertEq(c[0] + ": no generic failure on top", false, p.said("Couldn't start « gamma » right now"));
}
api.policy.remove("gamma");
api.phase.remove("gamma");