fix(velocity): 新增 /felis lobby,/felis go lobby 也能回大厅
This commit is contained in:
4 files changed
+95
No files matched your search
@@ -439,6 +439,11 @@ public final class FelisVelocityPlugin {
|
||||
sendServerList(ctx.getSource());
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}))
|
||||
.then(BrigadierCommand.literalArgumentBuilder("lobby")
|
||||
.executes(ctx -> {
|
||||
doLobby(ctx.getSource());
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}))
|
||||
.then(BrigadierCommand.literalArgumentBuilder("go")
|
||||
.then(BrigadierCommand.requiredArgumentBuilder("server", StringArgumentType.word())
|
||||
.executes(ctx -> {
|
||||
@@ -569,6 +574,8 @@ public final class FelisVelocityPlugin {
|
||||
zh ? "此代理已知的 felis 服务器" : "the felis servers this proxy knows");
|
||||
helpLine(source, "/felis go <server>",
|
||||
zh ? "启动服务器并在就绪后把你传送过去" : "start a server and move you in when it's ready");
|
||||
helpLine(source, "/felis lobby",
|
||||
zh ? "回到大厅" : "back to the lobby");
|
||||
helpLine(source, "/felis claim",
|
||||
zh ? "认领你所在的服务器" : "take ownership of the server you're on");
|
||||
helpLine(source, "/felis migrate",
|
||||
@@ -626,6 +633,11 @@ public final class FelisVelocityPlugin {
|
||||
return false;
|
||||
}
|
||||
String target = serverArg.trim();
|
||||
if (target.equalsIgnoreCase(config.lobbyServer())) {
|
||||
// The lobby is a system server, so the loop below would call it unknown.
|
||||
router.toLobby(player);
|
||||
return true;
|
||||
}
|
||||
ServerView match = null;
|
||||
for (ServerView v : registry.all()) {
|
||||
if (!isSystemServer(v.name()) && v.name().equalsIgnoreCase(target)) {
|
||||
@@ -659,6 +671,18 @@ public final class FelisVelocityPlugin {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void doLobby(CommandSource source) {
|
||||
Player player = requirePlayer(source);
|
||||
if (player == null || !ensureOutOfLimbo(player)) {
|
||||
return;
|
||||
}
|
||||
if (!routingActive) {
|
||||
player.sendMessage(routingDisabled(zh(player)));
|
||||
return;
|
||||
}
|
||||
router.toLobby(player);
|
||||
}
|
||||
|
||||
private void doClaim(CommandSource source) {
|
||||
Player player = requirePlayer(source);
|
||||
if (player == null || !ensureOutOfLimbo(player)) {
|
||||
|
||||
@@ -225,6 +225,33 @@ public final class WaitingRouter {
|
||||
authorizeAndWait(player, serverName, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* toLobby moves a player who is already past the login gate back to the lobby, for
|
||||
* {@code /felis lobby} and {@code /felis go <lobby>}. The lobby is always up, so there
|
||||
* is nothing to wake and no queue to join; a failed connect is reported like any other
|
||||
* transfer. A wait the player joined earlier stays: the lobby is where the queue parks
|
||||
* players anyway, and it still moves them when their server is ready.
|
||||
*/
|
||||
void toLobby(Player player) {
|
||||
boolean zh = FelisVelocityPlugin.zh(player);
|
||||
if (player.getCurrentServer()
|
||||
.map(sc -> serverNamed(sc.getServer(), lobbyServer))
|
||||
.orElse(false)) {
|
||||
player.sendMessage(Component.text(
|
||||
zh ? "你已经在大厅了。" : "You're already in the lobby.", NamedTextColor.YELLOW));
|
||||
return;
|
||||
}
|
||||
Optional<RegisteredServer> lobby = proxy.getServer(lobbyServer);
|
||||
if (lobby.isEmpty()) {
|
||||
log.warn("Felis: {} asked for the lobby but '{}' is not registered", player.getUniqueId(), lobbyServer);
|
||||
player.sendMessage(Component.text(
|
||||
zh ? "大厅暂时不可用,请稍后再试。" : "The lobby is unavailable right now. Try again shortly.",
|
||||
NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
transfer(player, lobbyServer, lobby.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* enqueueFromInvite is {@link #enqueueFromCommand} for an accepted invite. An invite can
|
||||
* only name the server its sender is standing on, so the target is running by
|
||||
|
||||
@@ -75,6 +75,7 @@ public final class WaitingRouterTest {
|
||||
longStart();
|
||||
menuAndCommands();
|
||||
joins();
|
||||
backToLobby();
|
||||
disconnectAndRelease();
|
||||
} finally {
|
||||
api.close();
|
||||
@@ -605,6 +606,43 @@ public final class WaitingRouterTest {
|
||||
assertEq("refused transfer: no retry advice", false, full.said("try again"));
|
||||
}
|
||||
|
||||
// /felis lobby and /felis go lobby: the lobby is a system server, so it never
|
||||
// appeared among the servers /felis go knows.
|
||||
private static void backToLobby() {
|
||||
Fakes.FakePlayer back = player(null, true);
|
||||
back.current = beta;
|
||||
router.toLobby(back.player);
|
||||
assertEq("from a server: moved to the lobby", List.of("lobby"), List.copyOf(back.connects));
|
||||
assertEq("from a server: nothing asked of felis-api", 0, api.count(LINK + back.id));
|
||||
|
||||
Fakes.FakePlayer there = player(null, true);
|
||||
there.current = lobby;
|
||||
router.toLobby(there.player);
|
||||
assertEq("in the lobby: told", true, there.said("You're already in the lobby."));
|
||||
assertEq("in the lobby: no move", 0, there.connects.size());
|
||||
|
||||
Fakes.FakePlayer between = player(null, true);
|
||||
router.toLobby(between.player);
|
||||
assertEq("on no server yet: moved to the lobby", List.of("lobby"), List.copyOf(between.connects));
|
||||
|
||||
// A wait survives the trip: the queue parks players in the lobby anyway.
|
||||
Fakes.FakePlayer waiter = player(null, true);
|
||||
waiter.current = beta;
|
||||
int before = router.waitingCount();
|
||||
router.enqueueFromCommand(waiter.player, "zeta");
|
||||
Fakes.await("waiter queued", () -> router.waitingCount() == before + 1);
|
||||
router.toLobby(waiter.player);
|
||||
assertEq("waiting: moved to the lobby", List.of("lobby"), List.copyOf(waiter.connects));
|
||||
assertEq("waiting: still queued", before + 1, router.waitingCount());
|
||||
router.onDisconnect(new DisconnectEvent(waiter.player, DisconnectEvent.LoginStatus.SUCCESSFUL_LOGIN));
|
||||
|
||||
Fakes.FakePlayer full = player(null, true);
|
||||
full.current = beta;
|
||||
full.refusals.put("lobby", "Server is full");
|
||||
router.toLobby(full.player);
|
||||
Fakes.await("lobby refused: told", () -> full.said("Couldn't connect you to « lobby ». Reason: Server is full"));
|
||||
}
|
||||
|
||||
private static void disconnectAndRelease() {
|
||||
// Leaving the proxy drops the queue entry.
|
||||
Fakes.FakePlayer leaver = player(null, true);
|
||||
@@ -648,6 +686,11 @@ public final class WaitingRouterTest {
|
||||
router.releaseFromLogin(early.player);
|
||||
assertEq("no lobby yet: nothing sent", 0, early.connects.size());
|
||||
assertEq("no lobby yet: logged", 1, log.count("WARN", "login release for " + early.id + " but the lobby"));
|
||||
Fakes.FakePlayer asker = player(null, true);
|
||||
asker.current = beta;
|
||||
router.toLobby(asker.player);
|
||||
assertEq("no lobby: told", true, asker.said("The lobby is unavailable right now."));
|
||||
assertEq("no lobby: no move", 0, asker.connects.size());
|
||||
|
||||
// With no login gate registered a host-routed player is turned away.
|
||||
net.remove("login");
|
||||
|
||||
Reference in new issue
Block a user