From c2025e0ca26bcf600ad43dc427bdddc78a08c44a Mon Sep 17 00:00:00 2001 From: Mike Mueller Date: Sun, 8 Mar 2026 13:46:20 +0100 Subject: [PATCH] Fix sound on non-host players --- src/game.js | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/game.js b/src/game.js index 59b5296..cd55702 100644 --- a/src/game.js +++ b/src/game.js @@ -127,6 +127,7 @@ const network = { lastInputSentAt: 0, activeRoster: [], lastPingAt: 0, + hasReceivedSnapshot: false, }; let audio = null; @@ -711,6 +712,7 @@ function startMultiplayerMatch(roster) { network.inLobby = false; network.lastSnapshotAt = now(); network.lastInputSentAt = 0; + network.hasReceivedSnapshot = network.isHost; state.mode = "multiplayer"; state.screen = "game"; resetRoundMultiplayer(network.activeRoster); @@ -749,6 +751,7 @@ function leaveLobbyInternals() { network.activeRoster = []; network.inputStateAtClient = { dir: null, bomb: false }; network.lastInputSentAt = 0; + network.hasReceivedSnapshot = false; } function leaveMultiplayerToMainMenu() { @@ -817,10 +820,65 @@ function serializeGameState() { }; } +function playSnapshotSfx(snapshot) { + const localEntityIds = new Set( + snapshot.players.filter((player) => player.ownerId === network.clientId).map((player) => player.id), + ); + + const previousBombIds = new Set(state.bombs.map((bomb) => bomb.id)); + let placedByOther = false; + for (const bomb of snapshot.bombs) { + if (!previousBombIds.has(bomb.id) && !localEntityIds.has(bomb.ownerId)) { + placedByOther = true; + break; + } + } + if (placedByOther) { + audio.playPlaceBomb(); + } + + const nextBombIds = new Set(snapshot.bombs.map((bomb) => bomb.id)); + let bombDetonated = false; + for (const bomb of state.bombs) { + if (!nextBombIds.has(bomb.id)) { + bombDetonated = true; + break; + } + } + if (bombDetonated && snapshot.explosions.length > 0) { + audio.playExplosion(); + } + + let powerupCollected = false; + for (let y = 0; y < state.map.length; y += 1) { + for (let x = 0; x < state.map[y].length; x += 1) { + const prevTile = state.map[y][x]; + const nextTile = snapshot.map[y]?.[x]; + if (!prevTile || !nextTile) { + continue; + } + if (prevTile.type === "floor" && prevTile.powerup && nextTile.type === "floor" && !nextTile.powerup) { + powerupCollected = true; + break; + } + } + if (powerupCollected) { + break; + } + } + + if (powerupCollected) { + audio.playPowerup(); + } +} + function applySnapshot(snapshot) { const previousPlayers = new Map( state.players.map((player) => [player.ownerId || `id:${player.id}`, { x: player.renderX, y: player.renderY }]), ); + if (network.hasReceivedSnapshot) { + playSnapshotSfx(snapshot); + } state.status = snapshot.status; state.message = snapshot.message; state.time = snapshot.time; @@ -857,6 +915,7 @@ function applySnapshot(snapshot) { state.nextBombId = snapshot.nextBombId; state.outcomePlayed = snapshot.outcomePlayed; state.menu.open = snapshot.menuOpen; + network.hasReceivedSnapshot = true; rebuildFireLookup(); }