@minicode-dev/chat 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/assets/sounds/tanks/big_explosion.mp3 +0 -0
  2. package/assets/sounds/tanks/big_explosion.ogg +0 -0
  3. package/assets/sounds/tanks/cannon_fire.mp3 +0 -0
  4. package/assets/sounds/tanks/cannon_fire.ogg +0 -0
  5. package/assets/sounds/tanks/defeat.mp3 +0 -0
  6. package/assets/sounds/tanks/defeat.ogg +0 -0
  7. package/assets/sounds/tanks/engine_loop.mp3 +0 -0
  8. package/assets/sounds/tanks/engine_loop.ogg +0 -0
  9. package/assets/sounds/tanks/engine_start.mp3 +0 -0
  10. package/assets/sounds/tanks/engine_start.ogg +0 -0
  11. package/assets/sounds/tanks/projectile_whistle.mp3 +0 -0
  12. package/assets/sounds/tanks/projectile_whistle.ogg +0 -0
  13. package/assets/sounds/tanks/tank_destroyed.mp3 +0 -0
  14. package/assets/sounds/tanks/tank_destroyed.ogg +0 -0
  15. package/assets/sounds/tanks/tank_hit.mp3 +0 -0
  16. package/assets/sounds/tanks/tank_hit.ogg +0 -0
  17. package/assets/sounds/tanks/terrain_impact.mp3 +0 -0
  18. package/assets/sounds/tanks/terrain_impact.ogg +0 -0
  19. package/assets/sounds/tanks/tracks_loop.mp3 +0 -0
  20. package/assets/sounds/tanks/tracks_loop.ogg +0 -0
  21. package/assets/sounds/tanks/turret_loop.mp3 +0 -0
  22. package/assets/sounds/tanks/turret_loop.ogg +0 -0
  23. package/assets/sounds/tanks/victory.mp3 +0 -0
  24. package/assets/sounds/tanks/victory.ogg +0 -0
  25. package/dist/chunks/{BattleshipGameCard-S-UdM6rn.js → BattleshipGameCard-CAWHxqJE.js} +231 -230
  26. package/dist/chunks/{BattleshipGameCard-S-UdM6rn.js.map → BattleshipGameCard-CAWHxqJE.js.map} +1 -1
  27. package/dist/chunks/{BattleshipPrototype-Dm6U_mCr.js → BattleshipPrototype-CmQd5AUO.js} +4 -3
  28. package/dist/chunks/{BattleshipPrototype-Dm6U_mCr.js.map → BattleshipPrototype-CmQd5AUO.js.map} +1 -1
  29. package/dist/chunks/ChatContext-CUiEAMKK.js +90 -0
  30. package/dist/chunks/ChatContext-CUiEAMKK.js.map +1 -0
  31. package/dist/chunks/TanksGameCard-BEnXTz_J.js +1705 -0
  32. package/dist/chunks/TanksGameCard-BEnXTz_J.js.map +1 -0
  33. package/dist/chunks/{battleship-DXKuIZ1I.js → board-DXKuIZ1I.js} +1 -1
  34. package/dist/chunks/board-DXKuIZ1I.js.map +1 -0
  35. package/dist/chunks/connect4Sounds-BDXQAvU1.js +3199 -0
  36. package/dist/chunks/connect4Sounds-BDXQAvU1.js.map +1 -0
  37. package/dist/chunks/core-geo-UJY-tH9L.js +361 -0
  38. package/dist/chunks/core-geo-UJY-tH9L.js.map +1 -0
  39. package/dist/chunks/createBattleScene-L4ZRWDED.js +1265 -0
  40. package/dist/chunks/createBattleScene-L4ZRWDED.js.map +1 -0
  41. package/dist/chunks/createTankScene-BuliAxwR.js +2150 -0
  42. package/dist/chunks/createTankScene-BuliAxwR.js.map +1 -0
  43. package/dist/index.js +2393 -2448
  44. package/dist/index.js.map +1 -1
  45. package/dist/styles.css +1 -1
  46. package/index.d.ts +2 -0
  47. package/package.json +1 -1
  48. package/dist/chunks/battleship-DXKuIZ1I.js.map +0 -1
  49. package/dist/chunks/connect4Sounds-9u0p-dAf.js +0 -1847
  50. package/dist/chunks/connect4Sounds-9u0p-dAf.js.map +0 -1
  51. package/dist/chunks/createBattleScene-HIAvjixn.js +0 -1621
  52. package/dist/chunks/createBattleScene-HIAvjixn.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"connect4Sounds-9u0p-dAf.js","names":["isId","createBoard","createBoard","isFleetComplete","removeShip","isCell","createBoard$1","fireShot","placeShip","FLEET","GAME_PREFIX","MAX_MESSAGE_LENGTH","UUID","isRecord","value","isId$1","isUuid","isMoves","moves","move","isHistory","data","SHIP_IDS","isCoord","isCommitment","isPly","isSunk","sunk","cell","isFleet","fleet","ship","isLogEntry","entry","last","isBattleshipLog","commit","index","isValidBattleshipEvent","event","isGameMessage","text","isValidGameEvent","parseGameMessage","encodeGameEvent","message","createGameEvent","createBoard","directions","getWinningCells","row","column","player","board","dr","dc","cells","step","r","c","getWinner","isBoardFull","dropPiece","playerId","next","winningCells","winner","isId","createGame","players","gameId","firstPlayerId","battleshipReducer","state","action","playerIndex","outcome","boards","ready","playing","targetIndex","TOTAL_SHIP_CELLS","sum","HEX32","ENDED","SYNC_LOST","MISSING_ACCEPT","INVALID_RESULT","FLEET_MISSING","emptyMatrix","setCell","matrix","line","col","countHits","countShots","attackerFor","ply","game","otherPlayer","id","commitField","conflict","cellKey","byCell","a","b","sameCells","left","right","createBattleshipGame","base","canEditFleet","canFire","shipCopy","placementOf","normalizePlacement","item","boardFromFleet","placement","toRevealFleet","items","shipId","fromRevealFleet","isFleetReady","ownBoard","placeFleetShip","removeFleetShip","secureRandomInt","max","limit","buffer","randomFleet","attempt","tries","randomInt","randomizeFleet","toHex","bytes","byte","createSalt","canonicalFleet","sorted","salt","computeCommitment","digest","buildResult","shot","sunkShip","definition","horizontal","vertical","checkReportedResult","defeated","result","shots","hits","taken","sunkCount","checkOwnResult","expected","applyCommit","field","author","commitment","ships","stored","applyFire","attacker","eventId","applyResult","mine","defender","checked","record","receiveFire","previous","receiveResult","applyReveal","applyBattleshipEvent","ctx","replayMatches","fleets","real","verifyReveal","reveal","opponentId","enemy","actual","own","encodeShot","start","publicLog","log","compareLogs","localAccept","local","remoteAccept","remote","marks","theirs","ours","position","mergeLogs","accept","adoptLog","commits","ownIndex","offset","logCovers","withLogSeen","seen","PREFIX","MAX_AGE_MS","keyOf","scope","storage","isSecret","prune","now","store","key","saveFleet","loadFleet","GAME_TYPES","gameTypeOf","isBattleship","BS_EFFECT_DELAY","terminal","keyFor","roomId","retainGames","finished","games","applyEvent","RESYNC_TIMEOUT","idleSync","isResync","type","historyOf","rebuild","acceptEventId","used","compareHistories","shared","pendingMoveId","connect4Sync","pendingId","createBattleshipSync","secretFor","resyncEvent","createChatGamesStore","transport","secrets","effectTimers","verifying","earlyEvents","resyncTimers","battleshipSync","syncFor","createStore","timer","set","options","scopeOrOptions","ownIdArgument","ownId","body","normalized","members","get","guestId","competing","queued","gameType","eventData","change","current","verification","send","mayReveal","sendingTransport","update","requireCurrent","patch","error","adapter","put","sync","isState","relation","resolved","reply","deliversPending","merged","union","replies","at","replyEvent","auto","fail","offer","chatGamesStore","useChatGames","useStore","selector","DEFAULT_BASE_URL","baseUrl","trimTrailingSlash","url","setChatAssetsBaseUrl","getChatAssetsBaseUrl","chatSoundUrl","relativePath","chatConnectionStore","setChatConnectionStatus","useChatConnectionStatus","sameUser","isTerminalGame","isLiveGame","isBattleshipGame","getGameTitle","VERIFICATION_LABELS","getVerificationLabel","getBattleshipStatus","myTurn","currentUserId","getGameStatus","status","getShortGameStatus","useSoundSettings","useSyncExternalStore","manager","GameSoundControls","silent","muted","volume","jsx","VolumeX","Volume2","GESTURES","MAX_KEYS","MAX_LATENCY_MS","clamp","readSettings","storageKey","defaults","LOOP_FADE_IN_S","LOOP_FADE_OUT_S","createSoundManager","AudioContextClass","settings","settingsFrom","defaultVolume","context","gain","unlocked","raw","buffers","missing","playedKeys","listeners","wantedLoops","loops","started","listening","unsubscribeSettings","urlFor","sounds","name","fetchRaw","response","ensureContext","loadBuffer","resolve","levelFor","levels","beginLoop","token","level","source","endLoop","loop","unlock","removeGestureListeners","remember","emit","listener","applySettings","setSettings","names","requestedAt","node","connect4Sounds","FOLLOW_UP_MS","pendingDrops","followUps","stopSounds","same","reducedMotion","playMoveOutcome","settleConnect4Drop","scheduleDrop","delay","onGameChange","before","isConnect4SoundsRunning","startConnect4Sounds","unsubscribe","stop"],"sources":["../../src/games/shared/protocol.js","../../src/games/connect4/connect4.js","../../src/games/battleship/logic/game.js","../../src/games/battleship/net/session.js","../../src/games/battleship/net/fleetStorage.js","../../src/games/shared/useChatGames.js","../../src/assets/chatAssets.js","../../src/core/connection/connectionStore.js","../../src/games/shared/gameStatus.js","../../src/audio/useSoundSettings.js","../../src/games/shared/GameSoundControls.jsx","../../src/audio/createSoundManager.js","../../src/games/connect4/connect4Sounds.js"],"sourcesContent":["export const GAME_PREFIX = 'LIRA_GAME_V1:';\nexport const GAME_VERSION = 1;\nconst MAX_MESSAGE_LENGTH = 4096;\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\nconst isRecord = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);\nconst isId = (value) => typeof value === 'string' && value.length > 0 && value.length <= 256 && value.trim() === value;\nconst isUuid = (value) => typeof value === 'string' && UUID.test(value);\n// Resync history: [[column, move_event_id], ...] in ply order; author follows parity.\nconst isMoves = (moves) => Array.isArray(moves) && moves.length <= 42\n && moves.every((move) => Array.isArray(move) && move.length === 2 && Number.isInteger(move[0])\n && move[0] >= 0 && move[0] < 7 && isUuid(move[1]))\n && new Set(moves.map((move) => move[1])).size === moves.length;\nconst isHistory = (data) => isMoves(data.moves) && data.rev === data.moves.length\n && (data.accept_event_id === undefined ? data.moves.length === 0 : isUuid(data.accept_event_id));\n\n// Battleship (game: 'battleship'). Fleets stay private until bs_reveal; see\n// src/features/battleship/net/session.js for the commit-reveal design.\nconst SHIP_IDS = ['carrier', 'battleship', 'cruiser', 'submarine', 'destroyer'];\nconst isCoord = (value) => Number.isInteger(value) && value >= 0 && value < 10;\nconst isCommitment = (value) => typeof value === 'string' && /^[0-9a-f]{64}$/.test(value);\nconst isPly = (value) => Number.isInteger(value) && value >= 1 && value <= 200;\nconst isSunk = (sunk) => sunk === null || (isRecord(sunk) && SHIP_IDS.includes(sunk.ship_id)\n && Array.isArray(sunk.cells) && sunk.cells.length >= 2 && sunk.cells.length <= 5\n && sunk.cells.every((cell) => Array.isArray(cell) && cell.length === 2 && isCoord(cell[0]) && isCoord(cell[1])));\nconst isFleet = (fleet) => Array.isArray(fleet) && fleet.length === SHIP_IDS.length\n && fleet.every((ship) => isRecord(ship) && SHIP_IDS.includes(ship.ship_id) && isCoord(ship.row) && isCoord(ship.col)\n && (ship.orientation === 'horizontal' || ship.orientation === 'vertical'))\n && new Set(fleet.map((ship) => ship.ship_id)).size === fleet.length;\n// Public log entry: [row, col] pending fire (last only) | [row, col, 0 miss | 1 hit]\n// | [row, col, 2, shipIndex, startRow, startCol, 0 horizontal | 1 vertical] (sunk).\nconst isLogEntry = (entry, last) => Array.isArray(entry) && isCoord(entry[0]) && isCoord(entry[1]) && (\n (entry.length === 2 && last)\n || (entry.length === 3 && (entry[2] === 0 || entry[2] === 1))\n || (entry.length === 7 && entry[2] === 2 && Number.isInteger(entry[3]) && entry[3] >= 0 && entry[3] < SHIP_IDS.length\n && isCoord(entry[4]) && isCoord(entry[5]) && (entry[6] === 0 || entry[6] === 1)));\nconst isBattleshipLog = (data) => Array.isArray(data.commits) && data.commits.length === 2\n && data.commits.every((commit) => commit === null || isCommitment(commit))\n && Array.isArray(data.log) && data.log.length <= 200\n && data.log.every((entry, index) => isLogEntry(entry, index === data.log.length - 1))\n && isUuid(data.head)\n && (data.accept_event_id === undefined\n ? data.commits.every((commit) => commit === null) && data.log.length === 0\n : isUuid(data.accept_event_id))\n && (data.log.length === 0 || data.commits.every(Boolean));\n\nfunction isValidBattleshipEvent(event) {\n const data = event.data;\n switch (event.type) {\n case 'game_invite':\n return isId(data.opponent_id) && data.rules_version === 1;\n case 'game_accept':\n case 'game_decline':\n return isUuid(data.invite_event_id);\n case 'game_end':\n return ['closed', 'win'].includes(data.reason) && (data.winner_id === undefined || isId(data.winner_id));\n case 'bs_commit':\n return isCommitment(data.commitment);\n case 'bs_fire':\n return isPly(data.ply) && isCoord(data.row) && isCoord(data.col) && isUuid(data.prev_event_id);\n case 'bs_result':\n return isPly(data.ply) && isCoord(data.row) && isCoord(data.col) && ['hit', 'miss'].includes(data.result)\n && isSunk(data.sunk) && typeof data.defeated === 'boolean'\n && (data.result === 'hit' || (data.sunk === null && !data.defeated));\n case 'bs_reveal':\n return isFleet(data.fleet) && typeof data.salt === 'string' && /^[0-9a-f]{32}$/.test(data.salt);\n case 'bs_sync_request':\n return isBattleshipLog(data);\n case 'bs_sync_state':\n return isBattleshipLog(data) && isUuid(data.request_event_id);\n default:\n return false;\n }\n}\n\nexport function isGameMessage(text) {\n return typeof text === 'string' && text.startsWith(GAME_PREFIX);\n}\n\nexport function isValidGameEvent(event) {\n if (!isRecord(event) || event.version !== GAME_VERSION || !['connect4', 'battleship'].includes(event.game)\n || !isUuid(event.game_id) || !isUuid(event.event_id) || !isRecord(event.data)) return false;\n if (event.game === 'battleship') return isValidBattleshipEvent(event);\n const data = event.data;\n switch (event.type) {\n case 'game_invite':\n return isId(data.opponent_id) && data.rules_version === 1;\n case 'game_accept':\n case 'game_decline':\n return isUuid(data.invite_event_id);\n case 'game_move':\n return Number.isInteger(data.column) && data.column >= 0 && data.column < 7\n && Number.isInteger(data.ply) && data.ply >= 1 && data.ply <= 42\n && isUuid(data.prev_event_id);\n case 'game_end':\n return ['closed', 'win', 'draw'].includes(data.reason)\n && (data.winner_id === undefined || isId(data.winner_id))\n && (data.final_move_event_id === undefined || isUuid(data.final_move_event_id))\n && (data.reason !== 'win' || (isId(data.winner_id) && isUuid(data.final_move_event_id)))\n && (data.reason !== 'draw' || isUuid(data.final_move_event_id));\n case 'game_resync_request':\n return isHistory(data);\n case 'game_resync_state':\n return isHistory(data) && isUuid(data.request_event_id);\n default:\n return false;\n }\n}\n\nexport function parseGameMessage(text) {\n if (!isGameMessage(text) || text.length > MAX_MESSAGE_LENGTH) return null;\n try {\n const event = JSON.parse(text.slice(GAME_PREFIX.length));\n return isValidGameEvent(event) ? event : null;\n } catch {\n return null;\n }\n}\n\nexport function encodeGameEvent(event) {\n if (!isValidGameEvent(event)) throw new Error('Evento de juego inválido');\n const message = GAME_PREFIX + JSON.stringify(event);\n if (message.length > MAX_MESSAGE_LENGTH) throw new Error('Evento de juego demasiado grande');\n return message;\n}\n\nexport function createGameEvent(type, { game_id, data, event_id = crypto.randomUUID(), game = 'connect4' }) {\n const event = { version: GAME_VERSION, game, game_id, event_id, type, data };\n if (!isValidGameEvent(event)) throw new Error('Evento de juego inválido');\n return event;\n}\n","export const ROWS = 6;\nexport const COLUMNS = 7;\nexport const CONNECT = 4;\n\nexport function createBoard() {\n return Array.from({ length: ROWS }, () => Array(COLUMNS).fill(null));\n}\n\nconst directions = [[0, 1], [1, 0], [1, 1], [1, -1]];\n\nexport function getWinningCells(board) {\n for (let row = 0; row < ROWS; row += 1) {\n for (let column = 0; column < COLUMNS; column += 1) {\n const player = board[row][column];\n if (player == null) continue;\n for (const [dr, dc] of directions) {\n const cells = [];\n for (let step = 0; step < CONNECT; step += 1) {\n const r = row + dr * step;\n const c = column + dc * step;\n if (r < 0 || r >= ROWS || c < 0 || c >= COLUMNS || board[r][c] !== player) break;\n cells.push([r, c]);\n }\n if (cells.length === CONNECT) return cells;\n }\n }\n }\n return [];\n}\n\nexport function getWinner(board) {\n const cells = getWinningCells(board);\n return cells.length ? board[cells[0][0]][cells[0][1]] : null;\n}\n\nexport function isBoardFull(board) {\n return board[0].every((cell) => cell !== null);\n}\n\n// Pure rules: the store validates identities, sequencing and whose turn it is.\nexport function dropPiece(board, column, playerId) {\n if (!Number.isInteger(column) || column < 0 || column >= COLUMNS || playerId == null\n || getWinner(board) !== null) return null;\n let row = ROWS - 1;\n while (row >= 0 && board[row][column] !== null) row -= 1;\n if (row < 0) return null;\n const next = board.map((cells) => cells.slice());\n next[row][column] = playerId;\n const winningCells = getWinningCells(next);\n const winner = winningCells.length ? next[winningCells[0][0]][winningCells[0][1]] : null;\n return { board: next, row, column, winner, draw: winner === null && isBoardFull(next), winningCells };\n}\n\nexport function getTurn(players, ply = 0) {\n return players[ply % 2];\n}\n","import { RULES_VERSION, createBoard, placeShip, removeShip, isFleetComplete, fireShot } from './board.js';\n\nconst isId = (value) => typeof value === 'string' && value.length > 0 && value.length <= 256 && value.trim() === value;\n\n/** Caller supplies identifiers and the initial player: no clocks or randomness. */\nexport function createGame({ gameId, players, firstPlayerId = players?.[0] } = {}) {\n if (!isId(gameId) || !Array.isArray(players) || players.length !== 2\n || !players.every(isId) || players[0] === players[1] || !players.includes(firstPlayerId)) {\n throw new TypeError('Supply a gameId, two distinct player IDs and a valid firstPlayerId.');\n }\n return {\n game: 'battleship', rulesVersion: RULES_VERSION, gameId,\n players: players.slice(), boards: [createBoard(), createBoard()],\n ready: [false, false], phase: 'placement', turnId: null,\n firstPlayerId, winnerId: null, shotCount: 0, lastShot: null, revision: 0,\n };\n}\n\n/**\n * Invalid/stale actions return the original reference. Each accepted action adds\n * exactly one revision. Never trust a claimed hit/result: derive it from boards.\n * Optional gameId/expectedRevision let a future transport reject stale commands.\n */\nexport function battleshipReducer(state, action) {\n if (!state || !action || typeof action !== 'object' || state.phase === 'finished') return state;\n if (action.gameId !== undefined && action.gameId !== state.gameId) return state;\n if (action.expectedRevision !== undefined && action.expectedRevision !== state.revision) return state;\n const playerIndex = state.players.indexOf(action.playerId);\n if (playerIndex < 0) return state;\n const board = state.boards[playerIndex];\n if (state.phase === 'placement') {\n if (state.ready[playerIndex]) return state;\n if (action.type === 'place_ship' || action.type === 'remove_ship') {\n const outcome = action.type === 'place_ship'\n ? placeShip(board, action) : removeShip(board, action.shipId);\n if (!outcome.ok) return state;\n const boards = state.boards.slice();\n boards[playerIndex] = outcome.board;\n return { ...state, boards, revision: state.revision + 1 };\n }\n if (action.type === 'ready' && isFleetComplete(board)) {\n const ready = state.ready.slice();\n ready[playerIndex] = true;\n const playing = ready.every(Boolean);\n return {\n ...state, ready, phase: playing ? 'playing' : 'placement',\n turnId: playing ? state.firstPlayerId : null, revision: state.revision + 1,\n };\n }\n return state;\n }\n if (state.phase !== 'playing' || action.type !== 'fire' || action.playerId !== state.turnId) return state;\n const targetIndex = 1 - playerIndex;\n const outcome = fireShot(state.boards[targetIndex], action);\n if (!outcome.ok) return state;\n const boards = state.boards.slice();\n boards[targetIndex] = outcome.board;\n return {\n ...state, boards, revision: state.revision + 1, shotCount: state.shotCount + 1,\n phase: outcome.defeated ? 'finished' : 'playing',\n turnId: outcome.defeated ? null : state.players[targetIndex],\n winnerId: outcome.defeated ? action.playerId : null,\n lastShot: {\n playerId: action.playerId, targetId: state.players[targetIndex],\n row: action.row, col: action.col, result: outcome.result,\n shipId: outcome.shipId, sunk: outcome.sunk, defeated: outcome.defeated,\n },\n };\n}\n","/**\n * Battleship over LIRA_GAME_V1 chat frames: pure session reducer. No React, no\n * sockets, no storage. Board rules come from ../logic (Codex, read-only).\n *\n * Fairness (100% frontend, commit-reveal; detection, not prevention):\n * 1. Each player places the fleet locally. The fleet is NEVER sent before the end.\n * 2. On \"ready\" the client draws a 128-bit salt (crypto.getRandomValues) and sends\n * bs_commit { commitment = SHA-256(canonicalFleet(fleet, salt)) } where the\n * canonical form is JSON {fleet:[{ship_id,row,col,orientation}] sorted by\n * ship_id, salt}. {fleet, salt} is kept in localStorage (fleetStorage.js).\n * 3. The battle starts when both commitments are known. The host fires first and\n * every resolved shot changes turn (Codex rule in logic/game.js).\n * 4. The attacker sends bs_fire {ply, row, col, prev_event_id}. The defender's\n * client computes the result from its own fleet (logic/board.js fireShot) and\n * answers bs_result automatically. The attacker accepts only plausible results:\n * the cell matches the pending ply; a sunk ship is a straight contiguous line of\n * the size of a not-yet-sunk class, contains the cell and only previously\n * reported hits; defeated iff 17 hits (and five ships sunk); 17 hits must remain\n * reachable. Implausible results put the game in 'conflict'.\n * 5. When a fleet is defeated both clients send bs_reveal {fleet, salt}. Each one\n * checks SHA-256 against the opponent commitment and replays ALL shots with the\n * Codex createGame/battleshipReducer (both fleets, firstPlayer = host). Same\n * results/sunk/defeated → verification 'ok', otherwise 'mismatch' (cheating\n * warning; the winner stays the one reported during play). No reveal → 'pending'.\n *\n * Chain: ply 1 references the accept event; every later bs_fire references the\n * previous bs_result. Commits are independent of the chain.\n * Resync: publicLog(game) is the public history (no fleets); compareLogs →\n * equal | behind | ahead | diverged | mixed (only before the battle: independent\n * commits, merge them); adoptLog replays a history through the same rules.\n */\nimport { BOARD_SIZE, FLEET, createBoard, isCell, placeShip, validatePlacement, isFleetComplete, fireShot } from '../logic/board.js';\nimport { createGame, battleshipReducer } from '../logic/game.js';\n\nexport const TOTAL_SHIP_CELLS = FLEET.reduce((sum, ship) => sum + ship.size, 0);\nconst HEX32 = /^[0-9a-f]{32}$/;\nconst ENDED = ['won', 'closed', 'declined'];\nconst SYNC_LOST = 'La partida perdió sincronización. Se intentará resincronizar.';\nconst MISSING_ACCEPT = 'Falta la aceptación de la partida. Ciérrala y vuelve a invitar.';\nconst INVALID_RESULT = 'El rival envió un resultado imposible para ese disparo.';\nconst FLEET_MISSING = 'Tu flota no está disponible en este dispositivo; no se pueden responder disparos.';\n\nconst emptyMatrix = () => Array.from({ length: BOARD_SIZE }, () => Array(BOARD_SIZE).fill(null));\nconst setCell = (matrix, row, col, value) => matrix.map((line, r) => (r === row ? line.map((cell, c) => (c === col ? value : cell)) : line));\nconst countHits = (matrix) => matrix.reduce((sum, line) => sum + line.filter((cell) => cell === 'hit').length, 0);\nconst countShots = (matrix) => matrix.reduce((sum, line) => sum + line.filter((cell) => cell !== null).length, 0);\nconst attackerFor = (game, ply) => (ply % 2 === 1 ? game.hostId : game.guestId);\nconst otherPlayer = (game, id) => (id === game.hostId ? game.guestId : game.hostId);\nconst commitField = (game, id) => (id === game.hostId ? 'hostCommitment' : 'guestCommitment');\nconst conflict = (game, error) => ({ ...game, status: 'conflict', error });\nconst cellKey = (cell) => `${cell.row},${cell.col}`;\nconst byCell = (a, b) => a.row - b.row || a.col - b.col;\nconst sameCells = (left, right) => left.length === right.length\n && left.map(cellKey).sort().join('|') === right.map(cellKey).sort().join('|');\n\n/* ------------------------------ game object ------------------------------ */\n\n/** base: { key, gameId, scope, roomId, hostId, guestId, ownId, createdAt, inviteEventId, lastEventId, seen, sync } */\nexport function createBattleshipGame(base) {\n return {\n ...base, game: 'battleship', status: 'invited', turnId: null,\n myFleet: [], myReady: false, opponentReady: false,\n incomingShots: emptyMatrix(), targetShots: emptyMatrix(), sunkEnemyShips: [],\n pendingShot: null, lastShot: null, winnerId: null, verification: null,\n ply: 0, shots: [], acceptEventId: null, hostCommitment: null, guestCommitment: null,\n myCommitment: null, mySalt: null, myRevealSent: false, opponentReveal: null,\n seen: base.seen ?? {}, pending: false, pendingEvent: null, error: '', sync: base.sync ?? null,\n };\n}\n\nexport const canEditFleet = (game) => game?.game === 'battleship' && ['invited', 'placement'].includes(game.status) && !game.myReady;\nexport const canFire = (game) => game?.status === 'active' && game.turnId === game.ownId && !game.pendingShot;\n\n/* --------------------------------- fleets -------------------------------- */\n\nconst shipCopy = (ship) => ({ id: ship.id, size: ship.size, orientation: ship.orientation, cells: ship.cells.map((cell) => ({ row: cell.row, col: cell.col })) });\nconst placementOf = (ship) => ({ shipId: ship.id, row: ship.cells[0].row, col: ship.cells[0].col, orientation: ship.orientation });\n\n// Accepts game ships ({id, cells, orientation}) and reveal ships ({ship_id, row, col, orientation}).\nfunction normalizePlacement(item) {\n if (!item || typeof item !== 'object') return null;\n if (typeof item.ship_id === 'string') return { shipId: item.ship_id, row: item.row, col: item.col, orientation: item.orientation };\n if (typeof item.id === 'string' && Array.isArray(item.cells) && item.cells.length) return placementOf(item);\n return null;\n}\n\n/** Codex board for a fleet (no shots), or null when any ship is invalid/overlapping. */\nexport function boardFromFleet(fleet) {\n if (!Array.isArray(fleet)) return null;\n let board = createBoard();\n for (const item of fleet) {\n const placement = normalizePlacement(item);\n const outcome = placement && placeShip(board, placement);\n if (!outcome?.ok) return null;\n board = outcome.board;\n }\n return board;\n}\n\n/** Reveal/commit format: [{ship_id,row,col,orientation}] sorted by ship_id; null if invalid. */\nexport function toRevealFleet(fleet) {\n if (!Array.isArray(fleet)) return null;\n const items = fleet.map(normalizePlacement);\n if (items.some((item) => !item)) return null;\n return items.map(({ shipId, row, col, orientation }) => ({ ship_id: shipId, row, col, orientation }))\n .sort((a, b) => (a.ship_id < b.ship_id ? -1 : a.ship_id > b.ship_id ? 1 : 0));\n}\n\n/** Complete fleet → game ships; null when invalid or incomplete. */\nexport function fromRevealFleet(fleet) {\n const board = boardFromFleet(fleet);\n return board && isFleetComplete(board) ? board.ships.map(shipCopy) : null;\n}\n\nexport const isFleetReady = (fleet) => Boolean(fromRevealFleet(fleet));\n\n/** Own board with the opponent's shots applied (for fireShot), or null without a fleet. */\nexport function ownBoard(game) {\n const board = boardFromFleet(game?.myFleet);\n return board && isFleetComplete(board) ? { ...board, shots: game.incomingShots.map((line) => line.slice()) } : null;\n}\n\n/** Placement preview ignoring the ship being moved: { ok, reason?, ship? }. */\nexport function previewPlacement(game, placement) {\n const board = boardFromFleet((game?.myFleet ?? []).filter((ship) => ship.id !== placement?.shipId));\n return board ? validatePlacement(board, placement) : { ok: false, reason: 'invalid_fleet' };\n}\n\n/** Places (or moves) one ship. Invalid placements return the same reference. */\nexport function placeFleetShip(game, { shipId, row, col, orientation } = {}) {\n if (!canEditFleet(game)) return game;\n const board = boardFromFleet(game.myFleet.filter((ship) => ship.id !== shipId));\n const outcome = board && placeShip(board, { shipId, row, col, orientation });\n return outcome?.ok ? { ...game, myFleet: outcome.board.ships.map(shipCopy) } : game;\n}\n\nexport function removeFleetShip(game, shipId) {\n if (!canEditFleet(game) || !game.myFleet.some((ship) => ship.id === shipId)) return game;\n return { ...game, myFleet: game.myFleet.filter((ship) => ship.id !== shipId) };\n}\n\nexport function secureRandomInt(limit) {\n const max = Math.floor(0x100000000 / limit) * limit;\n const buffer = new Uint32Array(1);\n do globalThis.crypto.getRandomValues(buffer); while (buffer[0] >= max);\n return buffer[0] % limit;\n}\n\n/** Random complete fleet (seedless, crypto-backed unless randomInt is supplied). */\nexport function randomFleet(randomInt = secureRandomInt) {\n for (let attempt = 0; attempt < 50; attempt += 1) {\n let board = createBoard();\n for (const ship of FLEET) {\n for (let tries = 0; tries < 300; tries += 1) {\n const outcome = placeShip(board, {\n shipId: ship.id, row: randomInt(BOARD_SIZE), col: randomInt(BOARD_SIZE),\n orientation: randomInt(2) === 0 ? 'horizontal' : 'vertical',\n });\n if (outcome.ok) { board = outcome.board; break; }\n }\n }\n if (isFleetComplete(board)) return board.ships.map(shipCopy);\n }\n throw new Error('No se pudo generar una flota aleatoria.');\n}\n\nexport const randomizeFleet = (game, randomInt) => (canEditFleet(game) ? { ...game, myFleet: randomFleet(randomInt) } : game);\n\n/* ------------------------------ commit-reveal ----------------------------- */\n\nconst toHex = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n\nexport function createSalt() {\n const bytes = new Uint8Array(16);\n globalThis.crypto.getRandomValues(bytes);\n return toHex(bytes);\n}\n\nexport function canonicalFleet(fleet, salt) {\n const sorted = toRevealFleet(fleet);\n if (!sorted || typeof salt !== 'string') throw new TypeError('Flota inválida');\n return JSON.stringify({ fleet: sorted, salt });\n}\n\nexport async function computeCommitment(fleet, salt) {\n const digest = await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(canonicalFleet(fleet, salt)));\n return toHex(new Uint8Array(digest));\n}\n\n/** bs_result data for a shot at `board` (own fleet + received shots), or null. */\nexport function buildResult(board, shot) {\n if (!board || !shot) return null;\n const outcome = fireShot(board, { row: shot.row, col: shot.col });\n if (!outcome.ok) return null;\n const ship = outcome.sunk ? board.ships.find((item) => item.id === outcome.shipId) : null;\n return {\n ply: shot.ply, row: shot.row, col: shot.col, result: outcome.result,\n sunk: ship ? { ship_id: ship.id, cells: ship.cells.map((cell) => [cell.row, cell.col]) } : null,\n defeated: outcome.defeated,\n };\n}\n\n/** Wire sunk {ship_id, cells:[[r,c]]} → ship {id,size,orientation,cells} when it is a valid straight ship. */\nfunction sunkShip(sunk) {\n const definition = FLEET.find((ship) => ship.id === sunk?.ship_id);\n if (!definition || !Array.isArray(sunk.cells) || sunk.cells.length !== definition.size) return null;\n const cells = sunk.cells.map((cell) => (Array.isArray(cell) ? { row: cell[0], col: cell[1] } : null));\n if (cells.some((cell) => !isCell(cell))) return null;\n cells.sort(byCell);\n const horizontal = cells.every((cell, index) => cell.row === cells[0].row && cell.col === cells[0].col + index);\n const vertical = cells.every((cell, index) => cell.col === cells[0].col && cell.row === cells[0].row + index);\n if (!horizontal && !vertical) return null;\n return { id: definition.id, size: definition.size, orientation: horizontal ? 'horizontal' : 'vertical', cells, sunk: true };\n}\n\n// Attacker side: the defender's fleet is unknown, so check what can be checked.\nfunction checkReportedResult(game, data) {\n const { row, col, result, sunk } = data;\n const defeated = Boolean(data.defeated);\n if ((result !== 'hit' && result !== 'miss') || game.targetShots[row][col] !== null) return null;\n const shots = setCell(game.targetShots, row, col, result);\n const hits = countHits(shots);\n let ship = null;\n if (sunk) {\n ship = result === 'hit' ? sunkShip(sunk) : null;\n if (!ship || game.sunkEnemyShips.some((item) => item.id === ship.id)) return null;\n const taken = new Set(game.sunkEnemyShips.flatMap((item) => item.cells.map(cellKey)));\n if (!ship.cells.some((cell) => cell.row === row && cell.col === col)) return null;\n if (ship.cells.some((cell) => shots[cell.row][cell.col] !== 'hit' || taken.has(cellKey(cell)))) return null;\n }\n const sunkCount = game.sunkEnemyShips.length + (ship ? 1 : 0);\n if (hits > TOTAL_SHIP_CELLS || defeated !== (hits === TOTAL_SHIP_CELLS)) return null;\n if (defeated !== (sunkCount === FLEET.length)) return null;\n // Even hitting every remaining cell could not reach 17: hits are being hidden.\n if (!defeated && TOTAL_SHIP_CELLS - hits > BOARD_SIZE * BOARD_SIZE - countShots(shots)) return null;\n return { shots, ship };\n}\n\n// Defender side: the result must be exactly what our own fleet produces.\nfunction checkOwnResult(game, data) {\n const expected = buildResult(ownBoard(game), data);\n if (!expected || expected.result !== data.result || expected.defeated !== Boolean(data.defeated)\n || Boolean(expected.sunk) !== Boolean(data.sunk)) return null;\n const ship = expected.sunk ? sunkShip(expected.sunk) : null;\n if (ship && (data.sunk.ship_id !== ship.id || !sameCells(ship.cells, data.sunk.cells.map(([row, col]) => ({ row, col }))))) return null;\n return { shots: setCell(game.incomingShots, data.row, data.col, data.result), ship };\n}\n\n/* -------------------------------- reducer -------------------------------- */\n\nfunction applyCommit(game, author, commitment, stored) {\n const field = commitField(game, author);\n if (game[field]) return game[field] === commitment ? game : null;\n let next = { ...game, [field]: commitment };\n if (author === game.ownId) {\n const ships = stored?.commitment === commitment ? fromRevealFleet(stored.fleet) : null;\n if (ships && HEX32.test(stored.salt ?? '')) next = { ...next, myFleet: ships, mySalt: stored.salt, myCommitment: commitment };\n else if (game.myCommitment !== commitment || !game.mySalt) next = { ...next, myFleet: [], mySalt: null, myCommitment: commitment, error: FLEET_MISSING };\n next.myReady = true;\n } else next.opponentReady = true;\n if (next.hostCommitment && next.guestCommitment) next = { ...next, status: 'active', turnId: game.hostId, ply: 0, pendingShot: null };\n return next;\n}\n\nfunction applyFire(game, attacker, { row, col, ply }, eventId) {\n const matrix = attacker === game.ownId ? game.targetShots : game.incomingShots;\n if (!isCell({ row, col }) || matrix[row][col] !== null) return null;\n return { ...game, pendingShot: { row, col, ply, by: attacker }, lastEventId: eventId ?? game.lastEventId };\n}\n\nfunction applyResult(game, defender, data, eventId) {\n const shot = game.pendingShot;\n const mine = defender === game.ownId;\n const checked = mine ? checkOwnResult(game, data) : checkReportedResult(game, data);\n if (!checked) return null;\n const defeated = Boolean(data.defeated);\n const record = { ply: shot.ply, by: shot.by, row: shot.row, col: shot.col, result: data.result, sunk: checked.ship, defeated };\n return {\n ...game,\n incomingShots: mine ? checked.shots : game.incomingShots,\n targetShots: mine ? game.targetShots : checked.shots,\n sunkEnemyShips: !mine && checked.ship ? [...game.sunkEnemyShips, checked.ship] : game.sunkEnemyShips,\n ply: shot.ply, shots: [...game.shots, record], pendingShot: null,\n lastShot: { ...record, eventId: eventId ?? null }, lastEventId: eventId ?? game.lastEventId,\n turnId: defeated ? null : defender, status: defeated ? 'won' : 'active',\n winnerId: defeated ? shot.by : null, verification: defeated ? 'pending' : game.verification,\n };\n}\n\nfunction receiveFire(game, event, author) {\n const { ply, row, col, prev_event_id: previous } = event.data;\n if (author !== attackerFor(game, ply)) return game;\n if (game.status !== 'active') return conflict(game, game.status === 'invited' ? MISSING_ACCEPT : SYNC_LOST);\n if (ply <= game.ply) return game;\n if (game.pendingShot) return ply === game.pendingShot.ply ? game : conflict(game, SYNC_LOST);\n if (ply > game.ply + 1) return conflict(game, SYNC_LOST);\n if (author !== game.turnId) return game;\n if (previous !== game.lastEventId) return conflict(game, SYNC_LOST);\n return applyFire(game, author, { row, col, ply }, event.event_id) ?? game;\n}\n\nfunction receiveResult(game, event, author) {\n const { ply, row, col } = event.data;\n if (game.status !== 'active') return game.status === 'placement' ? conflict(game, SYNC_LOST) : game;\n const shot = game.pendingShot;\n if (!shot) return ply <= game.ply ? game : conflict(game, SYNC_LOST);\n if (ply !== shot.ply) return ply < shot.ply ? game : conflict(game, SYNC_LOST);\n if (author === shot.by) return game;\n if (row !== shot.row || col !== shot.col) return author === game.ownId ? game : conflict(game, 'El rival respondió a un disparo distinto.');\n const next = applyResult(game, author, event.data, event.event_id);\n if (next) return next;\n return author === game.ownId ? game : conflict(game, INVALID_RESULT);\n}\n\nfunction applyReveal(game, data, author) {\n if (!game.winnerId || !['won', 'closed'].includes(game.status)) return game;\n if (author === game.ownId) return game.myRevealSent ? game : { ...game, myRevealSent: true };\n if (game.opponentReveal) return game;\n return { ...game, opponentReveal: { fleet: data.fleet.map((ship) => ({ ...ship })), salt: data.salt }, verification: 'pending' };\n}\n\n/**\n * Applies one validated protocol event authored by `author`. Returns the next game\n * or the same reference when the event is invalid, duplicated, stale or out of turn.\n * ctx.stored: own {fleet, salt, commitment} (needed when ingesting our own bs_commit).\n */\nexport function applyBattleshipEvent(game, event, author, ctx = {}) {\n if (!game || game.game !== 'battleship' || event?.game !== 'battleship' || event.game_id !== game.gameId) return game;\n if (author !== game.hostId && author !== game.guestId) return game;\n const data = event.data;\n if (event.type === 'game_end') {\n if (data.reason !== 'closed' || ['closed', 'declined', 'won'].includes(game.status)) return game;\n return { ...game, status: 'closed', closedBy: author, error: '' };\n }\n if (event.type === 'bs_reveal') return applyReveal(game, data, author);\n if (ENDED.includes(game.status) || game.status === 'conflict') return game;\n switch (event.type) {\n case 'game_accept':\n case 'game_decline':\n if (author !== game.guestId || game.status !== 'invited' || data.invite_event_id !== game.inviteEventId) return game;\n return event.type === 'game_accept'\n ? { ...game, status: 'placement', acceptEventId: event.event_id, lastEventId: event.event_id }\n : { ...game, status: 'declined', lastEventId: event.event_id };\n case 'bs_commit':\n if (game.status === 'invited') return conflict(game, MISSING_ACCEPT);\n if (game.status !== 'placement') return game;\n return applyCommit(game, author, data.commitment, ctx.stored) ?? game;\n case 'bs_fire':\n return receiveFire(game, event, author);\n case 'bs_result':\n return receiveResult(game, event, author);\n default:\n return game;\n }\n}\n\n/* ------------------------------ verification ----------------------------- */\n\nfunction replayMatches(game, fleets) {\n let state = createGame({ gameId: String(game.gameId), players: [game.hostId, game.guestId], firstPlayerId: game.hostId });\n for (const playerId of state.players) {\n for (const ship of fleets[playerId]) state = battleshipReducer(state, { type: 'place_ship', playerId, ...placementOf(ship) });\n state = battleshipReducer(state, { type: 'ready', playerId });\n }\n if (state.phase !== 'playing') return false;\n for (const shot of game.shots) {\n const next = battleshipReducer(state, { type: 'fire', playerId: shot.by, row: shot.row, col: shot.col });\n if (next === state) return false;\n const real = next.lastShot;\n if (real.result !== shot.result || real.defeated !== shot.defeated || real.sunk !== Boolean(shot.sunk)) return false;\n if (shot.sunk) {\n const ship = next.boards[next.players.indexOf(real.targetId)].ships.find((item) => item.id === real.shipId);\n if (shot.sunk.id !== real.shipId || !sameCells(ship.cells, shot.sunk.cells)) return false;\n }\n state = next;\n }\n return !game.winnerId || state.winnerId === game.winnerId;\n}\n\n/** 'ok' | 'mismatch' | 'pending' (no reveal yet, or our own fleet is unavailable). */\nexport async function verifyReveal(game, reveal = game?.opponentReveal) {\n if (!game || !reveal) return 'pending';\n const opponentId = otherPlayer(game, game.ownId);\n const commitment = game[commitField(game, opponentId)];\n const enemy = fromRevealFleet(reveal.fleet);\n if (!commitment || !enemy || typeof reveal.salt !== 'string' || !HEX32.test(reveal.salt)) return 'mismatch';\n let actual;\n try {\n actual = await computeCommitment(reveal.fleet, reveal.salt);\n } catch {\n return 'mismatch';\n }\n if (actual !== commitment) return 'mismatch';\n const own = fromRevealFleet(game.myFleet);\n if (!own) return 'pending';\n return replayMatches(game, { [game.ownId]: own, [opponentId]: enemy }) ? 'ok' : 'mismatch';\n}\n\n/* --------------------------------- resync -------------------------------- */\n\nconst encodeShot = (shot) => {\n if (shot.result === 'miss') return [shot.row, shot.col, 0];\n if (!shot.sunk) return [shot.row, shot.col, 1];\n const start = shot.sunk.cells[0];\n return [shot.row, shot.col, 2, FLEET.findIndex((ship) => ship.id === shot.sunk.id), start.row, start.col, shot.sunk.orientation === 'vertical' ? 1 : 0];\n};\n\n/** Public history for bs_sync_request/bs_sync_state data (never contains a fleet). */\nexport function publicLog(game) {\n if (!game.acceptEventId) return { commits: [null, null], log: [], head: game.inviteEventId };\n const log = game.shots.map(encodeShot);\n if (game.pendingShot) log.push([game.pendingShot.row, game.pendingShot.col]);\n return { accept_event_id: game.acceptEventId, commits: [game.hostCommitment ?? null, game.guestCommitment ?? null], log, head: game.lastEventId };\n}\n\n/** equal | behind (remote extends local) | ahead | diverged | mixed (pre-battle commits on both sides). */\nexport function compareLogs(local, remote) {\n const localAccept = local.accept_event_id ?? null;\n const remoteAccept = remote.accept_event_id ?? null;\n if (localAccept && remoteAccept && localAccept !== remoteAccept) return 'diverged';\n const marks = new Set();\n if (localAccept && !remoteAccept) marks.add('ahead');\n if (!localAccept && remoteAccept) marks.add('behind');\n for (const index of [0, 1]) {\n const mine = local.commits?.[index] ?? null;\n const theirs = remote.commits?.[index] ?? null;\n if (mine && theirs && mine !== theirs) return 'diverged';\n if (mine && !theirs) marks.add('ahead');\n if (!mine && theirs) marks.add('behind');\n }\n const ours = local.log ?? [];\n const theirs = remote.log ?? [];\n for (let index = 0; index < Math.min(ours.length, theirs.length); index += 1) {\n const left = ours[index];\n const right = theirs[index];\n if (left.length === right.length) {\n if (left.some((value, position) => value !== right[position])) return 'diverged';\n } else if (left[0] !== right[0] || left[1] !== right[1]) return 'diverged';\n // A pending fire is a prefix of its resolved entry.\n else marks.add(left.length === 2 ? 'behind' : 'ahead');\n }\n if (ours.length !== theirs.length) marks.add(ours.length < theirs.length ? 'behind' : 'ahead');\n if (marks.size === 2) return 'mixed';\n if (marks.size === 1) return [...marks][0];\n return ours.length && local.head !== remote.head ? 'diverged' : 'equal';\n}\n\n/** Union of two pre-battle histories (relation 'mixed'); null when they cannot merge. */\nexport function mergeLogs(local, remote) {\n if ((local.log ?? []).length || (remote.log ?? []).length) return null;\n const accept = local.accept_event_id ?? remote.accept_event_id;\n if (!accept) return null;\n return { accept_event_id: accept, commits: [0, 1].map((index) => local.commits?.[index] ?? remote.commits?.[index] ?? null), log: [], head: accept };\n}\n\n/**\n * Rebuilds the game from a public history using the same rules as live events.\n * Keeps local-only data (own fleet draft, salt). Returns null for an invalid history.\n */\nexport function adoptLog(game, data, ctx = {}) {\n const base = {\n ...game, status: 'invited', turnId: null, myReady: false, opponentReady: false,\n incomingShots: emptyMatrix(), targetShots: emptyMatrix(), sunkEnemyShips: [],\n pendingShot: null, lastShot: null, winnerId: null, verification: null, ply: 0, shots: [],\n acceptEventId: null, hostCommitment: null, guestCommitment: null, error: '',\n myRevealSent: false, opponentReveal: null, closedBy: undefined,\n };\n const log = data.log ?? [];\n const commits = data.commits ?? [null, null];\n if (!data.accept_event_id) {\n return commits.some(Boolean) || log.length ? null : { ...base, lastEventId: game.inviteEventId };\n }\n if (data.accept_event_id === game.inviteEventId) return null;\n const ownIndex = game.ownId === game.hostId ? 0 : 1;\n if (game.myCommitment && commits[ownIndex] && commits[ownIndex] !== game.myCommitment\n && ctx.stored?.commitment !== commits[ownIndex]) return null;\n let state = { ...base, status: 'placement', acceptEventId: data.accept_event_id, lastEventId: data.accept_event_id };\n for (const [index, playerId] of [game.hostId, game.guestId].entries()) {\n if (!commits[index]) continue;\n state = applyCommit(state, playerId, commits[index], ctx.stored);\n if (!state) return null;\n }\n if (log.length && state.status !== 'active') return null;\n for (let index = 0; index < log.length; index += 1) {\n const entry = log[index];\n const ply = index + 1;\n state = applyFire(state, attackerFor(state, ply), { row: entry[0], col: entry[1], ply }, null);\n if (!state) return null;\n if (entry.length === 2) {\n if (index !== log.length - 1) return null;\n break;\n }\n const defender = otherPlayer(state, state.pendingShot.by);\n let sunk = null;\n if (entry[2] === 2) {\n const definition = FLEET[entry[3]];\n if (!definition) return null;\n const vertical = entry[6] === 1;\n sunk = { ship_id: definition.id, cells: Array.from({ length: definition.size }, (_, offset) => [entry[4] + (vertical ? offset : 0), entry[5] + (vertical ? 0 : offset)]) };\n }\n const matrix = defender === state.ownId ? state.incomingShots : state.targetShots;\n const hits = countHits(matrix) + (entry[2] === 0 ? 0 : 1);\n state = applyResult(state, defender, { ply, row: entry[0], col: entry[1], result: entry[2] === 0 ? 'miss' : 'hit', sunk, defeated: hits === TOTAL_SHIP_CELLS }, null);\n if (!state || (state.status === 'won' && index !== log.length - 1)) return null;\n }\n if (!log.length && data.head !== data.accept_event_id) return null;\n state = { ...state, lastEventId: data.head };\n // A finished game keeps the reveal exchange it already had.\n if (state.winnerId && game.winnerId === state.winnerId) {\n state = { ...state, myRevealSent: game.myRevealSent, opponentReveal: game.opponentReveal, verification: game.verification };\n }\n return state;\n}\n\n/** Whether a not-yet-acknowledged own event is already contained in a public history. */\nexport function logCovers(data, event) {\n if (!data || !event) return false;\n const entry = data.log?.[(event.data?.ply ?? 0) - 1];\n switch (event.type) {\n case 'game_accept': return data.accept_event_id === event.event_id;\n case 'bs_commit': return (data.commits ?? []).includes(event.data.commitment);\n case 'bs_fire': return Boolean(entry && entry[0] === event.data.row && entry[1] === event.data.col);\n case 'bs_result': return Boolean(entry && entry.length > 2 && entry[0] === event.data.row && entry[1] === event.data.col);\n default: return false;\n }\n}\n\n/** Ids implied by an adopted history count as seen, so late copies are not forks. */\nexport function withLogSeen(seen, game) {\n const next = { ...seen };\n if (game.acceptEventId) next[game.acceptEventId] = true;\n if (game.lastEventId) next[game.lastEventId] = true;\n return next;\n}\n","// Private fleet + salt of the local player, needed to answer shots and reveal at\n// the end after a reload. Never sent to the opponent before the game ends.\nconst PREFIX = 'lira:bs:';\nconst MAX_AGE_MS = 14 * 24 * 60 * 60 * 1000;\nconst keyOf = (scope, gameId) => `${PREFIX}${scope}:${gameId}`;\nconst storage = () => {\n try {\n return globalThis.localStorage ?? null;\n } catch {\n return null;\n }\n};\n\nfunction isSecret(value) {\n return value !== null && typeof value === 'object' && Array.isArray(value.fleet) && value.fleet.length === 5\n && typeof value.salt === 'string' && /^[0-9a-f]{32}$/.test(value.salt)\n && typeof value.commitment === 'string' && /^[0-9a-f]{64}$/.test(value.commitment);\n}\n\nfunction prune(store) {\n const now = Date.now();\n for (let index = store.length - 1; index >= 0; index -= 1) {\n const key = store.key(index);\n if (!key?.startsWith(PREFIX)) continue;\n try {\n const value = JSON.parse(store.getItem(key));\n if (!isSecret(value) || !(now - value.savedAt < MAX_AGE_MS)) store.removeItem(key);\n } catch {\n store.removeItem(key);\n }\n }\n}\n\n/** Saves { fleet (reveal format), salt, commitment }. Returns false when storage is unavailable. */\nexport function saveFleet(scope, gameId, { fleet, salt, commitment }) {\n try {\n const store = storage();\n if (!store) return false;\n prune(store);\n store.setItem(keyOf(scope, gameId), JSON.stringify({ fleet, salt, commitment, savedAt: Date.now() }));\n return true;\n } catch {\n return false;\n }\n}\n\n/** { fleet, salt, commitment } or null. */\nexport function loadFleet(scope, gameId) {\n try {\n const value = JSON.parse(storage()?.getItem(keyOf(scope, gameId)) ?? 'null');\n return isSecret(value) ? { fleet: value.fleet, salt: value.salt, commitment: value.commitment } : null;\n } catch {\n return null;\n }\n}\n\nexport function clearFleet(scope, gameId) {\n try {\n storage()?.removeItem(keyOf(scope, gameId));\n } catch {\n // Storage unavailable: nothing to clear.\n }\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\nimport { parseGameMessage, encodeGameEvent, createGameEvent } from './protocol';\nimport { createBoard, dropPiece } from '../connect4/connect4';\nimport {\n createBattleshipGame, applyBattleshipEvent, placeFleetShip, removeFleetShip, randomizeFleet,\n toRevealFleet, isFleetReady, createSalt, computeCommitment, ownBoard, buildResult, verifyReveal,\n canFire, publicLog, compareLogs, mergeLogs, adoptLog, logCovers, withLogSeen,\n} from '../battleship/net/session';\nimport { saveFleet, loadFleet } from '../battleship/net/fleetStorage';\n\nconst GAME_TYPES = ['connect4', 'battleship'];\nconst gameTypeOf = (game) => game?.game ?? 'connect4';\nconst isBattleship = (game) => gameTypeOf(game) === 'battleship';\n// Automatic Battleship frames (bs_result, bs_reveal) run debounced after state\n// changes, so replayed or duplicated frames settle before anything is sent.\nconst BS_EFFECT_DELAY = 250;\nconst terminal = (game) => ['won', 'draw', 'closed', 'declined'].includes(game.status);\nconst keyFor = (scope, roomId, gameId) => JSON.stringify([scope, String(roomId), gameId]);\nconst retainGames = (games) => {\n const finished = Object.keys(games).filter((key) => terminal(games[key]));\n if (finished.length <= 80) return games;\n const next = { ...games };\n finished.slice(0, finished.length - 80).forEach((key) => { delete next[key]; });\n return next;\n};\n\nfunction applyEvent(game, event, author) {\n if (![game.hostId, game.guestId].includes(author)) return game;\n if (event.type === 'game_end' && event.data.reason === 'closed') {\n return ['closed', 'declined'].includes(game.status) ? game : { ...game, status: 'closed', closedBy: author, error: '' };\n }\n if (terminal(game) || game.status === 'conflict') return game;\n if (event.type === 'game_accept' || event.type === 'game_decline') {\n if (author !== game.guestId || game.status !== 'invited' || event.data.invite_event_id !== game.inviteEventId) return game;\n return { ...game, status: event.type === 'game_accept' ? 'active' : 'declined', lastEventId: event.event_id,\n acceptEventId: event.type === 'game_accept' ? event.event_id : game.acceptEventId };\n }\n if (event.type !== 'game_move') return game;\n const { ply, prev_event_id: previous, column } = event.data;\n const expectedAuthor = ply % 2 === 1 ? game.hostId : game.guestId;\n if (author !== expectedAuthor) return game;\n if (game.status !== 'active') return { ...game, status: 'conflict', error: 'Falta la aceptación de la partida. Ciérrala y vuelve a invitar.' };\n // An alternative event for an already-applied turn is a fork, not a replay.\n if (ply <= game.ply || ply > game.ply + 1 || previous !== game.lastEventId) {\n return { ...game, status: 'conflict', error: 'La partida perdió sincronización. Ciérrala y envía una nueva invitación.' };\n }\n if (author !== game.turnId) return game;\n const move = dropPiece(game.board, column, author);\n if (!move) return game;\n return {\n ...game, board: move.board, ply, lastEventId: event.event_id,\n moves: [...(game.moves ?? []), [column, event.event_id]],\n lastMove: { row: move.row, column, eventId: event.event_id },\n winnerId: move.winner || null,\n winningCells: move.winningCells,\n status: move.winner ? 'won' : move.draw ? 'draw' : 'active',\n turnId: author === game.hostId ? game.guestId : game.hostId,\n };\n}\n\nconst RESYNC_TIMEOUT = 8000;\nconst idleSync = { status: 'idle', requestId: null, requestedAt: 0, auto: false, outgoing: [], replies: [], offer: null, message: '' };\nconst isResync = (type) => ['game_resync_request', 'game_resync_state', 'bs_sync_request', 'bs_sync_state'].includes(type);\nconst historyOf = (game) => (game.acceptEventId\n ? { accept_event_id: game.acceptEventId, moves: game.moves ?? [], rev: (game.moves ?? []).length }\n : { moves: [], rev: 0 });\n\n// Replays a history from the invitation through the regular reducer, so a\n// resync can never produce a board, turn or result the move rules reject.\nfunction rebuild(game, acceptEventId, moves) {\n const base = { ...game, board: createBoard(), ply: 0, turnId: game.hostId, winnerId: null, winningCells: [],\n lastMove: null, moves: [], error: '' };\n if (!acceptEventId) return moves.length ? null : { ...base, status: 'invited', acceptEventId: null, lastEventId: game.inviteEventId };\n if (acceptEventId === game.inviteEventId) return null;\n let state = { ...base, status: 'active', acceptEventId, lastEventId: acceptEventId };\n const used = new Set([game.inviteEventId, acceptEventId]);\n for (let index = 0; index < moves.length; index += 1) {\n const [column, eventId] = moves[index];\n if (used.has(eventId)) return null;\n used.add(eventId);\n const author = index % 2 === 0 ? game.hostId : game.guestId;\n const next = applyEvent(state, { type: 'game_move', event_id: eventId, data: { column, ply: index + 1, prev_event_id: state.lastEventId } }, author);\n if (next.status === 'conflict' || next.ply !== index + 1 || next.lastEventId !== eventId) return null;\n state = next;\n }\n return state;\n}\n\n// equal | behind (remote extends local) | ahead (local extends remote) | diverged\nfunction compareHistories(local, remote) {\n if (local.acceptEventId && remote.acceptEventId && local.acceptEventId !== remote.acceptEventId) return 'diverged';\n const shared = Math.min(local.moves.length, remote.moves.length);\n for (let index = 0; index < shared; index += 1) {\n if (local.moves[index][0] !== remote.moves[index][0] || local.moves[index][1] !== remote.moves[index][1]) return 'diverged';\n }\n if (local.moves.length !== remote.moves.length) return local.moves.length < remote.moves.length ? 'behind' : 'ahead';\n if (local.acceptEventId && !remote.acceptEventId) return 'ahead';\n return !local.acceptEventId && remote.acceptEventId ? 'behind' : 'equal';\n}\n\nconst pendingMoveId = (game) => (game.pendingEvent?.type === 'game_move' && !game.pending ? game.pendingEvent.event_id : null);\n\n// Adopted history ids count as seen so late copies of those events are not forks.\nconst withHistorySeen = (seen, game) => {\n const next = { ...seen };\n if (game.acceptEventId) next[game.acceptEventId] = true;\n (game.moves ?? []).forEach((move) => { next[move[1]] = true; });\n return next;\n};\n\n// Per-game resync rules. Connect 4 keeps its original history/replay; Battleship\n// uses the public log from battleship/net/session.js.\nconst connect4Sync = {\n requestType: 'game_resync_request',\n stateType: 'game_resync_state',\n historyOf,\n rebuild: (game, data) => rebuild(game, data.accept_event_id ?? null, data.moves),\n compare: (game, data) => compareHistories({ acceptEventId: game.acceptEventId ?? null, moves: game.moves ?? [] },\n { acceptEventId: data.accept_event_id ?? null, moves: data.moves }),\n offerOf: (data) => ({ accept_event_id: data.accept_event_id ?? null, moves: data.moves }),\n covers: (game, data) => {\n const pendingId = pendingMoveId(game);\n return Boolean(pendingId && data.moves?.some((move) => move[1] === pendingId));\n },\n markSeen: withHistorySeen,\n merge: () => null,\n};\nconst createBattleshipSync = (secretFor) => ({\n requestType: 'bs_sync_request',\n stateType: 'bs_sync_state',\n historyOf: publicLog,\n rebuild: (game, data) => adoptLog(game, data, { stored: secretFor(game.scope, game.gameId) }),\n compare: (game, data) => compareLogs(publicLog(game), data),\n offerOf: (data) => ({ accept_event_id: data.accept_event_id, commits: data.commits, log: data.log, head: data.head }),\n covers: (game, data) => Boolean(game.pendingEvent && !game.pending && logCovers(data, game.pendingEvent)),\n markSeen: withLogSeen,\n merge: (game, data) => mergeLogs(publicLog(game), data),\n});\nconst resyncEvent = (game, type, data) => createGameEvent(type, { game_id: game.gameId, data, game: gameTypeOf(game) });\n\n// Each store instance owns its transport, timers and Battleship secrets.\nexport function createChatGamesStore() {\n let transport = null;\n // Battleship secrets created this session (fallback when localStorage is blocked).\n const secrets = new Map();\n const secretFor = (scope, gameId) => secrets.get(`${scope}:${gameId}`) ?? loadFleet(scope, gameId);\n const effectTimers = new Map();\n const verifying = new Set();\n // Bounded, short-lived inbox for frames delivered before their invitation.\n const earlyEvents = new Map();\n const resyncTimers = new Set();\n const battleshipSync = createBattleshipSync(secretFor);\n const syncFor = (game) => (isBattleship(game) ? battleshipSync : connect4Sync);\n\n return createStore((set, get) => ({\n games: {},\n configureTransport: (value) => { transport = value; },\n clear: () => {\n effectTimers.forEach((timer) => clearTimeout(timer));\n effectTimers.clear();\n resyncTimers.forEach((timer) => clearTimeout(timer));\n resyncTimers.clear();\n secrets.clear();\n verifying.clear();\n earlyEvents.clear();\n set({ games: {} });\n },\n markDisconnected: (scope) => set((state) => ({ games: Object.fromEntries(Object.entries(state.games).map(([key, game]) => [key,\n game.scope === scope && !terminal(game) ? { ...game, status: 'conflict', error: 'Conexión interrumpida. Se intentará resincronizar al reconectar.',\n sync: { ...idleSync, ...game.sync, status: 'idle', auto: false } } : game,\n ])) })),\n\n // Return true for protocol messages, including malformed ones, so they never\n // leak into ordinary bubbles or notifications.\n ingest: (message, scopeOrOptions, ownIdArgument) => {\n const options = typeof scopeOrOptions === 'object' ? scopeOrOptions : { scope: scopeOrOptions, currentUserId: ownIdArgument };\n const scope = options?.scope ?? transport?.getScope?.();\n const ownId = String(options?.currentUserId ?? transport?.getUserId?.() ?? '');\n const body = message.data ?? message.payload;\n const normalized = body && typeof body === 'object' ? { ...body, ...message } : message;\n const text = normalized.message ?? normalized.text;\n if (typeof text !== 'string' || !text.startsWith('LIRA_GAME_V1:')) return false;\n const event = parseGameMessage(text);\n const roomId = String(normalized.room_id ?? '');\n const author = String(normalized.user_id ?? '');\n if (!event || !scope || !ownId || !author || !roomId.startsWith('private_')) return true;\n const members = roomId.slice('private_'.length).split('_');\n if (members.length !== 2 || !members.includes(ownId) || !members.includes(author)) return true;\n const key = keyFor(scope, roomId, event.game_id);\n const game = get().games[key];\n // A game id never changes game type.\n if (game && gameTypeOf(game) !== event.game) return true;\n // Resync frames never wait in the early inbox: without a game there is nothing to repair.\n if (isResync(event.type)) {\n if (game && !game.seen[event.event_id]) get().handleResync(key, event, author, ownId);\n return true;\n }\n if (!game && event.type !== 'game_invite') {\n const now = Date.now();\n for (const [id, entry] of earlyEvents) {\n if (now - entry.at > 30000) earlyEvents.delete(id);\n }\n if (!earlyEvents.has(key) && earlyEvents.size >= 32) earlyEvents.delete(earlyEvents.keys().next().value);\n const entry = earlyEvents.get(key) ?? { at: now, messages: [] };\n if (entry.messages.length < 8 && !entry.messages.some((item) => item.eventId === event.event_id)) {\n entry.messages.push({ eventId: event.event_id, message: normalized });\n }\n earlyEvents.set(key, entry);\n return true;\n }\n if (game?.seen[event.event_id]) return true;\n let next = game;\n if (event.type === 'game_invite') {\n const guestId = event.data.opponent_id;\n if (game || guestId === author || !members.includes(guestId)) return true;\n if (event.game === 'battleship') {\n next = createBattleshipGame({\n key, gameId: event.game_id, game_id: event.game_id, scope, roomId, ownId, hostId: author, guestId,\n createdAt: normalized.timestamp ?? new Date().toISOString(),\n inviteEventId: event.event_id, lastEventId: event.event_id, seen: {}, sync: { ...idleSync },\n });\n } else next = {\n key, gameId: event.game_id, game_id: event.game_id, game: 'connect4', scope, roomId, ownId,\n hostId: author, guestId, turnId: author, status: 'invited',\n board: createBoard(), ply: 0, winnerId: null, lastMove: null,\n createdAt: normalized.timestamp ?? new Date().toISOString(),\n inviteEventId: event.event_id, lastEventId: event.event_id,\n seen: {}, pending: false, error: '', pendingEvent: null,\n acceptEventId: null, moves: [], sync: { ...idleSync },\n };\n } else if (isBattleship(game)) {\n const stored = event.type === 'bs_commit' && author === ownId ? secretFor(scope, event.game_id) : null;\n next = applyBattleshipEvent(game, event, author, { stored });\n } else if (game) next = applyEvent(game, event, author);\n if (!next) return true;\n // Invalid events cannot grow the replay set indefinitely.\n if (next === game) return true;\n next = { ...next, seen: { ...next.seen, [event.event_id]: true } };\n set((state) => {\n const games = { ...state.games, [key]: next };\n if (event.type === 'game_invite') {\n const competing = Object.values(games).filter((item) => item.scope === scope && item.roomId === roomId && !terminal(item));\n const winner = competing.sort((a, b) => a.gameId < b.gameId ? -1 : a.gameId > b.gameId ? 1 : 0)[0];\n competing.forEach((item) => {\n if (item.key !== winner?.key) games[item.key] = { ...item, status: 'closed', error: 'Se conserva la otra invitación de esta conversación.' };\n });\n }\n return { games: retainGames(games) };\n });\n if (next.status === 'conflict' && game?.status !== 'conflict') {\n queueMicrotask(() => { void get().requestResync(key, { auto: true }); });\n }\n if (isBattleship(next)) get().bsScheduleEffects(key);\n if (event.type === 'game_invite') {\n const queued = earlyEvents.get(key);\n earlyEvents.delete(key);\n if (queued && Date.now() - queued.at <= 30000) {\n queued.messages.forEach((item) => get().ingest(item.message, scope, ownId));\n }\n }\n return true;\n },\n\n invite: async ({ roomId, opponentId, gameType = 'connect4' }) => {\n if (!transport) throw new Error('Chat no disponible');\n if (!GAME_TYPES.includes(gameType)) throw new Error('Juego no disponible');\n const scope = transport.getScope();\n const ownId = String(transport.getUserId() ?? '');\n if (!ownId || !String(roomId).startsWith('private_')) throw new Error('Abre un chat privado para jugar.');\n if (Object.values(get().games).some((game) => game.scope === scope && game.roomId === String(roomId) && (!terminal(game) || game.pendingEvent))) {\n throw new Error('Cierra la partida actual antes de invitar.');\n }\n const event = createGameEvent('game_invite', { game_id: crypto.randomUUID(), data: { opponent_id: String(opponentId), rules_version: 1 }, game: gameType });\n return get().sendEvent(roomId, event);\n },\n\n act: async (key, type, data = {}) => {\n const game = get().games[key];\n const ownId = String(transport?.getUserId?.() ?? '');\n if (!game || game.scope !== transport?.getScope?.()) throw new Error('Partida no disponible');\n if (type !== 'game_end' && (game.pending || game.pendingEvent)) throw new Error('Reintenta el envío pendiente antes de continuar.');\n let eventData = data;\n if (type === 'game_accept' || type === 'game_decline') {\n if (game.status !== 'invited' || ownId !== game.guestId) return;\n eventData = { invite_event_id: game.inviteEventId };\n } else if (type === 'game_move') {\n if (isBattleship(game)) return;\n if (game.status !== 'active' || ownId !== game.turnId || !dropPiece(game.board, data.column, ownId)) return;\n eventData = { column: data.column, ply: game.ply + 1, prev_event_id: game.lastEventId };\n } else if (type === 'game_end') eventData = { reason: 'closed' };\n else return;\n return get().sendEvent(game.roomId, createGameEvent(type, { game_id: game.gameId, data: eventData, game: gameTypeOf(game) }));\n },\n\n // Battleship placement is local until bsReady sends only a commitment.\n bsUpdateLocal: (key, change) => {\n const game = get().games[key];\n if (!isBattleship(game)) return false;\n const next = change(game);\n if (next === game) return false;\n set((state) => (state.games[key] === game ? { games: { ...state.games, [key]: next } } : state));\n return get().games[key] === next;\n },\n bsPlaceShip: (key, placement) => get().bsUpdateLocal(key, (game) => placeFleetShip(game, placement)),\n bsRemoveShip: (key, shipId) => get().bsUpdateLocal(key, (game) => removeFleetShip(game, shipId)),\n bsRandomFleet: (key) => get().bsUpdateLocal(key, (game) => randomizeFleet(game)),\n bsReady: async (key) => {\n const game = get().games[key];\n if (!isBattleship(game) || game.status !== 'placement' || game.myReady) return;\n if (game.scope !== transport?.getScope?.()) throw new Error('Partida no disponible');\n if (game.pending || game.pendingEvent) throw new Error('Reintenta el envío pendiente antes de continuar.');\n const fleet = toRevealFleet(game.myFleet);\n if (!isFleetReady(fleet)) throw new Error('Coloca los cinco barcos antes de continuar.');\n const salt = createSalt();\n const commitment = await computeCommitment(fleet, salt);\n const current = get().games[key];\n // The fleet may have changed (or another ready won) while hashing.\n if (!current || current.myReady || current.status !== 'placement' || current.pending || current.pendingEvent\n || JSON.stringify(toRevealFleet(current.myFleet)) !== JSON.stringify(fleet)) return;\n secrets.set(`${game.scope}:${game.gameId}`, { fleet, salt, commitment });\n saveFleet(game.scope, game.gameId, { fleet, salt, commitment });\n return get().sendEvent(game.roomId, createGameEvent('bs_commit', { game_id: game.gameId, data: { commitment }, game: 'battleship' }));\n },\n bsFire: async (key, { row, col } = {}) => {\n const game = get().games[key];\n if (!isBattleship(game) || game.scope !== transport?.getScope?.()) throw new Error('Partida no disponible');\n if (game.pending || game.pendingEvent) throw new Error('Reintenta el envío pendiente antes de continuar.');\n if (!canFire(game) || game.targetShots[row]?.[col] !== null) return;\n return get().sendEvent(game.roomId, createGameEvent('bs_fire', {\n game_id: game.gameId, data: { ply: game.ply + 1, row, col, prev_event_id: game.lastEventId }, game: 'battleship',\n }));\n },\n bsScheduleEffects: (key) => {\n if (effectTimers.has(key)) return;\n effectTimers.set(key, setTimeout(() => {\n effectTimers.delete(key);\n get().bsRunEffects(key);\n }, BS_EFFECT_DELAY));\n },\n // Automatic frames: verification of the rival reveal, our bs_result for a\n // pending incoming shot, and our bs_reveal once the game is decided.\n bsRunEffects: (key) => {\n const game = get().games[key];\n if (!isBattleship(game) || !transport || game.scope !== transport.getScope?.()) return;\n if (game.opponentReveal && game.verification === 'pending' && !verifying.has(key)) {\n const reveal = game.opponentReveal;\n verifying.add(key);\n void verifyReveal(game, reveal).then((verification) => set((state) => {\n const current = state.games[key];\n if (!current || current.opponentReveal !== reveal || current.verification === verification) return state;\n return { games: { ...state.games, [key]: { ...current, verification } } };\n })).catch(() => {}).finally(() => { verifying.delete(key); });\n }\n if (game.pending || game.pendingEvent) return;\n const send = (type, data) => {\n void get().sendEvent(game.roomId, createGameEvent(type, { game_id: game.gameId, data, game: 'battleship' })).catch(() => {});\n };\n if (game.status === 'active' && game.pendingShot && game.pendingShot.by !== game.ownId) {\n const data = buildResult(ownBoard(game), game.pendingShot);\n if (data) send('bs_result', data);\n else if (!game.error) set((state) => ({ games: { ...state.games, [key]: { ...state.games[key], error: 'Tu flota no está disponible en este dispositivo; no se pueden responder disparos.' } } }));\n return;\n }\n const mayReveal = String(game.winnerId) !== String(game.ownId) || Boolean(game.opponentReveal);\n if (game.winnerId && ['won', 'closed'].includes(game.status) && !game.myRevealSent && mayReveal) {\n const fleet = toRevealFleet(game.myFleet);\n const salt = game.mySalt ?? secretFor(game.scope, game.gameId)?.salt;\n if (isFleetReady(fleet) && salt) send('bs_reveal', { fleet, salt });\n }\n },\n\n sendEvent: async (roomId, event) => {\n if (!transport) throw new Error('Chat no disponible');\n const sendingTransport = transport;\n const scope = sendingTransport.getScope();\n const ownId = String(sendingTransport.getUserId() ?? '');\n const key = keyFor(scope, roomId, event.game_id);\n const text = encodeGameEvent(event);\n get().ingest({ room_id: roomId, user_id: ownId, message: text }, scope, ownId);\n if (!get().games[key]?.seen[event.event_id]) throw new Error('Evento de partida inválido');\n const update = (patch, requireCurrent = true) => set((state) => {\n const game = state.games[key];\n if (!game || (requireCurrent && game.pendingEvent?.event_id !== event.event_id)) return state;\n return { games: { ...state.games, [key]: { ...game, ...patch } } };\n });\n update({ pending: true, pendingEvent: event, error: '' }, false);\n try {\n await sendingTransport.send(roomId, text);\n update({ pending: false, pendingEvent: null });\n if (event.game === 'battleship') get().bsScheduleEffects(key);\n } catch (error) {\n update({ pending: false, error: error.message || 'No se pudo enviar. Reintenta el mismo evento.' });\n throw error;\n }\n return key;\n },\n // The host is the initial source of truth. Histories are only adopted after a\n // full replay; a fork is never overwritten without the player's consent.\n handleResync: (key, event, author, ownId) => {\n const game = get().games[key];\n const adapter = syncFor(game);\n const seen = { ...game.seen, [event.event_id]: true };\n const put = (next) => {\n set((state) => ({ games: { ...state.games, [key]: next } }));\n if (isBattleship(next)) get().bsScheduleEffects(key);\n };\n if (author === ownId || ![game.hostId, game.guestId].includes(author) || ['closed', 'declined'].includes(game.status)) {\n put({ ...game, seen });\n return;\n }\n const sync = { ...idleSync, ...game.sync };\n if (![adapter.requestType, adapter.stateType].includes(event.type)) {\n put({ ...game, seen });\n return;\n }\n const isState = event.type === adapter.stateType;\n // Stale or unsolicited answers are dropped: they must reference one of our recent frames.\n if (isState && !sync.outgoing.includes(event.data.request_event_id)) {\n put({ ...game, seen });\n return;\n }\n const remote = adapter.rebuild(game, event.data);\n if (!remote) {\n put({ ...game, seen, sync: isState ? { ...sync, status: 'failed', message: 'El rival envió un estado de partida inválido.' } : sync });\n return;\n }\n const relation = adapter.compare(game, event.data);\n const resolved = { ...sync, status: 'ok', offer: null, auto: false, message: '' };\n let next;\n let reply = !isState;\n let deliversPending = false;\n const merged = relation === 'mixed' ? adapter.merge(game, event.data) : null;\n if (relation === 'equal' || relation === 'behind') {\n next = { ...remote, sync: resolved };\n if (adapter.covers(game, event.data)) next = { ...next, pendingEvent: null };\n } else if (merged) {\n // Independent pre-battle commits on both sides: keep the union and answer with it.\n const union = adapter.rebuild(game, merged);\n next = union ? { ...union, sync: resolved } : { ...game, sync: { ...sync, status: 'failed', message: 'No se pudo reconstruir la partida local.' } };\n reply = Boolean(union);\n deliversPending = Boolean(union);\n } else if (relation === 'ahead' || author === game.guestId) {\n // Our history is longer, or we are the host and keep ours on a fork.\n const own = adapter.rebuild(game, adapter.historyOf(game));\n next = own ? { ...own, sync: resolved } : { ...game, sync: { ...sync, status: 'failed', message: 'No se pudo reconstruir la partida local.' } };\n reply = Boolean(own);\n deliversPending = Boolean(own);\n } else {\n next = { ...game, status: 'conflict', error: 'El anfitrión tiene otra versión de la partida. Revísala antes de aceptarla.',\n sync: { ...sync, status: 'incompatible', offer: adapter.offerOf(event.data), message: '' } };\n }\n next = { ...next, seen: adapter.markSeen(seen, next) };\n const now = Date.now();\n const replies = next.sync.replies.filter((at) => now - at < 30000);\n let replyEvent = null;\n if (reply && replies.length < 6) {\n try {\n replyEvent = resyncEvent(game, adapter.stateType, { ...adapter.historyOf(next), request_event_id: event.event_id });\n } catch { replyEvent = null; }\n }\n if (replyEvent) {\n next = { ...next, seen: { ...next.seen, [replyEvent.event_id]: true },\n sync: { ...next.sync, replies: [...replies, now], outgoing: [...next.sync.outgoing, replyEvent.event_id].slice(-8) } };\n }\n put(next);\n if (!replyEvent) return;\n void get().sendResync(key, replyEvent).then(() => {\n if (!deliversPending) return;\n // The reply carried our unsent move, so its retry is no longer needed.\n set((state) => {\n const current = state.games[key];\n if (!current || !syncFor(current).covers(current, syncFor(current).historyOf(current))) return state;\n return { games: { ...state.games, [key]: { ...current, pendingEvent: null, error: '' } } };\n });\n if (isBattleship(get().games[key])) get().bsScheduleEffects(key);\n }).catch(() => {});\n },\n sendResync: async (key, event) => {\n const game = get().games[key];\n if (!transport || !game || game.scope !== transport.getScope?.()) throw new Error('Chat no disponible');\n await transport.send(game.roomId, encodeGameEvent(event));\n },\n requestResync: async (key, { auto = false } = {}) => {\n const game = get().games[key];\n if (!game || !transport || ['closed', 'declined'].includes(game.status) || game.scope !== transport.getScope?.()) return;\n const sync = { ...idleSync, ...game.sync };\n if ((sync.status === 'requesting' && Date.now() - sync.requestedAt < RESYNC_TIMEOUT) || (auto && sync.auto)) return;\n let event;\n try {\n event = resyncEvent(game, syncFor(game).requestType, syncFor(game).historyOf(game));\n } catch { return; }\n const fail = (message) => set((state) => {\n const current = state.games[key];\n if (current?.sync?.requestId !== event.event_id || current.sync.status !== 'requesting') return state;\n return { games: { ...state.games, [key]: { ...current, sync: { ...current.sync, status: 'failed', message } } } };\n });\n set((state) => {\n const current = state.games[key];\n if (!current) return state;\n return { games: { ...state.games, [key]: { ...current, seen: { ...current.seen, [event.event_id]: true },\n sync: { ...sync, status: 'requesting', requestId: event.event_id, requestedAt: Date.now(), auto: sync.auto || auto,\n message: '', outgoing: [...sync.outgoing, event.event_id].slice(-8) } } } };\n });\n const timer = setTimeout(() => {\n resyncTimers.delete(timer);\n fail('El rival no respondió a la sincronización. Reintenta cuando esté conectado.');\n }, RESYNC_TIMEOUT);\n resyncTimers.add(timer);\n try {\n await get().sendResync(key, event);\n } catch (error) {\n fail(error.message || 'No se pudo enviar la solicitud de sincronización.');\n }\n },\n adoptResyncOffer: (key) => {\n const game = get().games[key];\n const offer = game?.sync?.offer;\n if (!offer || game.sync.status !== 'incompatible') return false;\n const adapter = syncFor(game);\n const remote = adapter.rebuild(game, offer);\n set((state) => ({ games: { ...state.games, [key]: remote\n ? { ...remote, seen: adapter.markSeen(game.seen, remote), pending: false, pendingEvent: null, sync: { ...game.sync, status: 'ok', offer: null, auto: false, message: '' } }\n : { ...game, sync: { ...game.sync, status: 'failed', offer: null, message: 'El estado del anfitrión ya no es válido.' } } } }));\n if (remote && isBattleship(remote)) get().bsScheduleEffects(key);\n return Boolean(remote);\n },\n resyncConflicts: (scope) => {\n Object.values(get().games).filter((game) => game.scope === scope && game.status === 'conflict')\n .forEach((game) => { void get().requestResync(game.key, { auto: true }); });\n },\n retry: (key) => {\n const game = get().games[key];\n if (!game?.pendingEvent || game.pending) return Promise.resolve();\n if (game.scope !== transport?.getScope?.()) return Promise.reject(new Error('La sesión de esta partida ya no está activa.'));\n return get().sendEvent(game.roomId, game.pendingEvent);\n },\n }));\n}\n\n// Backward-compatible singleton: hook plus getState/setState/subscribe.\nexport const chatGamesStore = createChatGamesStore();\nexport const useChatGames = (selector) => useStore(chatGamesStore, selector);\nObject.assign(useChatGames, {\n getState: chatGamesStore.getState,\n setState: chatGamesStore.setState,\n subscribe: chatGamesStore.subscribe,\n});\n\nexport default useChatGames;\n","// Base URL for chat static assets (sounds). The host app serves them; by\n// default they live under `/sounds` in its public folder.\n//\n// Module-level state on purpose: this is a single host-level setting, set once\n// at bootstrap (before any sound plays) via setChatAssetsBaseUrl. URLs are\n// resolved lazily, so changing it later still affects subsequent loads.\nconst DEFAULT_BASE_URL = '/sounds';\nlet baseUrl = DEFAULT_BASE_URL;\n\nconst trimTrailingSlash = (url) => String(url).replace(/\\/+$/, '');\n\nexport function setChatAssetsBaseUrl(url) {\n baseUrl = url == null ? DEFAULT_BASE_URL : trimTrailingSlash(url);\n}\n\nexport function getChatAssetsBaseUrl() {\n return baseUrl;\n}\n\nexport function chatSoundUrl(relativePath) {\n return `${baseUrl}/${String(relativePath).replace(/^\\/+/, '')}`;\n}\n","import { useStore } from 'zustand';\nimport { createStore } from 'zustand/vanilla';\n\n// Transport-agnostic connection status for chat UI (host app syncs it).\nexport const chatConnectionStore = createStore(() => ({ status: 'idle' }));\n\nexport function setChatConnectionStatus(status) {\n chatConnectionStore.setState({ status });\n}\n\nexport function useChatConnectionStatus() {\n return useStore(chatConnectionStore, (state) => state.status);\n}\n","export const sameUser = (left, right) => left != null && right != null && String(left) === String(right);\nexport const isTerminalGame = (game) => ['won', 'draw', 'declined', 'closed'].includes(game?.status);\nexport const isLiveGame = (game) => Boolean(game) && (['invited', 'placement', 'active', 'conflict'].includes(game.status) || Boolean(game.pendingEvent));\nexport const isBattleshipGame = (game) => game?.game === 'battleship';\nexport const getGameTitle = (game) => (isBattleshipGame(game) ? 'Batalla Naval' : 'Conecta 4');\n\nconst VERIFICATION_LABELS = { ok: 'Partida verificada', mismatch: 'Resultados inconsistentes del rival', pending: 'Verificando…' };\nexport const getVerificationLabel = (game) => VERIFICATION_LABELS[game?.verification] || '';\n\nfunction getBattleshipStatus(game, currentUserId) {\n const myTurn = sameUser(currentUserId, game.turnId);\n if (game.status === 'placement') {\n if (!game.myReady) return 'Coloca tu flota';\n return game.opponentReady ? 'Iniciando batalla…' : 'Esperando a que el rival coloque su flota';\n }\n if (game.status === 'active') {\n if (game.pendingShot) return 'Esperando resultado…';\n return myTurn ? 'Tu turno · elige una casilla' : 'Turno del rival';\n }\n if (game.status === 'won') return sameUser(currentUserId, game.winnerId) ? '¡Ganaste!' : 'Tu rival ganó';\n return null;\n}\n\nexport function getGameStatus(game, currentUserId) {\n if (isBattleshipGame(game)) {\n const status = getBattleshipStatus(game, currentUserId);\n if (status) return status;\n }\n const myTurn = game.status === 'active' && sameUser(currentUserId, game.turnId);\n if (game.status === 'invited') return sameUser(currentUserId, game.guestId) ? 'Te han invitado a jugar' : 'Esperando respuesta a la invitación';\n if (game.status === 'active') return myTurn ? 'Tu turno · elige una columna' : 'Turno de tu rival';\n if (game.status === 'won') return sameUser(currentUserId, game.winnerId) ? '¡Ganaste la partida!' : 'Tu rival ganó la partida';\n if (game.status === 'draw') return 'Empate · tablero completo';\n if (game.status === 'declined') return 'Invitación rechazada';\n if (game.status === 'closed') return 'Partida finalizada';\n if (game.status === 'conflict') return 'Partida pausada por un conflicto de sincronización';\n return 'Esperando respuesta a la invitación';\n}\n\n// Short label for the minimized bar and the timeline placeholder.\nexport function getShortGameStatus(game, currentUserId) {\n if (isBattleshipGame(game)) {\n if (game.status === 'placement') return game.myReady ? 'Esperando al rival' : 'Coloca tu flota';\n if (game.status === 'active' && game.pendingShot) return 'Esperando resultado…';\n }\n if (game.status === 'active') return sameUser(currentUserId, game.turnId) ? 'Tu turno' : 'Turno del rival';\n if (game.status === 'invited') return sameUser(currentUserId, game.guestId) ? 'Invitación recibida' : 'Invitación enviada';\n if (game.status === 'conflict') return game.sync?.status === 'requesting' ? 'Sincronizando…' : 'Sin sincronizar';\n return getGameStatus(game, currentUserId);\n}\n","import { useSyncExternalStore } from 'react';\n\n// React binding for a sound manager's volume/mute settings.\nexport default function useSoundSettings(manager) {\n return useSyncExternalStore(manager.subscribe, manager.getSettings, manager.getSettings);\n}\n","/* eslint-disable react/prop-types */\nimport { Volume2, VolumeX } from 'lucide-react';\nimport useSoundSettings from '../../audio/useSoundSettings';\n\nexport default function GameSoundControls({ manager }) {\n const { volume, muted } = useSoundSettings(manager);\n const silent = muted || volume === 0;\n return (\n <div className=\"chat-game-sound\">\n <button type=\"button\" className=\"chat-game-sound-toggle\" onClick={manager.toggleMuted}\n aria-pressed={silent} aria-label={silent ? 'Activar sonido del juego' : 'Silenciar sonido del juego'} title={silent ? 'Activar sonido' : 'Silenciar'}>\n {silent ? <VolumeX size={15} /> : <Volume2 size={15} />}\n </button>\n <input type=\"range\" min=\"0\" max=\"100\" step=\"5\" value={Math.round((muted ? 0 : volume) * 100)}\n onChange={(event) => manager.setVolume(Number(event.target.value) / 100)} aria-label=\"Volumen del juego\" />\n </div>\n );\n}\n","// Reusable game sound manager built on Web Audio (no dependencies).\n// - Lazy: files are fetched on preload()/first play and decoded once.\n// - Autoplay-safe: the AudioContext is created/resumed only after a user\n// gesture; sounds requested before that are dropped, never queued.\n// - Fault-tolerant: a missing or undecodable file is marked unavailable and\n// every later play() of it is a silent no-op.\n// - Deduplicated: play(name, { key }) ignores keys already played recently.\n// - Optional per-sound levels, looped beds (startLoop/stopLoop) and settings\n// shared with another manager (settingsFrom) so games keep one preference.\n// - Side-effect free at creation (SSR-safe): gesture listeners and the\n// settingsFrom subscription are registered on start() or the first\n// preload()/play()/startLoop()/subscribe(); dispose() tears everything down.\n\nconst GESTURES = ['pointerdown', 'keydown', 'touchend'];\nconst MAX_KEYS = 300;\n// Sounds still loading when requested are dropped if they would play too late.\nconst MAX_LATENCY_MS = 800;\n\nconst clamp = (value) => Math.min(1, Math.max(0, Number(value) || 0));\n\nfunction readSettings(storageKey, defaults) {\n try {\n const stored = JSON.parse(localStorage.getItem(storageKey) ?? 'null');\n if (stored && typeof stored === 'object') {\n return { volume: clamp(stored.volume ?? defaults.volume), muted: Boolean(stored.muted) };\n }\n } catch { /* storage unavailable */ }\n return { volume: clamp(defaults.volume), muted: false };\n}\n\nconst LOOP_FADE_IN_S = 1.5;\nconst LOOP_FADE_OUT_S = 0.6;\n\nexport function createSoundManager({ id, baseUrl, sounds, levels = {}, defaultVolume = 0.6, settingsFrom = null }) {\n const storageKey = `lira.sound.${id}`;\n const AudioContextClass = typeof window !== 'undefined' ? (window.AudioContext || window.webkitAudioContext) : null;\n let settings = settingsFrom ? settingsFrom.getSettings() : readSettings(storageKey, { volume: defaultVolume });\n let context = null;\n let gain = null;\n let unlocked = false;\n const raw = new Map(); // name -> Promise<ArrayBuffer | null>\n const buffers = new Map(); // name -> Promise<AudioBuffer | null>\n const missing = new Set();\n const playedKeys = new Set();\n const listeners = new Set();\n const wantedLoops = new Set();\n const loops = new Map(); // name -> { source, level } once playing\n let started = false;\n let listening = false;\n let unsubscribeSettings = null;\n\n // baseUrl may be a function so hosts can configure asset locations after import.\n const urlFor = (name) => `${String(typeof baseUrl === 'function' ? baseUrl() : baseUrl).replace(/\\/$/, '')}/${sounds[name]}`;\n\n const fetchRaw = (name) => {\n if (!raw.has(name)) {\n raw.set(name, fetch(urlFor(name))\n .then((response) => (response.ok ? response.arrayBuffer() : null))\n .catch(() => null));\n }\n return raw.get(name);\n };\n\n const ensureContext = () => {\n if (!AudioContextClass) return null;\n if (!context) {\n try {\n context = new AudioContextClass();\n gain = context.createGain();\n gain.gain.value = settings.muted ? 0 : settings.volume;\n gain.connect(context.destination);\n } catch {\n context = null;\n return null;\n }\n }\n if (context.state === 'suspended') void context.resume().catch(() => {});\n return context;\n };\n\n const loadBuffer = (name) => {\n if (missing.has(name) || !sounds[name]) return Promise.resolve(null);\n if (!buffers.has(name)) {\n const ctx = ensureContext();\n if (!ctx) return Promise.resolve(null);\n buffers.set(name, fetchRaw(name).then((data) => {\n // decodeAudioData detaches the buffer, so decode a copy.\n if (!data) return null;\n return new Promise((resolve) => {\n ctx.decodeAudioData(data.slice(0), resolve, () => resolve(null));\n });\n }).then((buffer) => {\n if (!buffer) missing.add(name);\n return buffer;\n }).catch(() => {\n missing.add(name);\n return null;\n }));\n }\n return buffers.get(name);\n };\n\n const levelFor = (name) => clamp(levels[name] ?? 1);\n\n const beginLoop = (name) => {\n if (!wantedLoops.has(name) || loops.has(name) || !unlocked) return;\n const ctx = ensureContext();\n if (!ctx) return;\n const token = {}; // a stop/start while loading must not start a stale copy\n loops.set(name, token);\n void loadBuffer(name).then((buffer) => {\n if (loops.get(name) !== token) return;\n if (!buffer || ctx.state === 'closed') { loops.delete(name); return; }\n try {\n const level = ctx.createGain();\n level.gain.setValueAtTime(0, ctx.currentTime);\n level.gain.linearRampToValueAtTime(levelFor(name), ctx.currentTime + LOOP_FADE_IN_S);\n level.connect(gain);\n const source = ctx.createBufferSource();\n source.buffer = buffer;\n source.loop = true;\n source.connect(level);\n source.start();\n loops.set(name, { source, level });\n } catch {\n loops.delete(name);\n }\n });\n };\n\n const endLoop = (name) => {\n const loop = loops.get(name);\n loops.delete(name);\n if (!loop?.source || !context) return;\n try {\n const now = context.currentTime;\n loop.level.gain.cancelScheduledValues(now);\n loop.level.gain.setValueAtTime(loop.level.gain.value, now);\n loop.level.gain.linearRampToValueAtTime(0, now + LOOP_FADE_OUT_S);\n loop.source.stop(now + LOOP_FADE_OUT_S + 0.05);\n } catch { /* already stopped */ }\n };\n\n const unlock = () => {\n if (unlocked) return;\n unlocked = true;\n removeGestureListeners();\n if (ensureContext()) Object.keys(sounds).forEach((name) => { if (raw.has(name)) void loadBuffer(name); });\n wantedLoops.forEach(beginLoop);\n };\n\n function removeGestureListeners() {\n if (!listening) return;\n listening = false;\n GESTURES.forEach((type) => window.removeEventListener(type, unlock, true));\n }\n\n const remember = (key) => {\n if (playedKeys.has(key)) return false;\n playedKeys.add(key);\n if (playedKeys.size > MAX_KEYS) playedKeys.delete(playedKeys.values().next().value);\n return true;\n };\n\n const emit = () => listeners.forEach((listener) => listener());\n\n const applySettings = (next) => {\n settings = next;\n if (gain) gain.gain.value = settings.muted ? 0 : settings.volume;\n emit();\n };\n\n const setSettings = (patch) => {\n const next = { volume: clamp(patch.volume ?? settings.volume), muted: patch.muted ?? settings.muted };\n try { localStorage.setItem(storageKey, JSON.stringify(next)); } catch { /* storage unavailable */ }\n applySettings(next);\n };\n\n // Idempotent; registers the unlock listeners and the shared-settings link.\n const start = () => {\n if (started) return;\n started = true;\n if (settingsFrom) {\n settings = settingsFrom.getSettings();\n unsubscribeSettings = settingsFrom.subscribe(() => applySettings(settingsFrom.getSettings()));\n }\n if (typeof window === 'undefined' || unlocked) return;\n // Sticky activation: a gesture already happened before the manager started.\n if (typeof navigator !== 'undefined' && navigator.userActivation?.hasBeenActive) unlocked = true;\n else {\n listening = true;\n GESTURES.forEach((type) => window.addEventListener(type, unlock, { capture: true, passive: true }));\n }\n };\n\n // Removes listeners, unlinks settings, stops loops and closes the context.\n // A later start()/play() starts the manager again.\n const dispose = () => {\n removeGestureListeners();\n if (unsubscribeSettings) { unsubscribeSettings(); unsubscribeSettings = null; }\n started = false;\n wantedLoops.clear();\n loops.forEach((loop) => { try { loop?.source?.stop(); } catch { /* already stopped */ } });\n loops.clear();\n buffers.clear();\n const ctx = context;\n context = null;\n gain = null;\n if (ctx && ctx.state !== 'closed') void ctx.close().catch(() => {});\n };\n\n return {\n start,\n dispose,\n // Fetches files ahead of time without touching the AudioContext.\n preload(names = Object.keys(sounds)) {\n start();\n names.forEach((name) => {\n if (!sounds[name] || missing.has(name)) return;\n void fetchRaw(name);\n if (context) void loadBuffer(name);\n });\n },\n // Returns true when the sound was scheduled (not muted, unlocked, not a duplicate).\n play(name, { key } = {}) {\n start();\n if (key != null && !remember(`${name}:${key}`)) return false;\n if (!sounds[name] || missing.has(name) || !unlocked || settings.muted || settings.volume === 0) return false;\n const ctx = ensureContext();\n if (!ctx) return false;\n const requestedAt = Date.now();\n void loadBuffer(name).then((buffer) => {\n if (!buffer || ctx.state === 'closed' || Date.now() - requestedAt > MAX_LATENCY_MS) return;\n try {\n const source = ctx.createBufferSource();\n source.buffer = buffer;\n const level = levelFor(name);\n if (level === 1) source.connect(gain);\n else {\n const node = ctx.createGain();\n node.gain.value = level;\n source.connect(node);\n node.connect(gain);\n }\n source.start();\n } catch { /* the game must keep working without audio */ }\n });\n return true;\n },\n // Marks a key as handled without playing (e.g. replays that must stay silent).\n markPlayed(name, key) { remember(`${name}:${key}`); },\n // Looped bed through the master gain, so mute/volume apply live. Requested\n // before the first gesture it starts on unlock; stopLoop fades it out.\n startLoop(name) {\n start();\n if (!sounds[name] || missing.has(name)) return;\n wantedLoops.add(name);\n beginLoop(name);\n },\n stopLoop(name) {\n wantedLoops.delete(name);\n endLoop(name);\n },\n // Before start() a follower reads the shared settings directly.\n getSettings: () => (settingsFrom && !started ? settingsFrom.getSettings() : settings),\n setVolume: settingsFrom ? settingsFrom.setVolume : (volume) => setSettings({ volume, muted: clamp(volume) === 0 ? settings.muted : false }),\n setMuted: settingsFrom ? settingsFrom.setMuted : (muted) => setSettings({ muted: Boolean(muted) }),\n toggleMuted: settingsFrom ? settingsFrom.toggleMuted : () => setSettings({ muted: !settings.muted }),\n subscribe(listener) {\n start();\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n\nexport default createSoundManager;\n","import { createSoundManager } from '../../audio/createSoundManager';\nimport { chatSoundUrl } from '../../assets/chatAssets';\nimport useChatGames from '../shared/useChatGames';\n\nexport const connect4Sounds = createSoundManager({\n id: 'connect4',\n baseUrl: () => chatSoundUrl('connect4'), // resolved lazily at fetch time\n sounds: {\n invite: 'invite.ogg', start: 'start.ogg', drop: 'drop.ogg', turn: 'turn.ogg',\n win: 'win.ogg', lose: 'lose.ogg', draw: 'draw.ogg', close: 'close.ogg',\n },\n});\n\n// Keep in sync with .chat-game-piece--new in games.css.\nconst DROP_ANIMATION_MS = 360;\n// Gap between the piece landing and the follow-up cue (turn/win/lose/draw).\nconst FOLLOW_UP_MS = 140;\nconst pendingDrops = new Map(); // eventId -> { game, timer }\nconst followUps = new Set(); // outcome timers scheduled after a drop\nlet stopSounds = null;\n\nconst same = (left, right) => left != null && right != null && String(left) === String(right);\nconst reducedMotion = () => typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;\n\nfunction playMoveOutcome(game, eventId) {\n if (game.status === 'won') connect4Sounds.play(same(game.winnerId, game.ownId) ? 'win' : 'lose', { key: eventId });\n else if (game.status === 'draw') connect4Sounds.play('draw', { key: eventId });\n // turnId is the next player, so this only fires after the rival's move.\n else if (game.status === 'active' && same(game.turnId, game.ownId)) connect4Sounds.play('turn', { key: eventId });\n}\n\n// Called when the piece animation ends (or by the fallback timer when the card\n// is not on screen). Plays the impact, then the outcome of that move.\nexport function settleConnect4Drop(eventId) {\n const entry = pendingDrops.get(eventId);\n if (!entry) return;\n clearTimeout(entry.timer);\n pendingDrops.delete(eventId);\n connect4Sounds.play('drop', { key: eventId });\n const timer = setTimeout(() => {\n followUps.delete(timer);\n playMoveOutcome(entry.game, eventId);\n }, FOLLOW_UP_MS);\n followUps.add(timer);\n}\n\nfunction scheduleDrop(game) {\n const eventId = game.lastMove?.eventId;\n if (!eventId || pendingDrops.has(eventId)) return;\n const delay = reducedMotion() ? 0 : DROP_ANIMATION_MS + 80;\n pendingDrops.set(eventId, { game, timer: setTimeout(() => settleConnect4Drop(eventId), delay) });\n}\n\nfunction onGameChange(game, before) {\n if (!before) {\n if (game.status === 'invited' && same(game.guestId, game.ownId)) connect4Sounds.play('invite', { key: game.inviteEventId });\n return;\n }\n if (before.status === 'invited' && game.status === 'active') {\n connect4Sounds.play('start', { key: game.lastEventId });\n return;\n }\n if (game.ply > before.ply) {\n scheduleDrop(game);\n return;\n }\n // Competing invitations are closed locally without closedBy: stay silent.\n const ended = (game.status === 'closed' && game.closedBy != null) || game.status === 'declined';\n if (ended && before.status !== game.status) connect4Sounds.play('close', { key: game.gameId });\n}\n\n// Sounds derive from store transitions, so WebSocket replays already rejected\n// by the store (seen event_id) never reach here; keys guard the rest.\n// Idempotent: repeated calls return the same stop(), which unsubscribes and\n// clears pending timers.\n/** True when startConnect4Sounds() is active (someone else owns its stop()). */\nexport const isConnect4SoundsRunning = () => stopSounds != null;\n\nexport function startConnect4Sounds() {\n if (stopSounds) return stopSounds;\n connect4Sounds.start();\n const unsubscribe = useChatGames.subscribe((state, previous) => {\n if (state.games === previous.games) return;\n Object.entries(state.games).forEach(([key, game]) => {\n const before = previous.games[key];\n // Other games (e.g. Battleship) have their own cues.\n if (game.game && game.game !== 'connect4') return;\n if (game !== before && game.ownId != null) onGameChange(game, before);\n });\n });\n const stop = () => {\n if (stopSounds !== stop) return;\n stopSounds = null;\n unsubscribe();\n pendingDrops.forEach(({ timer }) => clearTimeout(timer));\n pendingDrops.clear();\n followUps.forEach(clearTimeout);\n followUps.clear();\n };\n stopSounds = stop;\n return stop;\n}\n"],"mappings":"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"}