From 77a60d5a005c8bbdf9b744e3c9821654938c7d83 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 2 Apr 2025 16:50:58 -0700 Subject: [PATCH] attempt reconnect if no messages received for 5 seconds. --- src/client/ClientGameRunner.ts | 35 +++++++++++++++++++++++++++++++--- src/client/Transport.ts | 13 ++++++++----- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts index 162d57d27..04cef96e4 100644 --- a/src/client/ClientGameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -158,8 +158,9 @@ export class ClientGameRunner { private hasJoined = false; private lastMousePosition: { x: number; y: number } | null = null; - private mouseHoverTimer: number | null = null; - private readonly HOVER_DELAY = 200; + + private lastMessageTime: number = 0; + private connectionCheckInterval: NodeJS.Timeout | null = null; constructor( private lobby: LobbyConfig, @@ -169,7 +170,9 @@ export class ClientGameRunner { private transport: Transport, private worker: WorkerClient, private gameView: GameView, - ) {} + ) { + this.lastMessageTime = Date.now(); + } private saveGame(update: WinUpdate) { const players: PlayerRecord[] = [ @@ -207,6 +210,13 @@ export class ClientGameRunner { public start() { consolex.log("starting client game"); this.isActive = true; + this.lastMessageTime = Date.now(); + setTimeout(() => { + this.connectionCheckInterval = setInterval( + () => this.onConnectionCheck(), + 1000, + ); + }, 20000); this.eventBus.on(MouseUpEvent, (e) => this.inputEvent(e)); this.eventBus.on(MouseMoveEvent, (e) => this.onMouseMove(e)); @@ -245,6 +255,7 @@ export class ClientGameRunner { this.transport.joinGame(this.turnsSeen); }; const onmessage = (message: ServerMessage) => { + this.lastMessageTime = Date.now(); if (message.type == "start") { this.hasJoined = true; consolex.log("starting game!"); @@ -296,6 +307,10 @@ export class ClientGameRunner { this.worker.cleanup(); this.isActive = false; this.transport.leaveGame(saveFullGame); + if (this.connectionCheckInterval) { + clearInterval(this.connectionCheckInterval); + this.connectionCheckInterval = null; + } } private inputEvent(event: MouseUpEvent) { @@ -391,6 +406,20 @@ export class ClientGameRunner { } } } + + private onConnectionCheck() { + if (this.transport.isLocal) { + return; + } + const timeSinceLastMessage = Date.now() - this.lastMessageTime; + if (timeSinceLastMessage > 5000) { + console.log( + `No message from server for ${timeSinceLastMessage} ms, reconnecting`, + ); + this.lastMessageTime = Date.now(); + this.transport.reconnect(); + } + } } function showErrorModal( diff --git a/src/client/Transport.ts b/src/client/Transport.ts index 5cfdf9b24..38498c9fa 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -158,8 +158,7 @@ export class Transport { private onmessage: (msg: ServerMessage) => void; private pingInterval: number | null = null; - private isLocal: boolean; - + public readonly isLocal: boolean; constructor( private lobbyConfig: LobbyConfig, private eventBus: EventBus, @@ -267,7 +266,7 @@ export class Transport { onmessage: (message: ServerMessage) => void, ) { this.startPing(); - this.maybeKillSocket(); + this.killExistingSocket(); const wsHost = window.location.host; const wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:"; const workerPath = this.lobbyConfig.serverConfig.workerPath( @@ -304,11 +303,15 @@ export class Transport { ); if (event.code != 1000) { console.log(`reconnecting`); - this.connect(onconnect, onmessage); + this.reconnect(); } }; } + public reconnect() { + this.connect(this.onconnect, this.onmessage); + } + private onSendLogEvent(event: SendLogEvent) { this.sendMsg( JSON.stringify( @@ -586,7 +589,7 @@ export class Transport { } } - private maybeKillSocket(): void { + private killExistingSocket(): void { if (this.socket == null) { return; }