fix(menu): 大厅菜单按玩家标出每台服能否启动及原因,自己的服排前面,状态改成中文
This commit is contained in:
21 files changed
+1081
-136
No files matched your search
@@ -34,6 +34,7 @@ public final class ControlRoundTripTest {
|
||||
errorOmitsServerWhenAbsentButRoundTrips();
|
||||
escapesAwkwardStrings();
|
||||
listUpdateCarriesNamesInOrder();
|
||||
listUpdateCarriesAccessByName();
|
||||
rejectsMalformedAndUnknownFrames();
|
||||
System.out.println("ControlRoundTripTest OK (" + checks + " checks)");
|
||||
}
|
||||
@@ -52,6 +53,7 @@ public final class ControlRoundTripTest {
|
||||
roundTrip(ControlFrame.listRequest());
|
||||
roundTrip(ControlFrame.listUpdate(Arrays.asList("alpha", "beta-2", "gamma")));
|
||||
roundTrip(ControlFrame.listUpdate(List.of()));
|
||||
roundTrip(ControlFrame.listUpdate(List.of("mine", "theirs"), List.of("owner", "owner_only")));
|
||||
roundTrip(ControlFrame.loginRelease("Notch"));
|
||||
}
|
||||
|
||||
@@ -81,6 +83,34 @@ public final class ControlRoundTripTest {
|
||||
assertEq("non-string entries skipped", List.of("a", "b"), mixed.servers());
|
||||
}
|
||||
|
||||
// ListUpdate's access list is the player's verdict per name, by index: it holds
|
||||
// its alignment through a dropped name on either end, a missing or non-string
|
||||
// verdict reads as unknown (""), and a list with no verdict at all is the plain
|
||||
// name list on the wire.
|
||||
private static void listUpdateCarriesAccessByName() {
|
||||
ControlFrame f = decode(ControlFrame.listUpdate(
|
||||
Arrays.asList("mine", null, "theirs", "fresh"),
|
||||
Arrays.asList("owner", "wake", "owner_only")));
|
||||
assertEq("names", List.of("mine", "theirs", "fresh"), f.servers());
|
||||
assertEq("verdicts follow their names", List.of("owner", "owner_only", ""), f.access());
|
||||
assertEq("names only: no verdicts", List.of(), decode(ControlFrame.listUpdate(List.of("a"))).access());
|
||||
assertEq("all unknown: no verdicts", List.of(),
|
||||
decode(ControlFrame.listUpdate(List.of("a", "b"), Arrays.asList("", null))).access());
|
||||
assertEq("names only: nothing extra on the wire",
|
||||
"{\"type\":\"ListUpdate\",\"servers\":[\"a\"]}",
|
||||
new String(Control.encode(ControlFrame.listUpdate(List.of("a"), List.of(""))), StandardCharsets.UTF_8));
|
||||
assertEq("extra verdicts are cut", List.of("wake"),
|
||||
ControlFrame.listUpdate(List.of("a"), List.of("wake", "owner")).access());
|
||||
ControlFrame mixed = Control.decode(("{\"type\":\"ListUpdate\",\"servers\":[\"a\",1,\"b\",\"c\"],"
|
||||
+ "\"access\":[\"owner\",\"wake\",7,\"allowlist\"]}").getBytes(StandardCharsets.UTF_8));
|
||||
assertEq("hand-written: names", List.of("a", "b", "c"), mixed.servers());
|
||||
assertEq("hand-written: a skipped name takes its verdict", List.of("owner", "", "allowlist"), mixed.access());
|
||||
ControlFrame shortList = Control.decode(("{\"type\":\"ListUpdate\",\"servers\":[\"a\",\"b\"],"
|
||||
+ "\"access\":[\"retiring\"]}").getBytes(StandardCharsets.UTF_8));
|
||||
assertEq("hand-written: a missing verdict is unknown", List.of("retiring", ""), shortList.access());
|
||||
assertEq("access on a non-list frame", List.of(), decode(ControlFrame.statusQuery("s")).access());
|
||||
}
|
||||
|
||||
// StatusUpdate refines the spec's "players" into ready + online + max; the GUI
|
||||
// renders all three, so all three must survive the round-trip with exact values.
|
||||
private static void wireCarriesRefinedStatusFields() {
|
||||
|
||||
@@ -44,6 +44,9 @@ public final class FelisApiClientTest {
|
||||
if (path.endsWith("/wake")) {
|
||||
status = 202;
|
||||
body = "{\"name\":\"alpha\",\"phase\":\"Starting\",\"ready\":false}";
|
||||
} else if (path.startsWith("/api/v1/internal/player/menu-access/")) {
|
||||
status = 200;
|
||||
body = "{\"servers\":{\"mine\":\"owner\",\"odd\":7,\"pub\":\"wake\"}}";
|
||||
} else if (path.equals("/api/v1/internal/op-login/mismatch/approve")) {
|
||||
status = 409;
|
||||
body = "{\"error\":{\"code\":\"op_login_mismatch\",\"message\":\"that operator login is for a different account\"}}";
|
||||
@@ -78,6 +81,7 @@ public final class FelisApiClientTest {
|
||||
opaqueSegmentsArePercentEncoded(api);
|
||||
opLoginShowNamesTheAccount(api);
|
||||
opLoginApproveSendsTheTypedName(api);
|
||||
menuAccessReadsVerdictsByName(api);
|
||||
} finally {
|
||||
stub.stop(0);
|
||||
}
|
||||
@@ -96,6 +100,15 @@ public final class FelisApiClientTest {
|
||||
"GET /api/v1/internal/servers/abc/status"), seen);
|
||||
}
|
||||
|
||||
// menuAccess reads the verdict map for the player's own UUID and keeps only the
|
||||
// string verdicts, so one malformed entry cannot hide the others.
|
||||
private static void menuAccessReadsVerdictsByName(FelisApiClient api) throws LinkException {
|
||||
seen.clear();
|
||||
UUID id = UUID.fromString("00000000-0000-0000-0000-00000000000a");
|
||||
assertEq("verdicts", java.util.Map.of("mine", "owner", "pub", "wake"), api.menuAccess(id));
|
||||
assertEq("route", List.of("GET /api/v1/internal/player/menu-access/" + id), seen);
|
||||
}
|
||||
|
||||
private static void pathBendingNamesNeverLeaveTheClient(FelisApiClient api) {
|
||||
UUID id = UUID.fromString("00000000-0000-0000-0000-000000000002");
|
||||
String[] bad = {
|
||||
|
||||
Reference in new issue
Block a user