From 5e84227b54de2f2478a3de754df471f0aec6ff3b Mon Sep 17 00:00:00 2001 From: FloPinguin <25036848+FloPinguin@users.noreply.github.com> Date: Wed, 11 Mar 2026 22:36:32 +0100 Subject: [PATCH] =?UTF-8?q?Fix:=20Lobby=20websocket=20reconnects=20after?= =?UTF-8?q?=20`stop()`=20in=20singleplayer=20=F0=9F=94=A7=20(#3407)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description: Calling `lobbySocket.stop()` closes the WebSocket, but the async `close` event fires afterward and triggers `handleClose()` → `scheduleReconnect()`, reopening the connection. In singleplayer, both `onPrestart` and `onJoin` callbacks fire synchronously in a single stack, so the second `stop()` call has nothing left to clean up - the reconnect timeout gets set after both calls complete. Adds a `stopped` flag that skips reconnection in `handleClose()` when the socket was intentionally closed. Surely this PR description is not AI generated. Should reduce network load of the server because all the singleplayer gamers no longer stay connected to the lobbies websocket forever. They also no longer load all the map mainfest.jsons and thumbnails while they are playing alone (rotation running in the background). - [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 --- src/client/LobbySocket.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/client/LobbySocket.ts b/src/client/LobbySocket.ts index 7b71dc21a..4e4922508 100644 --- a/src/client/LobbySocket.ts +++ b/src/client/LobbySocket.ts @@ -18,6 +18,7 @@ export class PublicLobbySocket { private wsConnectionAttempts = 0; private wsAttemptCounted = false; private workerPath: string = ""; + private stopped = true; private readonly reconnectDelay: number; private readonly maxWsAttempts: number; @@ -31,6 +32,7 @@ export class PublicLobbySocket { } async start() { + this.stopped = false; this.wsConnectionAttempts = 0; // Get config to determine number of workers, then pick a random one const config = await getServerConfigFromClient(); @@ -39,6 +41,7 @@ export class PublicLobbySocket { } stop() { + this.stopped = true; this.disconnectWebSocket(); } @@ -96,6 +99,7 @@ export class PublicLobbySocket { } private handleClose() { + if (this.stopped) return; console.log("WebSocket disconnected, attempting to reconnect..."); if (!this.wsAttemptCounted) { this.wsAttemptCounted = true;