mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 11:40:42 +00:00
Close private lobby when host leaves 🚪 (#3503)
## Description: When the host of a private lobby disconnects before the game starts, the lobby is now closed: - **Server:** Detects host disconnection via `creatorPersistentID` match, kicks all remaining clients with a `host_left` reason, and marks the game as ended so it's cleaned up by the game manager and can no longer be joined. - **Client:** Participants receive an `alert()` saying "The host has left the lobby." and their JoinLobbyModal is closed automatically via the `leave-lobby` event. - **Phase logic:** `phase()` now returns `Finished` for ended private lobbies that haven't started, preventing the game from lingering in `Lobby` state. ## Please complete the following: - [X] I have added screenshots for all UI updates - [X] I process any text displayed to the user through translateText() and I've added it to the en.json file - [X] I have added relevant tests to the test directory - [X] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: FloPinguin
This commit is contained in:
@@ -863,7 +863,8 @@
|
||||
},
|
||||
"kick_reason": {
|
||||
"duplicate_session": "Kicked from game (you may have been playing on another tab)",
|
||||
"lobby_creator": "Kicked by lobby creator"
|
||||
"lobby_creator": "Kicked by lobby creator",
|
||||
"host_left": "The host has left the lobby."
|
||||
},
|
||||
"send_troops_modal": {
|
||||
"title_with_name": "Send Troops to {name}",
|
||||
|
||||
@@ -172,6 +172,15 @@ export function joinLobby(
|
||||
composed: true,
|
||||
}),
|
||||
);
|
||||
} else if (message.error === "kick_reason.host_left") {
|
||||
alert(translateText("kick_reason.host_left"));
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("leave-lobby", {
|
||||
detail: { lobby: lobbyConfig.gameID, cause: "host-left" },
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
showErrorModal(
|
||||
message.error,
|
||||
|
||||
@@ -35,6 +35,7 @@ export enum GamePhase {
|
||||
|
||||
const KICK_REASON_DUPLICATE_SESSION = "kick_reason.duplicate_session";
|
||||
const KICK_REASON_LOBBY_CREATOR = "kick_reason.lobby_creator";
|
||||
const KICK_REASON_HOST_LEFT = "kick_reason.host_left";
|
||||
const KICK_REASON_TOO_MUCH_DATA = "kick_reason.too_much_data";
|
||||
const KICK_REASON_INVALID_MESSAGE = "kick_reason.invalid_message";
|
||||
|
||||
@@ -542,6 +543,20 @@ export class GameServer {
|
||||
this.activeClients = this.activeClients.filter(
|
||||
(c) => c.clientID !== client.clientID,
|
||||
);
|
||||
// Close lobby when host leaves before game starts
|
||||
if (
|
||||
!this._hasStarted &&
|
||||
!this.isPublic() &&
|
||||
client.persistentID === this.creatorPersistentID
|
||||
) {
|
||||
this.log.info("Host left, closing lobby", {
|
||||
gameID: this.id,
|
||||
});
|
||||
for (const c of [...this.activeClients]) {
|
||||
this.kickClient(c.clientID, KICK_REASON_HOST_LEFT);
|
||||
}
|
||||
this._hasEnded = true;
|
||||
}
|
||||
});
|
||||
client.ws.on("error", (error: Error) => {
|
||||
if ((error as any).code === "WS_ERR_UNEXPECTED_RSV_1") {
|
||||
@@ -847,6 +862,8 @@ export class GameServer {
|
||||
} else {
|
||||
return GamePhase.Active;
|
||||
}
|
||||
} else if (this._hasEnded) {
|
||||
return GamePhase.Finished;
|
||||
} else {
|
||||
return GamePhase.Lobby;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user