@minicode-dev/chat 0.1.5 → 0.1.6
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.
- package/README.md +6 -2
- package/dist/chunks/{BattleshipGameCard-CW_A8Nim.js → BattleshipGameCard-S-UdM6rn.js} +100 -100
- package/dist/chunks/{BattleshipGameCard-CW_A8Nim.js.map → BattleshipGameCard-S-UdM6rn.js.map} +1 -1
- package/dist/chunks/{BattleshipPrototype-Duz-S1JE.js → BattleshipPrototype-Dm6U_mCr.js} +52 -52
- package/dist/chunks/{BattleshipPrototype-Duz-S1JE.js.map → BattleshipPrototype-Dm6U_mCr.js.map} +1 -1
- package/dist/chunks/{connect4Sounds-Do3nvVFx.js → connect4Sounds-9u0p-dAf.js} +7 -7
- package/dist/chunks/{connect4Sounds-Do3nvVFx.js.map → connect4Sounds-9u0p-dAf.js.map} +1 -1
- package/dist/index.js +3035 -2947
- package/dist/index.js.map +1 -1
- package/index.d.ts +2 -0
- package/package.json +1 -1
package/dist/chunks/{BattleshipPrototype-Duz-S1JE.js.map → BattleshipPrototype-Dm6U_mCr.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BattleshipPrototype-Duz-S1JE.js","names":["createBoard","isShipSunk","fireShot","placeShip","FLEET","hasWebGL","ROWS","SIZE","QUALITY_ORDER","QUALITY_LABEL","cellLabel","cell","sameCell","a","b","isCell","SHIP_NAMES","DOUBLE_SELECT_MS","randomFleet","board","ship","attempt","placed","targetView","pendingShipId","prefersReducedMotion","autoQuality","coarse","weakCpu","BattleshipPrototype","stageRef","useRef","sceneRef","toastTimer","hintId","useId","status","setStatus","useState","errorMessage","setErrorMessage","selected","setSelected","hovered","setHovered","radar","setRadar","quality","setQuality","stats","setStats","result","setResult","toastVisible","setToastVisible","boardRef","busyRef","lastSelectRef","fireRef","ready","useEffect","container","disposed","scene","createBattleScene","next","now","last","error","showResult","useCallback","label","text","extra","kind","fire","target","shot","prevShots","prev","select","toggleRadar","cycleQuality","resetGame","handleStageKeyDown","event","moves","dr","dc","base","handleRootKeyDown","onClose","accuracy","qualityLabel","compact","index","Waves","TriangleAlert","X","Crosshair","Radar","LocateFixed","Gauge","RotateCcw"],"sources":["../../src/games/battleship/BattleshipPrototype.jsx"],"sourcesContent":["/* eslint-disable react/prop-types */\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport { Crosshair, Gauge, LocateFixed, Radar, RotateCcw, TriangleAlert, Waves, X } from 'lucide-react';\nimport { FLEET, createBoard, fireShot, isShipSunk, placeShip } from './logic';\nimport { hasWebGL } from './webglSupport';\nimport './battleship.css';\n\nconst ROWS = 'ABCDEFGHIJ';\nconst SIZE = 10;\nconst QUALITY_ORDER = ['auto', 'high', 'low'];\nconst QUALITY_LABEL = { auto: 'Auto', high: 'Alta', low: 'Baja' };\n\nconst cellLabel = (cell) => (cell ? `${ROWS[cell.row]}${cell.col + 1}` : '—');\nconst sameCell = (a, b) => a === b || (a && b && a.row === b.row && a.col === b.col);\nconst isCell = (cell) => cell && Number.isInteger(cell.row) && Number.isInteger(cell.col);\nconst SHIP_NAMES = { carrier: 'portaaviones', battleship: 'acorazado', cruiser: 'crucero', submarine: 'submarino', destroyer: 'destructor' };\nconst DOUBLE_SELECT_MS = 400;\n\n// Local single-player demo: a random hidden enemy fleet resolved with the shared rules.\nfunction randomFleet() {\n let board = createBoard();\n for (const ship of FLEET) {\n for (let attempt = 0; attempt < 500; attempt += 1) {\n const placed = placeShip(board, {\n shipId: ship.id, orientation: Math.random() < 0.5 ? 'horizontal' : 'vertical',\n row: Math.floor(Math.random() * SIZE), col: Math.floor(Math.random() * SIZE),\n });\n if (placed.ok) { board = placed.board; break; }\n }\n }\n return board;\n}\n\n// `pendingShipId` keeps a just-sunk ship visible but afloat so the scene can sink it on impact.\nfunction targetView(board, interactive, pendingShipId = null) {\n return {\n mode: 'target',\n ships: board.ships\n .filter((ship) => ship.id === pendingShipId || isShipSunk(board, ship.id))\n .map((ship) => ({ ...ship, sunk: ship.id !== pendingShipId && isShipSunk(board, ship.id) })),\n shots: board.shots,\n preview: null,\n interactive,\n };\n}\n\nfunction prefersReducedMotion() {\n return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;\n}\n\n// \"Auto\" has no scene API of its own once running, so resolve it to a concrete level.\nfunction autoQuality() {\n const coarse = window.matchMedia?.('(pointer: coarse)').matches;\n const weakCpu = (navigator.hardwareConcurrency || 8) <= 4;\n return coarse || weakCpu ? 'low' : 'high';\n}\n\nexport default function BattleshipPrototype({ onClose, compact = false }) {\n const stageRef = useRef(null);\n const sceneRef = useRef(null);\n const toastTimer = useRef(null);\n const hintId = useId();\n const [status, setStatus] = useState('loading');\n const [errorMessage, setErrorMessage] = useState('');\n const [selected, setSelected] = useState(null);\n const [hovered, setHovered] = useState(null);\n const [radar, setRadar] = useState(false);\n const [quality, setQuality] = useState('auto');\n const [stats, setStats] = useState({ shots: 0, hits: 0 });\n const [result, setResult] = useState(null);\n const [toastVisible, setToastVisible] = useState(false);\n const boardRef = useRef(null);\n const busyRef = useRef(false);\n const lastSelectRef = useRef({ cell: null, time: 0 });\n const fireRef = useRef(null);\n const ready = status === 'ready';\n if (!boardRef.current) boardRef.current = randomFleet();\n\n useEffect(() => {\n const container = stageRef.current;\n if (!container) return undefined;\n if (!hasWebGL()) {\n setStatus('error');\n setErrorMessage('Tu navegador o dispositivo no tiene WebGL disponible, necesario para la vista 3D.');\n return undefined;\n }\n let disposed = false;\n let scene = null;\n import('./scene/createBattleScene.js')\n .then(({ createBattleScene }) => {\n // StrictMode mounts twice: a late resolve for an unmounted instance must not create a scene.\n if (disposed) return;\n scene = createBattleScene(container, {\n quality: 'auto',\n reducedMotion: prefersReducedMotion(),\n onCellHover: (cell) => { if (!disposed) setHovered(isCell(cell) ? { row: cell.row, col: cell.col } : null); },\n onCellSelect: (cell) => {\n if (disposed || !isCell(cell)) return;\n const next = { row: cell.row, col: cell.col };\n const now = Date.now();\n const last = lastSelectRef.current;\n lastSelectRef.current = { cell: next, time: now };\n if (sameCell(last.cell, next) && now - last.time < DOUBLE_SELECT_MS) { fireRef.current?.(next); return; }\n setSelected(next);\n scene?.selectCell(next);\n },\n });\n sceneRef.current = scene;\n scene.setView(targetView(boardRef.current, true));\n setStatus('ready');\n })\n .catch((error) => {\n if (disposed) return;\n console.error('[battleship] No se pudo iniciar la escena', error);\n setStatus('error');\n setErrorMessage('No se pudo iniciar la escena 3D. Inténtalo de nuevo más tarde.');\n });\n return () => {\n disposed = true;\n sceneRef.current = null;\n try { scene?.dispose(); } catch (error) { console.error('[battleship] Error al liberar la escena', error); }\n };\n }, []);\n\n useEffect(() => () => clearTimeout(toastTimer.current), []);\n\n const showResult = useCallback((kind, cell, extra) => {\n const label = cellLabel(cell);\n const text = extra || (kind === 'hit' ? `¡Impacto en ${label}!` : kind === 'miss' ? `Agua en ${label}` : `Ya disparaste en ${label}`);\n setResult({ kind, text, id: Date.now() });\n setToastVisible(true);\n clearTimeout(toastTimer.current);\n toastTimer.current = setTimeout(() => setToastVisible(false), 2800);\n }, []);\n\n const fire = useCallback((target = selected) => {\n const scene = sceneRef.current;\n if (!scene || !isCell(target) || busyRef.current) return;\n const shot = fireShot(boardRef.current, target);\n if (!shot.ok) { showResult(shot.reason === 'repeat_shot' ? 'repeat' : 'miss', target, shot.reason === 'battle_finished' ? 'Flota enemiga hundida · reinicia para jugar otra vez' : undefined); return; }\n const prevShots = boardRef.current.shots;\n boardRef.current = shot.board;\n busyRef.current = true;\n setSelected(null);\n scene.selectCell(null);\n setStats((prev) => ({ shots: prev.shots + 1, hits: prev.hits + (shot.result === 'hit' ? 1 : 0) }));\n const text = shot.defeated ? '¡Flota enemiga hundida!' : shot.sunk ? `¡Hundiste el ${SHIP_NAMES[shot.shipId] || 'barco'}!` : undefined;\n // Pre-impact view: newly sunk ship afloat and the new shot not yet marked.\n if (shot.sunk) scene.setView({ ...targetView(shot.board, false, shot.shipId), shots: prevShots });\n Promise.resolve(scene.playShot({ row: target.row, col: target.col, result: shot.result, sunk: shot.sunk, incoming: false }))\n .catch(() => {})\n .then(() => {\n busyRef.current = false;\n if (sceneRef.current !== scene) return;\n scene.setView(targetView(boardRef.current, !shot.defeated));\n showResult(shot.result, target, text);\n });\n }, [selected, showResult]);\n fireRef.current = fire;\n\n const select = useCallback((cell) => {\n setSelected(cell);\n sceneRef.current?.selectCell(cell);\n }, []);\n\n const toggleRadar = () => {\n const next = !radar;\n setRadar(next);\n sceneRef.current?.setRadarVisible(next);\n };\n\n const cycleQuality = () => {\n const next = QUALITY_ORDER[(QUALITY_ORDER.indexOf(quality) + 1) % QUALITY_ORDER.length];\n setQuality(next);\n sceneRef.current?.setQuality(next === 'auto' ? autoQuality() : next);\n };\n\n const resetGame = () => {\n boardRef.current = randomFleet();\n busyRef.current = false;\n sceneRef.current?.setView(targetView(boardRef.current, true));\n sceneRef.current?.selectCell(null);\n setSelected(null);\n setHovered(null);\n setStats({ shots: 0, hits: 0 });\n setResult(null);\n setToastVisible(false);\n stageRef.current?.focus();\n };\n\n const handleStageKeyDown = (event) => {\n if (!ready || event.target !== event.currentTarget || event.altKey || event.ctrlKey || event.metaKey) return;\n const moves = { ArrowUp: [-1, 0], ArrowDown: [1, 0], ArrowLeft: [0, -1], ArrowRight: [0, 1] };\n if (moves[event.key]) {\n event.preventDefault();\n const [dr, dc] = moves[event.key];\n const base = selected || hovered;\n const next = base\n ? { row: Math.min(SIZE - 1, Math.max(0, base.row + dr)), col: Math.min(SIZE - 1, Math.max(0, base.col + dc)) }\n : { row: 0, col: 0 };\n if (!sameCell(next, selected)) select(next);\n } else if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n fire();\n } else if (event.key === 'r' || event.key === 'R') {\n event.preventDefault();\n sceneRef.current?.resetCamera();\n }\n };\n\n const handleRootKeyDown = (event) => {\n if (event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault();\n event.stopPropagation();\n onClose?.();\n }\n };\n\n const accuracy = stats.shots ? Math.round((stats.hits / stats.shots) * 100) : 0;\n const qualityLabel = QUALITY_LABEL[quality];\n\n return (\n <section className={`bs-proto${compact ? ' bs-proto--compact' : ''}`} aria-label=\"Batalla Naval, vista previa 3D sin rival\" onKeyDown={handleRootKeyDown}>\n <div\n ref={stageRef}\n className=\"bs-proto__stage\"\n tabIndex={0}\n role=\"application\"\n aria-label=\"Tablero 3D de Batalla Naval. Flechas para mover la selección, Enter o Espacio para disparar, R para centrar la cámara, Escape para cerrar.\"\n aria-describedby={hintId}\n aria-busy={status === 'loading'}\n onKeyDown={handleStageKeyDown}\n />\n\n {status === 'loading' && (\n <div className=\"bs-proto__state\" role=\"status\">\n <div className=\"bs-proto__skeleton\" aria-hidden=\"true\">\n {Array.from({ length: 25 }, (_, index) => <span key={index} />)}\n </div>\n <p><Waves size={16} aria-hidden=\"true\" /> Preparando el océano…</p>\n </div>\n )}\n {status === 'error' && (\n <div className=\"bs-proto__state bs-proto__state--error\" role=\"alert\">\n <TriangleAlert size={28} aria-hidden=\"true\" />\n <strong>Vista 3D no disponible</strong>\n <p>{errorMessage}</p>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={onClose}>Volver al chat</button>\n </div>\n )}\n\n <header className=\"bs-proto__top\">\n <div className=\"bs-proto__panel bs-proto__brand\">\n <span className=\"bs-proto__title\">Batalla Naval <span className=\"bs-proto__title-sub\">· Sin rival</span></span>\n <span className=\"bs-proto__badge\">Vista previa 3D</span>\n </div>\n {ready && (\n <div className=\"bs-proto__panel bs-proto__info\">\n <dl className=\"bs-proto__cells\">\n <div><dt>Objetivo</dt><dd className=\"bs-proto__cell-selected\">{cellLabel(selected)}</dd></div>\n <div className=\"bs-proto__cells-hover\"><dt>Cursor</dt><dd>{cellLabel(hovered)}</dd></div>\n </dl>\n <dl className=\"bs-proto__stats\">\n <div><dt>Disparos</dt><dd>{stats.shots}</dd></div>\n <div><dt>Impactos</dt><dd>{stats.hits}</dd></div>\n <div><dt>Precisión</dt><dd>{accuracy}%</dd></div>\n </dl>\n </div>\n )}\n <button type=\"button\" className=\"bs-proto__icon-btn bs-proto__close\" onClick={onClose} aria-label=\"Cerrar Batalla Naval\" title=\"Cerrar (Esc)\">\n <X size={18} aria-hidden=\"true\" />\n </button>\n </header>\n\n <div className=\"bs-proto__live\" aria-live=\"polite\" aria-atomic=\"true\">\n {result && (\n <span key={result.id} className={`bs-proto__toast bs-proto__toast--${result.kind}${toastVisible ? ' is-visible' : ''}`}>\n {result.text}\n </span>\n )}\n </div>\n <span className=\"bs-proto__sr\" aria-live=\"polite\">{selected ? `Casilla seleccionada ${cellLabel(selected)}` : ''}</span>\n\n {ready && (\n <footer className=\"bs-proto__bottom\">\n <p id={hintId} className=\"bs-proto__hint\">Arrastra para rotar · Rueda/pellizco para zoom · Clic para apuntar · doble clic para disparar</p>\n <div className=\"bs-proto__panel bs-proto__actions\" role=\"toolbar\" aria-label=\"Acciones de Batalla Naval\">\n <button type=\"button\" className=\"bs-proto__btn bs-proto__btn--fire\" onClick={() => fire()} disabled={!selected}\n title={selected ? `Disparar en ${cellLabel(selected)} (Enter)` : 'Selecciona una casilla para disparar'}>\n <Crosshair size={18} aria-hidden=\"true\" /><span>Disparar</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={toggleRadar} aria-pressed={radar} title=\"Mostrar u ocultar radar\">\n <Radar size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Radar</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={() => sceneRef.current?.resetCamera()} title=\"Centrar cámara (R)\">\n <LocateFixed size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Centrar cámara</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={cycleQuality} aria-label={`Calidad: ${qualityLabel}. Cambiar calidad`} title=\"Cambiar calidad de render\">\n <Gauge size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Calidad: {qualityLabel}</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={resetGame} title=\"Reiniciar tablero\">\n <RotateCcw size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Reiniciar</span>\n </button>\n </div>\n </footer>\n )}\n {!ready && <p id={hintId} className=\"bs-proto__sr\">Arrastra para rotar · Rueda/pellizco para zoom · Clic para seleccionar</p>}\n </section>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BattleshipPrototype-Dm6U_mCr.js","names":["createBoard","isShipSunk","fireShot","placeShip","FLEET","hasWebGL","ROWS","SIZE","QUALITY_ORDER","QUALITY_LABEL","cellLabel","cell","sameCell","a","b","isCell","SHIP_NAMES","DOUBLE_SELECT_MS","randomFleet","board","ship","attempt","placed","targetView","pendingShipId","prefersReducedMotion","autoQuality","coarse","weakCpu","BattleshipPrototype","stageRef","useRef","sceneRef","toastTimer","hintId","useId","status","setStatus","useState","errorMessage","setErrorMessage","selected","setSelected","hovered","setHovered","radar","setRadar","quality","setQuality","stats","setStats","result","setResult","toastVisible","setToastVisible","boardRef","busyRef","lastSelectRef","fireRef","ready","useEffect","container","disposed","scene","createBattleScene","next","now","last","error","showResult","useCallback","label","text","extra","kind","fire","target","shot","prevShots","prev","select","toggleRadar","cycleQuality","resetGame","handleStageKeyDown","event","moves","dr","dc","base","handleRootKeyDown","onClose","accuracy","qualityLabel","compact","index","Waves","TriangleAlert","X","Crosshair","Radar","LocateFixed","Gauge","RotateCcw"],"sources":["../../src/games/battleship/BattleshipPrototype.jsx"],"sourcesContent":["/* eslint-disable react/prop-types */\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport { Crosshair, Gauge, LocateFixed, Radar, RotateCcw, TriangleAlert, Waves, X } from 'lucide-react';\nimport { FLEET, createBoard, fireShot, isShipSunk, placeShip } from './logic';\nimport { hasWebGL } from './webglSupport';\nimport './battleship.css';\n\nconst ROWS = 'ABCDEFGHIJ';\nconst SIZE = 10;\nconst QUALITY_ORDER = ['auto', 'high', 'low'];\nconst QUALITY_LABEL = { auto: 'Auto', high: 'Alta', low: 'Baja' };\n\nconst cellLabel = (cell) => (cell ? `${ROWS[cell.row]}${cell.col + 1}` : '—');\nconst sameCell = (a, b) => a === b || (a && b && a.row === b.row && a.col === b.col);\nconst isCell = (cell) => cell && Number.isInteger(cell.row) && Number.isInteger(cell.col);\nconst SHIP_NAMES = { carrier: 'portaaviones', battleship: 'acorazado', cruiser: 'crucero', submarine: 'submarino', destroyer: 'destructor' };\nconst DOUBLE_SELECT_MS = 400;\n\n// Local single-player demo: a random hidden enemy fleet resolved with the shared rules.\nfunction randomFleet() {\n let board = createBoard();\n for (const ship of FLEET) {\n for (let attempt = 0; attempt < 500; attempt += 1) {\n const placed = placeShip(board, {\n shipId: ship.id, orientation: Math.random() < 0.5 ? 'horizontal' : 'vertical',\n row: Math.floor(Math.random() * SIZE), col: Math.floor(Math.random() * SIZE),\n });\n if (placed.ok) { board = placed.board; break; }\n }\n }\n return board;\n}\n\n// `pendingShipId` keeps a just-sunk ship visible but afloat so the scene can sink it on impact.\nfunction targetView(board, interactive, pendingShipId = null) {\n return {\n mode: 'target',\n ships: board.ships\n .filter((ship) => ship.id === pendingShipId || isShipSunk(board, ship.id))\n .map((ship) => ({ ...ship, sunk: ship.id !== pendingShipId && isShipSunk(board, ship.id) })),\n shots: board.shots,\n preview: null,\n interactive,\n };\n}\n\nfunction prefersReducedMotion() {\n return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;\n}\n\n// \"Auto\" has no scene API of its own once running, so resolve it to a concrete level.\nfunction autoQuality() {\n const coarse = window.matchMedia?.('(pointer: coarse)').matches;\n const weakCpu = (navigator.hardwareConcurrency || 8) <= 4;\n return coarse || weakCpu ? 'low' : 'high';\n}\n\nexport default function BattleshipPrototype({ onClose, compact = false }) {\n const stageRef = useRef(null);\n const sceneRef = useRef(null);\n const toastTimer = useRef(null);\n const hintId = useId();\n const [status, setStatus] = useState('loading');\n const [errorMessage, setErrorMessage] = useState('');\n const [selected, setSelected] = useState(null);\n const [hovered, setHovered] = useState(null);\n const [radar, setRadar] = useState(false);\n const [quality, setQuality] = useState('auto');\n const [stats, setStats] = useState({ shots: 0, hits: 0 });\n const [result, setResult] = useState(null);\n const [toastVisible, setToastVisible] = useState(false);\n const boardRef = useRef(null);\n const busyRef = useRef(false);\n const lastSelectRef = useRef({ cell: null, time: 0 });\n const fireRef = useRef(null);\n const ready = status === 'ready';\n if (!boardRef.current) boardRef.current = randomFleet();\n\n useEffect(() => {\n const container = stageRef.current;\n if (!container) return undefined;\n if (!hasWebGL()) {\n setStatus('error');\n setErrorMessage('Tu navegador o dispositivo no tiene WebGL disponible, necesario para la vista 3D.');\n return undefined;\n }\n let disposed = false;\n let scene = null;\n import('./scene/createBattleScene.js')\n .then(({ createBattleScene }) => {\n // StrictMode mounts twice: a late resolve for an unmounted instance must not create a scene.\n if (disposed) return;\n scene = createBattleScene(container, {\n quality: 'auto',\n reducedMotion: prefersReducedMotion(),\n onCellHover: (cell) => { if (!disposed) setHovered(isCell(cell) ? { row: cell.row, col: cell.col } : null); },\n onCellSelect: (cell) => {\n if (disposed || !isCell(cell)) return;\n const next = { row: cell.row, col: cell.col };\n const now = Date.now();\n const last = lastSelectRef.current;\n lastSelectRef.current = { cell: next, time: now };\n if (sameCell(last.cell, next) && now - last.time < DOUBLE_SELECT_MS) { fireRef.current?.(next); return; }\n setSelected(next);\n scene?.selectCell(next);\n },\n });\n sceneRef.current = scene;\n scene.setView(targetView(boardRef.current, true));\n setStatus('ready');\n })\n .catch((error) => {\n if (disposed) return;\n console.error('[battleship] No se pudo iniciar la escena', error);\n setStatus('error');\n setErrorMessage('No se pudo iniciar la escena 3D. Inténtalo de nuevo más tarde.');\n });\n return () => {\n disposed = true;\n sceneRef.current = null;\n try { scene?.dispose(); } catch (error) { console.error('[battleship] Error al liberar la escena', error); }\n };\n }, []);\n\n useEffect(() => () => clearTimeout(toastTimer.current), []);\n\n const showResult = useCallback((kind, cell, extra) => {\n const label = cellLabel(cell);\n const text = extra || (kind === 'hit' ? `¡Impacto en ${label}!` : kind === 'miss' ? `Agua en ${label}` : `Ya disparaste en ${label}`);\n setResult({ kind, text, id: Date.now() });\n setToastVisible(true);\n clearTimeout(toastTimer.current);\n toastTimer.current = setTimeout(() => setToastVisible(false), 2800);\n }, []);\n\n const fire = useCallback((target = selected) => {\n const scene = sceneRef.current;\n if (!scene || !isCell(target) || busyRef.current) return;\n const shot = fireShot(boardRef.current, target);\n if (!shot.ok) { showResult(shot.reason === 'repeat_shot' ? 'repeat' : 'miss', target, shot.reason === 'battle_finished' ? 'Flota enemiga hundida · reinicia para jugar otra vez' : undefined); return; }\n const prevShots = boardRef.current.shots;\n boardRef.current = shot.board;\n busyRef.current = true;\n setSelected(null);\n scene.selectCell(null);\n setStats((prev) => ({ shots: prev.shots + 1, hits: prev.hits + (shot.result === 'hit' ? 1 : 0) }));\n const text = shot.defeated ? '¡Flota enemiga hundida!' : shot.sunk ? `¡Hundiste el ${SHIP_NAMES[shot.shipId] || 'barco'}!` : undefined;\n // Pre-impact view: newly sunk ship afloat and the new shot not yet marked.\n if (shot.sunk) scene.setView({ ...targetView(shot.board, false, shot.shipId), shots: prevShots });\n Promise.resolve(scene.playShot({ row: target.row, col: target.col, result: shot.result, sunk: shot.sunk, incoming: false }))\n .catch(() => {})\n .then(() => {\n busyRef.current = false;\n if (sceneRef.current !== scene) return;\n scene.setView(targetView(boardRef.current, !shot.defeated));\n showResult(shot.result, target, text);\n });\n }, [selected, showResult]);\n fireRef.current = fire;\n\n const select = useCallback((cell) => {\n setSelected(cell);\n sceneRef.current?.selectCell(cell);\n }, []);\n\n const toggleRadar = () => {\n const next = !radar;\n setRadar(next);\n sceneRef.current?.setRadarVisible(next);\n };\n\n const cycleQuality = () => {\n const next = QUALITY_ORDER[(QUALITY_ORDER.indexOf(quality) + 1) % QUALITY_ORDER.length];\n setQuality(next);\n sceneRef.current?.setQuality(next === 'auto' ? autoQuality() : next);\n };\n\n const resetGame = () => {\n boardRef.current = randomFleet();\n busyRef.current = false;\n sceneRef.current?.setView(targetView(boardRef.current, true));\n sceneRef.current?.selectCell(null);\n setSelected(null);\n setHovered(null);\n setStats({ shots: 0, hits: 0 });\n setResult(null);\n setToastVisible(false);\n stageRef.current?.focus();\n };\n\n const handleStageKeyDown = (event) => {\n if (!ready || event.target !== event.currentTarget || event.altKey || event.ctrlKey || event.metaKey) return;\n const moves = { ArrowUp: [-1, 0], ArrowDown: [1, 0], ArrowLeft: [0, -1], ArrowRight: [0, 1] };\n if (moves[event.key]) {\n event.preventDefault();\n const [dr, dc] = moves[event.key];\n const base = selected || hovered;\n const next = base\n ? { row: Math.min(SIZE - 1, Math.max(0, base.row + dr)), col: Math.min(SIZE - 1, Math.max(0, base.col + dc)) }\n : { row: 0, col: 0 };\n if (!sameCell(next, selected)) select(next);\n } else if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n fire();\n } else if (event.key === 'r' || event.key === 'R') {\n event.preventDefault();\n sceneRef.current?.resetCamera();\n }\n };\n\n const handleRootKeyDown = (event) => {\n if (event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault();\n event.stopPropagation();\n onClose?.();\n }\n };\n\n const accuracy = stats.shots ? Math.round((stats.hits / stats.shots) * 100) : 0;\n const qualityLabel = QUALITY_LABEL[quality];\n\n return (\n <section className={`bs-proto${compact ? ' bs-proto--compact' : ''}`} aria-label=\"Batalla Naval, vista previa 3D sin rival\" onKeyDown={handleRootKeyDown}>\n <div\n ref={stageRef}\n className=\"bs-proto__stage\"\n tabIndex={0}\n role=\"application\"\n aria-label=\"Tablero 3D de Batalla Naval. Flechas para mover la selección, Enter o Espacio para disparar, R para centrar la cámara, Escape para cerrar.\"\n aria-describedby={hintId}\n aria-busy={status === 'loading'}\n onKeyDown={handleStageKeyDown}\n />\n\n {status === 'loading' && (\n <div className=\"bs-proto__state\" role=\"status\">\n <div className=\"bs-proto__skeleton\" aria-hidden=\"true\">\n {Array.from({ length: 25 }, (_, index) => <span key={index} />)}\n </div>\n <p><Waves size={16} aria-hidden=\"true\" /> Preparando el océano…</p>\n </div>\n )}\n {status === 'error' && (\n <div className=\"bs-proto__state bs-proto__state--error\" role=\"alert\">\n <TriangleAlert size={28} aria-hidden=\"true\" />\n <strong>Vista 3D no disponible</strong>\n <p>{errorMessage}</p>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={onClose}>Volver al chat</button>\n </div>\n )}\n\n <header className=\"bs-proto__top\">\n <div className=\"bs-proto__panel bs-proto__brand\">\n <span className=\"bs-proto__title\">Batalla Naval <span className=\"bs-proto__title-sub\">· Sin rival</span></span>\n <span className=\"bs-proto__badge\">Vista previa 3D</span>\n </div>\n {ready && (\n <div className=\"bs-proto__panel bs-proto__info\">\n <dl className=\"bs-proto__cells\">\n <div><dt>Objetivo</dt><dd className=\"bs-proto__cell-selected\">{cellLabel(selected)}</dd></div>\n <div className=\"bs-proto__cells-hover\"><dt>Cursor</dt><dd>{cellLabel(hovered)}</dd></div>\n </dl>\n <dl className=\"bs-proto__stats\">\n <div><dt>Disparos</dt><dd>{stats.shots}</dd></div>\n <div><dt>Impactos</dt><dd>{stats.hits}</dd></div>\n <div><dt>Precisión</dt><dd>{accuracy}%</dd></div>\n </dl>\n </div>\n )}\n <button type=\"button\" className=\"bs-proto__icon-btn bs-proto__close\" onClick={onClose} aria-label=\"Cerrar Batalla Naval\" title=\"Cerrar (Esc)\">\n <X size={18} aria-hidden=\"true\" />\n </button>\n </header>\n\n <div className=\"bs-proto__live\" aria-live=\"polite\" aria-atomic=\"true\">\n {result && (\n <span key={result.id} className={`bs-proto__toast bs-proto__toast--${result.kind}${toastVisible ? ' is-visible' : ''}`}>\n {result.text}\n </span>\n )}\n </div>\n <span className=\"bs-proto__sr\" aria-live=\"polite\">{selected ? `Casilla seleccionada ${cellLabel(selected)}` : ''}</span>\n\n {ready && (\n <footer className=\"bs-proto__bottom\">\n <p id={hintId} className=\"bs-proto__hint\">Arrastra para rotar · Rueda/pellizco para zoom · Clic para apuntar · doble clic para disparar</p>\n <div className=\"bs-proto__panel bs-proto__actions\" role=\"toolbar\" aria-label=\"Acciones de Batalla Naval\">\n <button type=\"button\" className=\"bs-proto__btn bs-proto__btn--fire\" onClick={() => fire()} disabled={!selected}\n title={selected ? `Disparar en ${cellLabel(selected)} (Enter)` : 'Selecciona una casilla para disparar'}>\n <Crosshair size={18} aria-hidden=\"true\" /><span>Disparar</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={toggleRadar} aria-pressed={radar} title=\"Mostrar u ocultar radar\">\n <Radar size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Radar</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={() => sceneRef.current?.resetCamera()} title=\"Centrar cámara (R)\">\n <LocateFixed size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Centrar cámara</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={cycleQuality} aria-label={`Calidad: ${qualityLabel}. Cambiar calidad`} title=\"Cambiar calidad de render\">\n <Gauge size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Calidad: {qualityLabel}</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={resetGame} title=\"Reiniciar tablero\">\n <RotateCcw size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Reiniciar</span>\n </button>\n </div>\n </footer>\n )}\n {!ready && <p id={hintId} className=\"bs-proto__sr\">Arrastra para rotar · Rueda/pellizco para zoom · Clic para seleccionar</p>}\n </section>\n );\n}\n"],"mappings":"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"}
|
|
@@ -2,8 +2,8 @@ import { a as e, c as t, i as n, n as r, r as i, s as a, t as o } from "./battle
|
|
|
2
2
|
import { useSyncExternalStore as s } from "react";
|
|
3
3
|
import { createStore as c } from "zustand/vanilla";
|
|
4
4
|
import { useStore as l } from "zustand";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { Volume2 as u, VolumeX as d } from "lucide-react";
|
|
6
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
7
7
|
// src/games/shared/protocol.js
|
|
8
8
|
var m = "LIRA_GAME_V1:", h = 4096, g = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, _ = (e) => typeof e == "object" && !!e && !Array.isArray(e), v = (e) => typeof e == "string" && e.length > 0 && e.length <= 256 && e.trim() === e, y = (e) => typeof e == "string" && g.test(e), b = (e) => Array.isArray(e) && e.length <= 42 && e.every((e) => Array.isArray(e) && e.length === 2 && Number.isInteger(e[0]) && e[0] >= 0 && e[0] < 7 && y(e[1])) && new Set(e.map((e) => e[1])).size === e.length, x = (e) => b(e.moves) && e.rev === e.moves.length && (e.accept_event_id === void 0 ? e.moves.length === 0 : y(e.accept_event_id)), S = [
|
|
9
9
|
"carrier",
|
|
@@ -1621,17 +1621,17 @@ function Jt(e) {
|
|
|
1621
1621
|
// src/games/shared/GameSoundControls.jsx
|
|
1622
1622
|
function Yt({ manager: e }) {
|
|
1623
1623
|
let { volume: t, muted: n } = Jt(e), r = n || t === 0;
|
|
1624
|
-
return /* @__PURE__ */
|
|
1624
|
+
return /* @__PURE__ */ p("div", {
|
|
1625
1625
|
className: "chat-game-sound",
|
|
1626
|
-
children: [/* @__PURE__ */
|
|
1626
|
+
children: [/* @__PURE__ */ f("button", {
|
|
1627
1627
|
type: "button",
|
|
1628
1628
|
className: "chat-game-sound-toggle",
|
|
1629
1629
|
onClick: e.toggleMuted,
|
|
1630
1630
|
"aria-pressed": r,
|
|
1631
1631
|
"aria-label": r ? "Activar sonido del juego" : "Silenciar sonido del juego",
|
|
1632
1632
|
title: r ? "Activar sonido" : "Silenciar",
|
|
1633
|
-
children:
|
|
1634
|
-
}), /* @__PURE__ */
|
|
1633
|
+
children: f(r ? d : u, { size: 15 })
|
|
1634
|
+
}), /* @__PURE__ */ f("input", {
|
|
1635
1635
|
type: "range",
|
|
1636
1636
|
min: "0",
|
|
1637
1637
|
max: "100",
|
|
@@ -1844,4 +1844,4 @@ function fn() {
|
|
|
1844
1844
|
}
|
|
1845
1845
|
export { m as C, At as S, zt as _, nn as a, Pt as b, Ht as c, J as d, Vt as f, Rt as g, Lt as h, fn as i, qt as l, q as m, dn as n, Yt as o, Bt as p, cn as r, Kt as s, X as t, Wt as u, It as v, O as w, K as x, Ft as y };
|
|
1846
1846
|
|
|
1847
|
-
//# sourceMappingURL=connect4Sounds-
|
|
1847
|
+
//# sourceMappingURL=connect4Sounds-9u0p-dAf.js.map
|