From 488188ff860c4534c2e4e3abd2f8ad53afa2502e Mon Sep 17 00:00:00 2001 From: Tyler Hanavan Date: Fri, 1 Aug 2025 00:24:15 -0400 Subject: [PATCH] Fix the stale disconnected (Zzz) icon persisting when a client reconnects (#1631) Fix the stale disconnected (Zzz) icon persisting when a client reconnects ## Description: Refer to issue #1630 This change modifies the GameServer.addClient function to send the mark_disconnected = false intent when a client that was previously disconnected gets replaced by a newly joined client with the same clientID. Under the old logic, this mark_disconnected = false intent is not sent if the client was disconnected for longer than 60 seconds before reconnecting. https://github.com/user-attachments/assets/5e0ce1c3-9519-4f39-aa80-e46f1275649c Left side browser (player with red tiles) is the disconnected client that was disconnected at 00:14 game clock time. It reconnected around 03:56 game clock time. Right side browser (player with green tiles) is the other client. Use the game clock time from the right side for the live game clock time. ## 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 - [x] I have read and accepted the CLA agreement (only required once). ## Please put your Discord username so you can be contacted if a bug or regression is found: slyty --------- Co-authored-by: Drills Kibo <59177241+drillskibo@users.noreply.github.com> --- src/server/Client.ts | 1 - src/server/GameServer.ts | 26 +++++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/server/Client.ts b/src/server/Client.ts index cdd788764..68f0a2bfb 100644 --- a/src/server/Client.ts +++ b/src/server/Client.ts @@ -5,7 +5,6 @@ import { ClientID } from "../core/Schemas"; export class Client { public lastPing: number = Date.now(); - public isDisconnected: boolean = false; public hashes: Map = new Map(); diff --git a/src/server/GameServer.ts b/src/server/GameServer.ts index 89900ac84..300d8c063 100644 --- a/src/server/GameServer.ts +++ b/src/server/GameServer.ts @@ -43,6 +43,7 @@ export class GameServer { public activeClients: Client[] = []; // Used for record record keeping private allClients: Map = new Map(); + private clientsDisconnectedStatus: Map = new Map(); private _hasStarted = false; private _startTime: number | null = null; @@ -174,7 +175,6 @@ export class GameServer { return; } - client.isDisconnected = existing.isDisconnected; client.lastPing = existing.lastPing; this.activeClients = this.activeClients.filter((c) => c !== existing); @@ -184,6 +184,8 @@ export class GameServer { this.activeClients.push(client); client.lastPing = Date.now(); + this.markClientDisconnected(client.clientID, false); + this.allClients.set(client.clientID, client); client.ws.removeAllListeners("message"); @@ -571,25 +573,27 @@ export class GameServer { const now = Date.now(); for (const [clientID, client] of this.allClients) { - if ( - client.isDisconnected === false && - now - client.lastPing > this.disconnectedTimeout - ) { - this.markClientDisconnected(client, true); + const isDisconnected = this.isClientDisconnected(clientID); + if (!isDisconnected && now - client.lastPing > this.disconnectedTimeout) { + this.markClientDisconnected(clientID, true); } else if ( - client.isDisconnected && + isDisconnected && now - client.lastPing < this.disconnectedTimeout ) { - this.markClientDisconnected(client, false); + this.markClientDisconnected(clientID, false); } } } - private markClientDisconnected(client: Client, isDisconnected: boolean) { - client.isDisconnected = isDisconnected; + public isClientDisconnected(clientID: string): boolean { + return this.clientsDisconnectedStatus.get(clientID) ?? true; + } + + private markClientDisconnected(clientID: string, isDisconnected: boolean) { + this.clientsDisconnectedStatus.set(clientID, isDisconnected); this.addIntent({ type: "mark_disconnected", - clientID: client.clientID, + clientID: clientID, isDisconnected: isDisconnected, }); }