diff --git a/TableturfBattleClient/src/Board.ts b/TableturfBattleClient/src/Board.ts index 87d9e24..9f12ef7 100644 --- a/TableturfBattleClient/src/Board.ts +++ b/TableturfBattleClient/src/Board.ts @@ -340,6 +340,9 @@ class Board { resize(grid?: Space[][]) { if (grid) this.grid = grid; + if (this.cells.length == this.grid.length && this.cells[0].length == this.grid[0].length) + return; // Reconnected and board size did not change. + clearChildren(this.table); this.cells.splice(0); this.highlightedCells.splice(0); @@ -422,7 +425,6 @@ class Board { } refresh() { - this.clearHighlight(); this.clearInkAnimations(); for (let x = 0; x < this.grid.length; x++) { for (let y = 0; y < this.grid[x].length; y++) { diff --git a/TableturfBattleClient/src/GameVariables.ts b/TableturfBattleClient/src/GameVariables.ts index eedda31..7248bcd 100644 --- a/TableturfBattleClient/src/GameVariables.ts +++ b/TableturfBattleClient/src/GameVariables.ts @@ -23,7 +23,8 @@ let currentGame: { /** The user's player data, or null if they are spectating. */ me: PlayerData | null, /** The WebSocket used for receiving game events, or null if not yet connected. */ - webSocket: WebSocket | null + webSocket: WebSocket | null, + reconnecting?: boolean } | null = null; let enterGameTimeout: number | null = null; diff --git a/TableturfBattleClient/src/Pages/GamePage.ts b/TableturfBattleClient/src/Pages/GamePage.ts index c765911..7628d8a 100644 --- a/TableturfBattleClient/src/Pages/GamePage.ts +++ b/TableturfBattleClient/src/Pages/GamePage.ts @@ -122,6 +122,7 @@ function initSpectator() { spectatorRow.hidden = false; flipButton.hidden = false; gameButtonsContainer.hidden = false; + board.autoHighlight = false; showPage('game'); } @@ -795,13 +796,12 @@ function populateShowDeck(deck: Deck) { /** Handles an update to the player's hand and/or deck during a game. */ function updateHandAndDeck(playerData: PlayerData) { - handButtons.clear(); - + const hand = playerData.hand!; populateShowDeck(playerData.deck!); for (const button of showDeckButtons) { const li = button.buttonElement.parentElement!; - if (playerData.hand!.find(c => c.number == button.card.number)) + if (hand.find(c => c.number == button.card.number)) li.className = 'inHand'; else if (playerData.cardsUsed.includes(button.card.number)) li.className = 'used'; @@ -810,7 +810,20 @@ function updateHandAndDeck(playerData: PlayerData) { } if (!currentGame?.me) return; - currentGame.me.hand = playerData.hand!.map(Card.fromJson); + + if (handButtons.entries.length == 4 && hand.length == 4) { + let handIsSame = true; + for (let i = 0; i < 4; i++) { + if (( handButtons.entries[i].button).card.number != hand[i].number) { + handIsSame = false; + break; + } + } + if (handIsSame) return; // The player's hand has not changed after reconnecting to the game. + } + currentGame.me.hand = hand.map(Card.fromJson); + handButtons.clear(); + board.autoHighlight = false; for (let i = 0; i < currentGame.me.hand.length; i++) { const card = currentGame.me.hand[i]; const button = new CardButton(card); diff --git a/TableturfBattleClient/src/app.ts b/TableturfBattleClient/src/app.ts index 57be347..53a7111 100644 --- a/TableturfBattleClient/src/app.ts +++ b/TableturfBattleClient/src/app.ts @@ -113,7 +113,10 @@ function onGameSettingsChange() { function onGameStateChange(game: any, playerData: PlayerData | null) { if (currentGame == null) throw new Error('currentGame is null'); - clearPlayContainers(); + + const isSameTurnReconnect = currentGame.game.state == GameState.Ongoing && currentGame.game.turnNumber == turnNumberLabel.turnNumber; + + if (!isSameTurnReconnect) clearPlayContainers(); currentGame.game.state = game.state; if (game.board) { @@ -122,9 +125,10 @@ function onGameStateChange(game: any, playerData: PlayerData | null) { else gamePage.classList.remove('boardFlipped'); board.resize(game.board); board.startSpaces = game.startSpaces; - board.refresh(); + if (!isSameTurnReconnect) board.refresh(); } - loadPlayers(game.players); + if (currentGame.game.state != GameState.Ongoing || currentGame.game.turnNumber != turnNumberLabel.turnNumber) + loadPlayers(game.players); gamePage.dataset.myPlayerIndex = playerData ? playerData.playerIndex.toString() : ''; gamePage.dataset.uiBaseColourIsSpecialColour = (userConfig.colourLock ? (playerData?.playerIndex ?? 0) != 1 @@ -162,7 +166,6 @@ function onGameStateChange(game: any, playerData: PlayerData | null) { case GameState.Ongoing: case GameState.GameEnded: case GameState.SetEnded: - board.autoHighlight = false; redrawModal.hidden = true; if (playerData) { updateHandAndDeck(playerData); @@ -183,15 +186,17 @@ function onGameStateChange(game: any, playerData: PlayerData | null) { timeLabel.paused = false; break; case GameState.Ongoing: - for (let i = 0; i < currentGame.game.players.length; i++) - showWaiting(i); if (currentGame.me) setConfirmLeavingGame(); turnNumberLabel.turnNumber = game.turnNumber; board.autoHighlight = true; canPlay = currentGame.me != null && !currentGame.game.players[currentGame.me.playerIndex].isReady; timeLabel.faded = !canPlay; timeLabel.paused = false; - resetPlayControls(); + if (!isSameTurnReconnect) { + for (let i = 0; i < currentGame.game.players.length; i++) + showWaiting(i); + resetPlayControls(); + } break; case GameState.GameEnded: case GameState.SetEnded: @@ -268,7 +273,8 @@ function setupWebSocket(gameID: string) { goalWinCount: payload.data.goalWinCount, }, me: payload.playerData, - webSocket: webSocket + webSocket: webSocket, + reconnecting: false }; updateColours(); @@ -419,8 +425,12 @@ function setupWebSocket(gameID: string) { webSocket.addEventListener('close', webSocket_close); } -function webSocket_close() { - communicationError(); +function webSocket_close(e: CloseEvent) { + if (currentGame == null || currentGame.reconnecting || (e.code != 1005 && e.code != 1006)) + communicationError(); + else + // Try to automatically reconnect. + setupWebSocket(currentGame.id); } function setConfirmLeavingGame() {