@minicode-dev/chat 0.1.11 → 0.1.12

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.
@@ -1 +0,0 @@
1
- {"version":3,"file":"TanksLiveGameCard-BNJqWt1z.js","names":["_Fragment","useChatGames","GameSoundControls","decodeSignal","createPeerLink","encodeSignal","ChatContext","stopAllTanksLoops","startTanksSounds","handleSceneEvent","playOutcome","getTanksSoundManager","__defProp","__exportAll","target","name","all","no_symbols","connectionDiagnostics","net","connectionHint","RULES","clamp","lo","hi","n","angleDelta","b","a","createArena","x","z","r","i","createTank","id","index","validPosition","arena","radius","o","moveTank","tank","throttle","input","steer","dt","segmentCircle","dx","bx","ax","dz","bz","az","length","t","cx","cz","advanceShell","shell","first","tanks","interpolatePose","fraction","finite","idValid","createLiveMatch","selfId","game","ids","turnConfigured","iceServers","server","url","peerId","shells","events","time","sendAt","round","sequence","status","winner","destroyed","wasConnected","pendingResign","endReason","poses","lastPoseAt","lastPose","lastFire","seen","wantsRematch","me","other","notify","onChange","emit","send","link","e","remember","key","snapshot","reset","finish","force","fire","owner","shot","broadcast","receiveMove","data","yaw","turretYaw","speed","elapsed","previous","pose","receiveEvent","isHost","hp","validPlaying","validOver","maybeRematch","s","peerFactory","signaling","signal","text","scoped","frame","listener","previousPhase","state","resumed","next","dtMs","renderTime","remaining","hz","hit","out","RAD_TO_DEG","num","value","fallback","arenaBounds","withSize","w","d","box","arenaObstacles","eventKind","event","shooterOf","list","found","best","bestD","tankById","selfTank","damageLevel","alive","wrapAngle","v","createSelfTracker","last","moving","turning","moveIdle","turnIdle","hull","turret","isMoving","moveSpeed","turnSpeed","holdMs","isTurning","soundEventsFor","outcomeFor","render","createLiveScene2d","canvas","container","ctx","bounds","h","scale","ox","oz","resize","dpr","ro","nx","ny","obstacle","TanksLiveGameCard_exports","TanksLiveGameCard_default","act","type","stopInput","TanksLiveGameCard","rtcOptions","useContext","gameKey","suspendedRef","useRef","suspended","stage","match","renderer","view","setView","useState","error","setError","prefer2d","setPrefer2d","mode","setMode","active","setArena","useEffect","disposed","scene","options","createLiveScene","published","outcome","tracker","keys","session","currentUserId","clear","down","up","host","visibility","tick","now","paused","sound","nextOutcome","guest","over","aim","rect","ground","hold","field","onMinimize","onDismiss","Fragment","memo"],"sources":["../../src/games/tanks-live/net/connectionDiagnostics.js","../../src/games/tanks-live/logic/simulation.js","../../src/games/tanks-live/net/createLiveMatch.js","../../src/games/tanks-live/scene/liveView.js","../../src/games/tanks-live/scene/createLiveScene2d.js","../../src/games/tanks-live/TanksLiveGameCard.jsx"],"sourcesContent":["// Deliberately excludes SDP, ICE addresses, account IDs and TURN credentials.\nexport function connectionDiagnostics(net = {}) {\n return {\n phase: net.phase ?? 'idle', ice: net.ice ?? 'new',\n connection: net.connection ?? 'new', gathering: net.gathering ?? 'new',\n signaling: {\n sent: net.signals?.sent ?? 0, received: net.signals?.received ?? 0,\n sendFailures: net.signals?.sendFailures ?? 0,\n ignored: net.signals?.ignored ?? 0, invalid: net.signals?.invalid ?? 0,\n retransmits: net.signals?.retransmits ?? 0,\n },\n turnConfigured: Boolean(net.turnConfigured),\n route: net.route?.label ?? null,\n movesSent: net.move?.sent ?? 0, movesReceived: net.move?.received ?? 0,\n error: net.error ? (/^[a-z_]+$/.test(net.error) ? net.error : 'negotiation_error') : null,\n };\n}\n\nexport function connectionHint(net = {}) {\n if (net.phase === 'connected') return '';\n if (net.signals?.sendFailures) return 'No se pudieron enviar señales por el chat. Revisa la conexión WebSocket y reintenta.';\n if (net.ice === 'checking' || net.ice === 'failed') return net.turnConfigured\n ? 'WebRTC aún no encuentra una ruta entre los jugadores. Revisa el servicio TURN y la red.'\n : 'WebRTC aún no encuentra una ruta entre los jugadores. Algunas redes necesitan un servidor TURN; esta partida no tiene uno configurado.';\n if (net.phase === 'listening') return 'Esperando la conexión del rival. Ambos deben mantener abierta la partida y usar la misma versión del chat.';\n if (net.phase === 'failed') return 'No se pudo conectar. Revisa el diagnóstico de ambos jugadores y reintenta.';\n return 'Intercambiando señales de conexión por el chat. El combate empieza cuando conecta WebRTC.';\n}\n","// Deterministic arcade simulation. Angles are radians, forward is +x.\nexport const RULES = Object.freeze({ speed: 16, reverse: 9, turn: 1.8, acceleration: 28, radius: 2, reloadMs: 1500, shellSpeed: 60, damage: 25 });\nexport const clamp = (n, lo, hi) => Math.max(lo, Math.min(hi, n));\nexport const angleDelta = (a, b) => Math.atan2(Math.sin(b - a), Math.cos(b - a));\nexport function createArena() {\n return { size: 120, bounds: { minX: 0, maxX: 120, minZ: 0, maxZ: 120 }, obstacles: [\n [42, 35, 4], [78, 85, 4], [60, 30, 3], [60, 90, 3], [35, 65, 3], [85, 55, 3], [60, 60, 5],\n ].map(([x, z, r], i) => ({ x, z, r, kind: i % 2 ? 'tree' : 'rock' })) };\n}\nexport function createTank(id, index) { return { id: String(id), x: index ? 102 : 18, z: 60, yaw: index ? Math.PI : 0, turretYaw: index ? Math.PI : 0, speed: 0, hp: 100, alive: true, color: index ? '#d7463f' : '#54a34a' }; }\nexport function validPosition(x, z, arena, radius = RULES.radius) {\n const b = arena.bounds;\n return x >= b.minX + radius && x <= b.maxX - radius && z >= b.minZ + radius && z <= b.maxZ - radius\n && !arena.obstacles.some(o => Math.hypot(x - o.x, z - o.z) < o.r + radius);\n}\nexport function moveTank(tank, input, dt, arena) {\n if (!tank.alive) return;\n const throttle = clamp(Number(input.throttle) || 0, -1, 1), steer = clamp(Number(input.steer) || 0, -1, 1);\n const target = throttle * (throttle < 0 ? RULES.reverse : RULES.speed);\n tank.speed += clamp(target - tank.speed, -RULES.acceleration * dt, RULES.acceleration * dt);\n tank.yaw += steer * RULES.turn * dt;\n if (Number.isFinite(input.turretYaw)) tank.turretYaw = input.turretYaw;\n const x = tank.x + Math.cos(tank.yaw) * tank.speed * dt, z = tank.z + Math.sin(tank.yaw) * tank.speed * dt;\n if (validPosition(x, tank.z, arena)) tank.x = x; else tank.speed = 0;\n if (validPosition(tank.x, z, arena)) tank.z = z; else tank.speed = 0;\n}\nexport function segmentCircle(ax, az, bx, bz, cx, cz, radius) {\n const dx = bx - ax, dz = bz - az, length = dx * dx + dz * dz;\n const t = length ? clamp(((cx - ax) * dx + (cz - az) * dz) / length, 0, 1) : 0;\n return Math.hypot(ax + dx * t - cx, az + dz * t - cz) <= radius ? t : null;\n}\nexport function advanceShell(shell, dt, arena, tanks) {\n const x = shell.x + Math.cos(shell.yaw) * RULES.shellSpeed * dt, z = shell.z + Math.sin(shell.yaw) * RULES.shellSpeed * dt;\n let first = null;\n for (const o of arena.obstacles) { const t = segmentCircle(shell.x, shell.z, x, z, o.x, o.z, o.r); if (t !== null && (!first || t < first.t)) first = { t, kind: 'obstacle' }; }\n for (const tank of tanks) { if (!tank.alive || tank.id === shell.owner) continue; const t = segmentCircle(shell.x, shell.z, x, z, tank.x, tank.z, RULES.radius); if (t !== null && (!first || t < first.t)) first = { t, kind: 'tank', target: tank.id }; }\n if (first) { shell.x += (x - shell.x) * first.t; shell.z += (z - shell.z) * first.t; return first; }\n shell.x = x; shell.z = z; shell.age += dt;\n return !validPosition(x, z, { ...arena, obstacles: [] }, 0) || shell.age > 3 ? { kind: 'terrain' } : null;\n}\nexport function interpolatePose(a, b, fraction) {\n const t = clamp(fraction, 0, 1);\n return { ...b, x: a.x + (b.x - a.x) * t, z: a.z + (b.z - a.z) * t, yaw: a.yaw + angleDelta(a.yaw, b.yaw) * t, turretYaw: a.turretYaw + angleDelta(a.turretYaw, b.turretYaw) * t };\n}\n","import { decodeSignal, encodeSignal } from '../../../net/webrtc/protocol.js';\nimport { createPeerLink } from '../../../net/webrtc/createPeerLink.js';\nimport { RULES, createArena, createTank, moveTank, advanceShell, validPosition, interpolatePose } from '../logic/simulation.js';\n\nconst finite = n => typeof n === 'number' && Number.isFinite(n);\nconst idValid = id => typeof id === 'string' && id.length > 0 && id.length < 160;\nexport function createLiveMatch({ game, selfId, isHost = String(selfId) === String(game.hostId), signaling, onChange = () => {}, peerFactory = createPeerLink, iceServers, iceTransportPolicy, RTCPeerConnectionImpl } = {}) {\n selfId = String(selfId);\n const ids = [String(game.hostId), String(game.guestId)];\n if (!ids.includes(selfId) || ids[0] === ids[1]) throw new Error('Invalid live match players');\n const turnConfigured = (iceServers || []).some(server => [server.urls].flat().some(url => /^turns?:/i.test(String(url))));\n const peerId = ids.find(id => id !== selfId), arena = createArena();\n let tanks = ids.map(createTank), shells = [], events = [], input = {}, time = 0, sendAt = 0, round = 0, sequence = 0;\n let status = 'connecting', winner = null, destroyed = false, net = { phase: 'idle', rtt: null, route: null }, wasConnected = false, pendingResign = false, endReason = null;\n let poses = [], lastPoseAt = null, lastPose = null, lastFire = new Map(), seen = new Set(), wantsRematch = new Set();\n const me = () => tanks.find(t => t.id === selfId), other = () => tanks.find(t => t.id === peerId);\n const notify = () => { if (!destroyed) onChange({ status, winner, net }); };\n const emit = e => { events.push(e); if (events.length > 200) events.shift(); };\n const send = e => link.sendEvent({ ...e, g: game.gameId, r: round });\n const remember = key => { seen.add(key); if (seen.size > 2048) seen.delete(seen.values().next().value); };\n const snapshot = () => ({ k: 'snapshot', hp: tanks.map(t => t.hp), status, winner, reason: endReason });\n function reset() {\n tanks = ids.map(createTank); shells = []; poses = []; lastPoseAt = null; lastPose = null; lastFire.clear(); seen.clear(); wantsRematch.clear(); pendingResign = false; endReason = null; winner = null; status = net.phase === 'connected' ? 'playing' : 'connecting'; emit({ k: 'rematch' }); notify();\n }\n function finish(id, force = false) { if (status === 'over' && (!force || winner === id)) return; status = 'over'; winner = id; shells = []; emit({ k: 'over', winner }); notify(); }\n function fire(owner, e, broadcast) {\n if (status !== 'playing' || !idValid(e.id) || seen.has(e.id)) return false;\n const tank = tanks.find(t => t.id === owner);\n if (!tank?.alive || time - (lastFire.get(owner) ?? -Infinity) < RULES.reloadMs - 20) return false;\n if (![e.x, e.z, e.yaw].every(finite) || Math.hypot(e.x - (owner === peerId && lastPose ? lastPose.x : tank.x), e.z - (owner === peerId && lastPose ? lastPose.z : tank.z)) > 6) return false;\n remember(e.id);\n lastFire.set(owner, time);\n const shot = { ...e, k: 'fire', owner, x: e.x + Math.cos(e.yaw) * 2.8, z: e.z + Math.sin(e.yaw) * 2.8, y: 1.4, age: 0 };\n shells.push(shot); emit(shot); if (broadcast) send({ ...e, k: 'fire' }); return true;\n }\n function receiveMove(data) {\n if (destroyed || status !== 'playing' || data?.g !== game.gameId || data.r !== round || !Array.isArray(data.p) || data.p.length !== 5 || !data.p.every(finite)) return;\n const [x, z, yaw, turretYaw, speed] = data.p;\n if (!validPosition(x, z, arena) || Math.abs(speed) > RULES.speed + 0.1 || Math.abs(yaw) > 1e6 || Math.abs(turretYaw) > 1e6) return;\n const elapsed = lastPoseAt === null ? 0.1 : Math.max(0, (time - lastPoseAt) / 1000);\n const previous = lastPose || other();\n if (Math.hypot(x - previous.x, z - previous.z) > RULES.speed * elapsed + 3) return;\n const pose = { ...other(), x, z, yaw, turretYaw, speed };\n lastPose = pose; lastPoseAt = time; poses.push({ time, pose }); if (poses.length > 30) poses.shift();\n }\n function receiveEvent(e) {\n if (destroyed || !e || e.g !== game.gameId || !Number.isInteger(e.r)) return;\n if (e.k === 'round' && !isHost && status === 'over' && wantsRematch.has(selfId) && e.r === round + 1) { round = e.r; reset(); return; }\n if (e.r !== round) return;\n if (e.k === 'sync' && isHost) { send(snapshot()); return; }\n if (e.k === 'snapshot' && !isHost && Array.isArray(e.hp) && e.hp.length === 2 && e.hp.every(hp => Number.isInteger(hp) && hp >= 0 && hp <= 100)) {\n const validPlaying = e.status === 'playing' && e.winner === null && e.hp.every(hp => hp > 0);\n const validOver = e.status === 'over' && ids.includes(e.winner) && (e.hp[1 - ids.indexOf(e.winner)] === 0 || e.reason === 'resigned');\n if (!validPlaying && !validOver) return;\n tanks.forEach((t, i) => { t.hp = e.hp[i]; t.alive = t.hp > 0; });\n if (validOver) { pendingResign = false; endReason = e.reason; finish(e.winner, true); }\n return;\n }\n if (e.k === 'resign') { endReason = 'resigned'; finish(selfId, isHost); if (isHost) send(snapshot()); return; }\n if (e.k === 'rematch' && status === 'over') { wantsRematch.add(peerId); maybeRematch(); return; }\n if (status !== 'playing') return;\n if (e.k === 'fire') fire(peerId, e, false);\n if (!isHost && e.k === 'hit' && idValid(e.id) && !seen.has(`hit:${e.id}`) && ids.includes(e.target) && Array.isArray(e.hp) && e.hp.length === 2 && e.hp.every((hp, i) => Number.isInteger(hp) && hp >= 0 && hp <= tanks[i].hp) && [e.x, e.z].every(finite)) {\n remember(`hit:${e.id}`); tanks.forEach((tank, i) => { tank.hp = e.hp[i]; tank.alive = tank.hp > 0; }); shells = shells.filter(s => s.id !== e.id); emit(e);\n }\n if (!isHost && e.k === 'destroyed' && ids.includes(e.target) && !seen.has(`destroyed:${e.target}`) && tanks.find(t => t.id === e.target).hp === 0) { remember(`destroyed:${e.target}`); emit(e); }\n if (!isHost && e.k === 'over' && ids.includes(e.winner) && tanks.find(t => t.id !== e.winner).hp === 0) finish(e.winner);\n }\n // Scope negotiation itself: a finished card must never answer another game's hello.\n const scopedSignaling = signaling && {\n send(text) { const signal = decodeSignal(text); if (!signal) return Promise.reject(new Error('Invalid live signal')); const scoped = encodeSignal({ ...signal, liveGame: game.gameId }); return scoped ? signaling.send(scoped) : Promise.reject(new Error('Live signal too large')); },\n subscribe(listener) { return signaling.subscribe(frame => { const signal = decodeSignal(frame?.text); if (signal?.liveGame === game.gameId) listener(frame); }); },\n };\n const link = peerFactory({ signaling: scopedSignaling, selfId, peerId, roomId: game.roomId, iceServers, iceTransportPolicy, RTCPeerConnectionImpl, onMove: receiveMove, onEvent: receiveEvent, onChange(state) {\n const previousPhase = net.phase; net = state;\n if (state.phase === 'connected') { const resumed = wasConnected; wasConnected = true; if (status !== 'over') status = 'playing'; if (previousPhase !== 'connected') queueMicrotask(() => { if (!destroyed) { if (pendingResign) send({ k: 'resign' }); if (isHost && resumed) send(snapshot()); else if (!isHost) send({ k: 'sync' }); } }); }\n else if (status !== 'over') status = wasConnected ? 'disconnected' : 'connecting';\n notify();\n } });\n function maybeRematch() { if (isHost && wantsRematch.size === 2) { round++; send({ k: 'round' }); reset(); } }\n if (isHost) link.connect(); else link.setListening(true);\n return {\n setInput(next) { input = { ...next }; },\n step(dtMs) {\n if (destroyed) return;\n const elapsed = Math.max(0, Math.min(Number(dtMs) || 0, 100)); time += elapsed;\n if (status !== 'playing') return;\n const dt = elapsed / 1000;\n const renderTime = time - 100;\n while (poses.length > 1 && poses[1].time <= renderTime) poses.shift();\n if (poses.length) { const a = poses[0], b = poses[1] || a; const pose = interpolatePose(a.pose, b.pose, b.time === a.time ? 1 : (renderTime - a.time) / (b.time - a.time)); for (const key of ['x', 'z', 'yaw', 'turretYaw', 'speed']) other()[key] = pose[key]; }\n for (let remaining = dt; remaining > 0; remaining -= 0.016) moveTank(me(), input, Math.min(remaining, 0.016), arena);\n if (input.fire) fire(selfId, { id: `${selfId}:${round}:${++sequence}`, x: me().x, z: me().z, yaw: me().turretYaw, t: time }, true);\n const hz = net.rtt > 250 || net.move?.lossPct > 15 ? 10 : net.rtt > 100 ? 15 : 20;\n if (time >= sendAt) { sendAt = time + 1000 / hz; const t = me(); link.sendMove({ g: game.gameId, r: round, p: [t.x, t.z, t.yaw, t.turretYaw, t.speed], t: time }); }\n shells = shells.filter(shell => {\n const hit = advanceShell(shell, dt, arena, tanks);\n if (!hit) return true;\n if (isHost && hit.target && status === 'playing') {\n const tank = tanks.find(t => t.id === hit.target); tank.hp = Math.max(0, tank.hp - RULES.damage); tank.alive = tank.hp > 0;\n const e = { k: 'hit', id: shell.id, target: tank.id, dmg: RULES.damage, hp: tanks.map(t => t.hp), x: shell.x, z: shell.z }; send(e); emit(e);\n if (!tank.alive) { const e = { k: 'destroyed', target: tank.id }; send(e); emit(e); send({ k: 'over', winner: shell.owner }); finish(shell.owner); }\n } else emit({ k: 'impact', kind: hit.kind, x: shell.x, z: shell.z });\n return false;\n });\n },\n getRender() { const out = { arena, tanks: tanks.map(t => ({ ...t, self: t.id === selfId, reload: Math.min(1, (time - (lastFire.get(t.id) ?? -Infinity)) / RULES.reloadMs) })), shells: shells.map(s => ({ ...s })), events, status, winner, net: { ...net, turnConfigured } }; events = []; return out; },\n reconnect() { if (!destroyed && status !== 'over') link.connect(); },\n rematch() { if (!destroyed && status === 'over') { wantsRematch.add(selfId); send({ k: 'rematch' }); maybeRematch(); } },\n resign() { if (!destroyed && status !== 'over') { pendingResign = true; endReason = 'resigned'; send({ k: 'resign' }); finish(peerId); } },\n destroy() { if (destroyed) return; destroyed = true; link.destroy(); shells = []; poses = []; events = []; },\n };\n}\n","// Pure helpers shared by the live 3D/2D scenes and the card (no three, no DOM).\n// Render-state yaw is radians with forward = (cos yaw, sin yaw) on the x/z plane.\n\nexport const DEFAULT_ARENA_SIZE = 120;\nexport const RAD_TO_DEG = 180 / Math.PI;\n\nconst num = (value, fallback) => (Number.isFinite(value) ? value : fallback);\n\n/** Arena rectangle in world meters: explicit bounds, or `size` (corner origin unless `centered`). */\nexport function arenaBounds(arena) {\n const a = arena || {};\n const b = a.bounds || a;\n if (Number.isFinite(b.minX) && Number.isFinite(b.maxX) && Number.isFinite(b.minZ) && Number.isFinite(b.maxZ)) {\n return withSize({ minX: b.minX, minZ: b.minZ, maxX: b.maxX, maxZ: b.maxZ });\n }\n const w = num(a.width, num(a.size, DEFAULT_ARENA_SIZE));\n const d = num(a.depth, num(a.height, num(a.size, w)));\n const centered = a.centered === true || a.origin === 'center';\n return withSize(centered\n ? { minX: -w / 2, minZ: -d / 2, maxX: w / 2, maxZ: d / 2 }\n : { minX: 0, minZ: 0, maxX: w, maxZ: d });\n}\n\nfunction withSize(box) {\n return { ...box, width: box.maxX - box.minX, depth: box.maxZ - box.minZ, cx: (box.minX + box.maxX) / 2, cz: (box.minZ + box.maxZ) / 2 };\n}\n\n/** Circular obstacles [{ x, z, r, kind: 'tree'|'rock' }]. */\nexport function arenaObstacles(arena) {\n const list = arena?.obstacles || [];\n return list\n .filter((o) => Number.isFinite(o?.x) && Number.isFinite(o?.z))\n .map((o) => ({ x: o.x, z: o.z, r: num(o.r, num(o.radius, 1.5)), kind: o.kind === 'tree' ? 'tree' : 'rock' }));\n}\n\nexport const eventKind = (event) => (event ? event.k ?? event.type ?? null : null);\n\n/** Tank that fired: explicit owner field, else the tank nearest to the shot origin. */\nexport function shooterOf(event, tanks) {\n const list = tanks || [];\n const owner = event?.tank ?? event?.by ?? event?.owner ?? event?.from;\n if (owner != null) {\n const found = list.find((t) => String(t.id) === String(owner));\n if (found) return found;\n }\n if (!Number.isFinite(event?.x) || !Number.isFinite(event?.z)) return null;\n let best = null;\n let bestD = Infinity;\n for (const t of list) {\n const d = (t.x - event.x) ** 2 + (t.z - event.z) ** 2;\n if (d < bestD) { bestD = d; best = t; }\n }\n return best;\n}\n\nexport const tankById = (tanks, id) => (id == null ? null : (tanks || []).find((t) => String(t.id) === String(id)) || null);\nexport const selfTank = (tanks) => (tanks || []).find((t) => t.self) || null;\n\n/** 0 healthy, 1 smoking, 2 burning (also wrecks). */\nexport const damageLevel = (hp, alive = true) => (!alive || hp <= 25 ? 2 : hp <= 50 ? 1 : 0);\n\nexport const wrapAngle = (a) => {\n let v = a % (Math.PI * 2);\n if (v > Math.PI) v -= Math.PI * 2;\n if (v < -Math.PI) v += Math.PI * 2;\n return v;\n};\n\n/**\n * Tracks the own tank between frames to drive the engine/tracks/turret loops.\n * update(tank, dtMs) → scene-style sound events (move_start/move_end/turret_start/turret_end).\n */\nexport function createSelfTracker({ moveSpeed = 0.6, turnSpeed = 0.35, holdMs = 160 } = {}) {\n let last = null;\n let moving = false;\n let turning = false;\n let moveIdle = 0;\n let turnIdle = 0;\n return {\n update(tank, dtMs) {\n const out = [];\n if (!tank || tank.alive === false) {\n if (moving) out.push({ type: 'move_end' });\n if (turning) out.push({ type: 'turret_end' });\n moving = turning = false;\n last = null;\n return out;\n }\n const dt = Math.max(1, dtMs) / 1000;\n if (last) {\n const speed = Math.hypot(tank.x - last.x, tank.z - last.z) / dt;\n const hull = Math.abs(wrapAngle((tank.yaw ?? 0) - last.yaw)) / dt;\n const turret = Math.abs(wrapAngle((tank.turretYaw ?? 0) - (tank.yaw ?? 0) - last.rel)) / dt;\n const isMoving = speed > moveSpeed || hull > turnSpeed;\n moveIdle = isMoving ? 0 : moveIdle + dtMs;\n if (isMoving && !moving) { moving = true; out.push({ type: 'move_start' }); }\n else if (!isMoving && moving && moveIdle >= holdMs) { moving = false; out.push({ type: 'move_end' }); }\n const isTurning = turret > turnSpeed;\n turnIdle = isTurning ? 0 : turnIdle + dtMs;\n if (isTurning && !turning) { turning = true; out.push({ type: 'turret_start' }); }\n else if (!isTurning && turning && turnIdle >= holdMs) { turning = false; out.push({ type: 'turret_end' }); }\n }\n last = { x: tank.x, z: tank.z, yaw: tank.yaw ?? 0, rel: wrapAngle((tank.turretYaw ?? 0) - (tank.yaw ?? 0)) };\n return out;\n },\n reset() {\n last = null;\n moving = turning = false;\n moveIdle = turnIdle = 0;\n },\n get moving() { return moving; },\n get turning() { return turning; },\n };\n}\n\n/** Render events → scene-style sound events (sound/cues.js vocabulary). */\nexport function soundEventsFor(event) {\n switch (eventKind(event)) {\n case 'fire': return [{ type: 'fire' }, { type: 'projectile_start' }];\n case 'impact': return [{ type: 'impact', kind: event.kind === 'obstacle' ? 'obstacle' : 'terrain' }];\n case 'hit': return [{ type: 'tank_hit' }];\n case 'destroyed': return [{ type: 'destroyed' }];\n default: return [];\n }\n}\n\n/** 'victory' | 'defeat' | null for the own player once the match is over. */\nexport function outcomeFor(render) {\n if (!render || render.status !== 'over') return null;\n const me = selfTank(render.tanks);\n if (!me || render.winner == null) return null;\n return String(render.winner) === String(me.id) ? 'victory' : 'defeat';\n}\n\n/** Own reload progress 0..1 (1 = ready): the tank's own field when given, else from the last own fire. */\nexport function reloadProgress(tank, lastFireAt, now, reloadMs = 1500) {\n if (!tank) return 1;\n if (Number.isFinite(tank.reload)) return Math.max(0, Math.min(1, tank.reload));\n if (Number.isFinite(tank.reloadMs)) return Math.max(0, Math.min(1, 1 - tank.reloadMs / reloadMs));\n if (!Number.isFinite(lastFireAt)) return 1;\n return Math.max(0, Math.min(1, (now - lastFireAt) / reloadMs));\n}\n","import { arenaBounds, arenaObstacles } from './liveView.js';\n\n/** Lightweight top-down fallback, with the same render/picking lifecycle as WebGL. */\nexport function createLiveScene2d(container, { arena } = {}) {\n const canvas = document.createElement('canvas');\n canvas.style.cssText = 'width:100%;height:100%;display:block';\n container.appendChild(canvas);\n const ctx = canvas.getContext('2d');\n if (!ctx) { canvas.remove(); throw new Error('Canvas 2D unavailable'); }\n const bounds = arenaBounds(arena);\n let w = 1; let h = 1; let scale = 1; let ox = 0; let oz = 0;\n function resize() {\n w = Math.max(1, container.clientWidth); h = Math.max(1, container.clientHeight);\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n canvas.width = w * dpr; canvas.height = h * dpr;\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n scale = Math.min(w / bounds.width, h / bounds.depth);\n ox = (w - bounds.width * scale) / 2; oz = (h - bounds.depth * scale) / 2;\n }\n resize();\n const ro = typeof ResizeObserver === 'function' ? new ResizeObserver(resize) : null;\n ro?.observe(container);\n return {\n kind: '2d', resize,\n screenToGround(nx, ny) { return { x: ((nx + 1) * w / 2 - ox) / scale + bounds.minX, z: ((1 - ny) * h / 2 - oz) / scale + bounds.minZ }; },\n render(state) {\n ctx.fillStyle = '#152519'; ctx.fillRect(0, 0, w, h);\n ctx.save(); ctx.translate(ox, oz); ctx.scale(scale, scale); ctx.translate(-bounds.minX, -bounds.minZ);\n ctx.fillStyle = '#526348'; ctx.fillRect(bounds.minX, bounds.minZ, bounds.width, bounds.depth);\n for (const obstacle of arenaObstacles(arena)) { ctx.fillStyle = obstacle.kind === 'tree' ? '#24472d' : '#929285'; ctx.beginPath(); ctx.arc(obstacle.x, obstacle.z, obstacle.r, 0, Math.PI * 2); ctx.fill(); }\n for (const tank of state.tanks || []) {\n ctx.save(); ctx.translate(tank.x, tank.z); ctx.rotate(tank.yaw);\n ctx.fillStyle = tank.alive === false ? '#333' : tank.color || '#73ce68';\n ctx.fillRect(-3, -1.8, 6, 3.6); ctx.restore();\n ctx.save(); ctx.translate(tank.x, tank.z); ctx.rotate(tank.turretYaw); ctx.strokeStyle = '#dce8cf'; ctx.lineWidth = 0.8; ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(5, 0); ctx.stroke(); ctx.restore();\n if (tank.self) { ctx.strokeStyle = '#fff'; ctx.lineWidth = 0.3; ctx.beginPath(); ctx.arc(tank.x, tank.z, 4, 0, Math.PI * 2); ctx.stroke(); }\n }\n ctx.fillStyle = '#ffe097';\n for (const shell of state.shells || []) { ctx.beginPath(); ctx.arc(shell.x, shell.z, 0.7, 0, Math.PI * 2); ctx.fill(); }\n ctx.restore();\n },\n dispose() { ro?.disconnect(); canvas.remove(); },\n };\n}\n","/* eslint-disable react/prop-types */\nimport { memo, useContext, useEffect, useRef, useState } from 'react';\nimport { ChatContext } from '../../provider/ChatContext.js';\nimport useChatGames from '../shared/useChatGames.js';\nimport GameSoundControls from '../shared/GameSoundControls.jsx';\nimport { connectionDiagnostics, connectionHint } from './net/connectionDiagnostics.js';\nimport { createLiveMatch } from './net/createLiveMatch.js';\nimport { createLiveScene2d } from './scene/createLiveScene2d.js';\nimport { createSelfTracker, outcomeFor, selfTank, soundEventsFor } from './scene/liveView.js';\nimport { getTanksSoundManager, startTanksSounds, handleSceneEvent, playOutcome, stopAllTanksLoops } from '../tanks/sound/tanksSounds.js';\nimport '../connect4/games.css';\nimport './tanks-live.css';\n\nconst act = (key, type) => { void useChatGames.getState().act(key, type).catch(() => {}); };\nconst stopInput = (input) => { input.throttle = 0; input.steer = 0; input.fire = false; };\nfunction TanksLiveGameCard({ gameKey, currentUserId, onMinimize, onDismiss, suspended = false }) {\n const rtcOptions = useContext(ChatContext)?.config?.webrtc;\n const game = useChatGames((state) => state.games[gameKey]);\n const suspendedRef = useRef(suspended);\n suspendedRef.current = suspended;\n const stage = useRef(null); const match = useRef(null); const renderer = useRef(null);\n const input = useRef({ throttle: 0, steer: 0, fire: false });\n const [view, setView] = useState(null); const [error, setError] = useState(''); const [prefer2d, setPrefer2d] = useState(false);\n const [mode, setMode] = useState('loading');\n useEffect(() => {\n if (suspended) { stopInput(input.current); stopAllTanksLoops(); }\n else renderer.current?.resize();\n }, [suspended]);\n const active = ['active', 'won'].includes(game?.status);\n const [arena, setArena] = useState(null);\n useEffect(() => {\n if (!active || !arena || !stage.current) return undefined;\n let disposed = false; let scene = null;\n const options = { arena, lowPower: matchMedia('(pointer: coarse)').matches, reducedMotion: matchMedia('(prefers-reduced-motion: reduce)').matches, onEvent: (event) => { if (event.type === 'context_lost') setPrefer2d(true); } };\n const fallback = () => { if (!disposed) { scene = createLiveScene2d(stage.current, options); renderer.current = scene; setMode('2d'); } };\n if (prefer2d) fallback();\n else import('./scene/createLiveScene.js').then(({ createLiveScene }) => { if (!disposed) { try { scene = createLiveScene(stage.current, options); renderer.current = scene; setMode('3d'); } catch { fallback(); } } }).catch(fallback);\n return () => { disposed = true; scene?.dispose(); if (renderer.current === scene) renderer.current = null; };\n }, [active, arena, prefer2d]);\n useEffect(() => {\n if (!active || game.status !== 'active' || !stage.current) return undefined;\n let disposed = false; let frame = 0; let last = performance.now(); let published = 0; let outcome = null;\n const tracker = createSelfTracker(); const keys = new Set();\n startTanksSounds();\n let session;\n try {\n const signaling = useChatGames.getState().createLiveSignaling(gameKey);\n session = createLiveMatch({ iceServers: rtcOptions?.iceServers, iceTransportPolicy: rtcOptions?.iceTransportPolicy, game, selfId: String(currentUserId), isHost: String(game.hostId) === String(currentUserId), signaling });\n match.current = session;\n } catch (e) { setError(e.message || 'No se pudo iniciar WebRTC'); return undefined; }\n setArena(session.getRender().arena);\n function clear() { keys.clear(); stopInput(input.current); stopAllTanksLoops(); }\n function key(event, down) {\n if (/^(INPUT|TEXTAREA|SELECT)$/.test(event.target?.tagName)) return;\n if (!['KeyW', 'KeyA', 'KeyS', 'KeyD', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Space'].includes(event.code)) return;\n event.preventDefault(); if (down) keys.add(event.code); else keys.delete(event.code);\n input.current.throttle = Number(keys.has('KeyW') || keys.has('ArrowUp')) - Number(keys.has('KeyS') || keys.has('ArrowDown'));\n input.current.steer = Number(keys.has('KeyD') || keys.has('ArrowRight')) - Number(keys.has('KeyA') || keys.has('ArrowLeft'));\n input.current.fire = keys.has('Space');\n }\n const down = (e) => key(e, true); const up = (e) => key(e, false);\n const host = stage.current;\n host.addEventListener('keydown', down); host.addEventListener('keyup', up); host.addEventListener('blur', clear);\n const visibility = () => { if (document.hidden) clear(); };\n document.addEventListener('visibilitychange', visibility);\n handleSceneEvent({ type: 'engine_start' }, gameKey);\n function tick(now) {\n if (disposed) return;\n const dt = Math.min(80, now - last); last = now;\n const paused = suspendedRef.current || document.hidden;\n session.setInput(paused ? { throttle: 0, steer: 0, fire: false } : input.current);\n session.step(dt); const state = session.getRender();\n if (!paused) renderer.current?.render(state, dt);\n if (paused) { keys.clear(); tracker.reset(); stopAllTanksLoops(); }\n if (!paused) for (const event of state.events || []) for (const sound of soundEventsFor(event)) handleSceneEvent(sound, event.id);\n if (!paused) for (const event of tracker.update(selfTank(state.tanks), dt)) handleSceneEvent(event);\n const nextOutcome = outcomeFor(state);\n if (nextOutcome && !outcome) { setView(state); outcome = nextOutcome; if (!paused) playOutcome(outcome, gameKey); useChatGames.getState().liveFinish?.(gameKey, state.winner); }\n if (now - published > 100) { published = now; setView(state); }\n frame = requestAnimationFrame(tick);\n }\n frame = requestAnimationFrame(tick);\n return () => {\n disposed = true; cancelAnimationFrame(frame); clear(); session.destroy(); match.current = null;\n host.removeEventListener('keydown', down); host.removeEventListener('keyup', up); host.removeEventListener('blur', clear); document.removeEventListener('visibilitychange', visibility);\n };\n }, [active, gameKey, currentUserId]);\n if (!game) return null;\n const guest = String(currentUserId) === String(game.guestId);\n const over = view?.status === 'over' || game.status === 'won';\n function aim(event) {\n const rect = stage.current?.getBoundingClientRect(); const me = selfTank(view?.tanks);\n if (!rect || !me) return;\n const ground = renderer.current?.screenToGround((event.clientX - rect.left) / rect.width * 2 - 1, 1 - (event.clientY - rect.top) / rect.height * 2);\n if (ground) input.current.turretYaw = Math.atan2(ground.z - me.z, ground.x - me.x);\n }\n const hold = (field, value) => ({ onPointerDown: (e) => { e.preventDefault(); e.currentTarget.setPointerCapture(e.pointerId); input.current[field] = value; }, onPointerUp: () => { input.current[field] = field === 'fire' ? false : 0; }, onPointerCancel: () => { input.current[field] = field === 'fire' ? false : 0; }, onLostPointerCapture: () => { input.current[field] = field === 'fire' ? false : 0; } });\n return <section className={`chat-game-card tl-card${active ? ' tl-card--active' : ''}`} aria-label=\"Tanques LIVE 3D\">\n <header className=\"tl-header\"><strong>Tanques LIVE 3D</strong><div className=\"tl-header-actions\"><GameSoundControls manager={getTanksSoundManager()} />{onMinimize && <button onClick={onMinimize} aria-label=\"Minimizar\">−</button>}{onDismiss && <button onClick={onDismiss} aria-label=\"Ocultar\">×</button>}</div></header>\n {game.status === 'invited' && <div className=\"tl-invite\"><span className=\"tl-invite-icon\" aria-hidden=\"true\">🪖</span><strong>{guest ? '¿Listo para combatir?' : 'Invitación enviada'}</strong><p>{guest ? 'Te invitaron a un combate en tiempo real.' : 'Esperando que el rival acepte…'}</p>{guest && <div className=\"tl-invite-actions\"><button className=\"tl-button-primary\" onClick={() => act(gameKey, 'game_accept')}>Aceptar combate</button><button onClick={() => act(gameKey, 'game_decline')}>Rechazar</button></div>}</div>}\n {(active || view) && <><div className=\"tl-hud\">{(view?.tanks || []).map((tank) => <span key={tank.id}>{tank.self ? 'Tú' : 'Rival'} <meter min=\"0\" max=\"100\" value={tank.hp} aria-label={tank.self ? 'Tu vida' : 'Vida del rival'} /> {tank.hp} HP</span>)}<span role=\"status\">{view?.net?.phase || 'Conectando WebRTC…'} {view?.net?.route?.label || (typeof view?.net?.route === 'string' ? view.net.route : '')} {Number.isFinite(view?.net?.rtt) ? `${Math.round(view.net.rtt)} ms` : ''}</span></div>\n <div className=\"tl-stage\" ref={stage} tabIndex={0} aria-label=\"Arena. WASD o flechas para conducir, ratón para apuntar, clic o espacio para disparar\" onPointerMove={aim} onPointerDown={(e) => { aim(e); if (e.pointerType === 'mouse') { e.currentTarget.focus(); e.currentTarget.setPointerCapture(e.pointerId); aim(e); input.current.fire = true; } }} onPointerUp={() => { input.current.fire = false; }} onPointerCancel={() => { stopInput(input.current); }} onLostPointerCapture={() => { input.current.fire = false; }} />\n <div className=\"tl-controls\"><div className=\"tl-joystick\" role=\"group\" aria-label=\"Joystick de conducción\" onPointerDown={(e) => { e.preventDefault(); e.currentTarget.setPointerCapture(e.pointerId); const r = e.currentTarget.getBoundingClientRect(); input.current.steer = Math.max(-1, Math.min(1, (e.clientX - r.left - r.width / 2) / (r.width / 2))); input.current.throttle = Math.max(-1, Math.min(1, -(e.clientY - r.top - r.height / 2) / (r.height / 2))); }} onPointerMove={(e) => { if (!e.currentTarget.hasPointerCapture(e.pointerId)) return; const r = e.currentTarget.getBoundingClientRect(); input.current.steer = Math.max(-1, Math.min(1, (e.clientX - r.left - r.width / 2) / (r.width / 2))); input.current.throttle = Math.max(-1, Math.min(1, -(e.clientY - r.top - r.height / 2) / (r.height / 2))); }} onPointerUp={() => stopInput(input.current)} onPointerCancel={() => stopInput(input.current)} onLostPointerCapture={() => stopInput(input.current)}>✥</div><div className=\"tl-drive\" aria-label=\"Controles de conducción\"><button aria-label=\"Avanzar\" {...hold('throttle', 1)}>▲</button><button aria-label=\"Girar izquierda\" {...hold('steer', -1)}>◀</button><button aria-label=\"Retroceder\" {...hold('throttle', -1)}>▼</button><button aria-label=\"Girar derecha\" {...hold('steer', 1)}>▶</button></div><button className=\"tl-fire\" {...hold('fire', true)}>Disparar</button></div>\n <div className=\"tl-reload\"><label>Recarga <progress max=\"1\" value={selfTank(view?.tanks)?.reload ?? 1} /> {(selfTank(view?.tanks)?.reload ?? 1) >= 1 ? 'Listo' : 'Recargando…'}</label></div>\n <small>WASD / flechas · ratón o toca la arena para apuntar · espacio / clic para disparar</small><button onClick={() => setPrefer2d((v) => !v)}>{mode === '2d' ? 'Probar 3D' : 'Vista 2D'}</button>\n </>}\n {over && <p role=\"status\">{String(view?.winner ?? game.winnerId) === String(currentUserId) ? '¡Victoria!' : 'Fin del combate'} <button onClick={() => { void Promise.resolve(useChatGames.getState().liveRematch?.(gameKey)).catch(() => {}); }}>Revancha</button></p>}\n {active && !over && view?.net?.phase !== 'connected' && <div className=\"tl-connection\">\n <p role=\"status\">{connectionHint(view?.net)}</p>\n <button type=\"button\" onClick={() => match.current?.reconnect()}>Reintentar conexión</button>\n </div>}\n {active && <details className=\"tl-diagnostics\"><summary>Diagnóstico de conexión</summary><pre>{JSON.stringify(connectionDiagnostics(view?.net), null, 2)}</pre></details>}\n {active && !over && <button onClick={() => match.current?.resign()}>Rendirse</button>}\n {game.pending && <p role=\"status\">Enviando…</p>}{game.pendingEvent && game.error && <button onClick={() => { void useChatGames.getState().retry(gameKey).catch(() => {}); }}>Reintentar envío</button>}\n {error && <p role=\"alert\">{error}</p>}{game.error && <p role=\"alert\">{game.error}</p>}\n {!['closed', 'declined'].includes(game.status) && <footer className=\"tl-footer\"><button onClick={() => act(gameKey, 'game_end')}>Cerrar partida</button></footer>}\n </section>;\n}\nexport default memo(TanksLiveGameCard);\n"],"mappings":"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"}
@@ -1,480 +0,0 @@
1
- // src/net/webrtc/protocol.js
2
- var e = "LIRA_WEBRTC_V1:", t = 1e4, n = [
3
- "hello",
4
- "ready",
5
- "offer",
6
- "answer",
7
- "ice",
8
- "ack",
9
- "bye"
10
- ], r = /^[A-Za-z0-9_-]{4,64}$/, i = 32, a = (e) => typeof e == "string" && e.startsWith("LIRA_WEBRTC_V1:"), o = (e, t) => {
11
- if (t == null) return [
12
- "hello",
13
- "ready",
14
- "ack",
15
- "bye"
16
- ].includes(e);
17
- if (typeof t != "object" || Array.isArray(t)) return !1;
18
- switch (e) {
19
- case "offer":
20
- case "answer": return typeof t.sdp == "string" && t.sdp.length > 0;
21
- case "ice": return Array.isArray(t.c) && t.c.length <= i && t.c.every((e) => e === null || e && typeof e.candidate == "string");
22
- case "ack": return typeof t.of == "string" && r.test(t.of);
23
- default: return !0;
24
- }
25
- };
26
- function s(e) {
27
- return !!e && typeof e == "object" && e.v === 1 && n.includes(e.t) && typeof e.sid == "string" && r.test(e.sid) && typeof e.mid == "string" && r.test(e.mid) && typeof e.from == "string" && r.test(e.from) && (e.to == null || typeof e.to == "string" && r.test(e.to)) && Number.isInteger(e.gen ?? 0) && (e.gen ?? 0) >= 0 && (e.at == null || Number.isFinite(e.at)) && o(e.t, e.d);
28
- }
29
- function c(t) {
30
- let n = e + JSON.stringify({
31
- v: 1,
32
- ...t
33
- });
34
- return n.length <= 1e4 ? n : null;
35
- }
36
- function l(e) {
37
- if (!a(e) || e.length > 1e4) return null;
38
- try {
39
- let t = JSON.parse(e.slice(15));
40
- return s(t) ? t : null;
41
- } catch {
42
- return null;
43
- }
44
- }
45
- var u = () => {
46
- try {
47
- if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID().replace(/-/g, "").slice(0, 20);
48
- } catch {}
49
- return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 12)}`;
50
- }, d = [{ urls: ["stun:stun.l.google.com:19302", "stun:stun.cloudflare.com:3478"] }], f = 1200, p = 6, ee = 2e3, te = 3e4, ne = 80, m = 3e3, h = 2e4, g = 1e3, _ = 1e4, v = 2, re = 5, y = 16384, ie = 500, b = () => ({
51
- sent: 0,
52
- dropped: 0,
53
- received: 0,
54
- firstSeq: null,
55
- maxSeq: 0,
56
- outOfOrder: 0,
57
- lossPct: 0,
58
- hzIn: 0,
59
- hzOut: 0,
60
- windowIn: 0,
61
- windowOut: 0
62
- }), ae = {
63
- host: "directa (red local)",
64
- srflx: "directa (NAT vía STUN)",
65
- prflx: "directa (NAT)",
66
- relay: "TURN (relay)"
67
- };
68
- function x({ signaling: e, selfId: t, peerId: n, roomId: r = null, tabId: i = u(), iceServers: o = d, iceTransportPolicy: s = "all", autoReconnect: x = !0, listen: S = !0, RTCPeerConnectionImpl: C = globalThis.RTCPeerConnection, onChange: oe = () => {}, onMove: se = () => {}, onEvent: ce = () => {}, log: w = () => {} } = {}) {
69
- if (!e?.send || !e?.subscribe) throw Error("createPeerLink: signaling { send, subscribe } requerido");
70
- t = String(t), n = String(n);
71
- let T = S, E = !1, D = null, O = 0, k = null, A = null, j = /* @__PURE__ */ new Set(), M = {
72
- phase: "idle",
73
- role: null,
74
- sid: null,
75
- gen: 0,
76
- tabId: i,
77
- peerTab: null,
78
- ice: "new",
79
- connection: "new",
80
- signalingState: "stable",
81
- gathering: "new",
82
- route: null,
83
- rtt: null,
84
- statsRtt: null,
85
- reconnects: 0,
86
- restarts: 0,
87
- error: null,
88
- move: b(),
89
- signals: {
90
- sent: 0,
91
- received: 0,
92
- sendFailures: 0,
93
- retransmits: 0,
94
- duplicates: 0,
95
- ignored: 0,
96
- invalid: 0,
97
- tooLarge: 0,
98
- maxLength: 0
99
- },
100
- events: {
101
- sent: 0,
102
- received: 0
103
- }
104
- }, N = () => {
105
- E || oe(P());
106
- }, P = () => ({
107
- ...M,
108
- move: { ...M.move },
109
- signals: { ...M.signals },
110
- events: { ...M.events }
111
- }), F = (e, t = null) => {
112
- M.phase = e, M.error = t, w(`fase: ${e}${t ? ` (${t})` : ""}`), N();
113
- }, I = (t) => {
114
- let n = () => (E || (M.signals.sendFailures += 1, N()), !1);
115
- try {
116
- return Promise.resolve(e.send(t)).then((e) => e !== !1 || n(), n);
117
- } catch {
118
- return Promise.resolve(n());
119
- }
120
- }, L = (e, t, n, { to: r = e?.peerTab ?? null, reliable: a = !0, gen: o = e?.gen ?? 0, sid: s = e?.sid } = {}) => {
121
- let l = u(), d = c({
122
- t,
123
- sid: s,
124
- gen: o,
125
- mid: l,
126
- at: Date.now(),
127
- from: i,
128
- to: r,
129
- d: n ?? void 0
130
- });
131
- if (!d) return M.signals.tooLarge += 1, w(`señal ${t} supera el límite y no se envía`), e && U(e, "signal_too_large"), null;
132
- if (M.signals.sent += 1, M.signals.maxLength = Math.max(M.signals.maxLength, d.length), I(d), a && e) {
133
- let n = {
134
- text: d,
135
- tries: 1,
136
- timer: null
137
- }, r = () => {
138
- !e.closed && e.outbox.has(l) && (n.tries >= p ? (e.outbox.delete(l), w(`señal ${t} sin ACK tras ${p} intentos`), t !== "bye" && U(e, "signal_timeout")) : (n.tries += 1, M.signals.retransmits += 1, I(d), n.timer = setTimeout(r, f)));
139
- };
140
- n.timer = setTimeout(r, f), e.outbox.set(l, n);
141
- }
142
- return l;
143
- }, R = (e) => !j.has(e) && (j.add(e), j.size > ie && j.delete(j.values().next().value), !0), z = e.subscribe((e) => {
144
- if (E || !e || !a(e.text) || r != null && e.roomId && String(e.roomId) !== String(r)) return;
145
- let t = l(e.text);
146
- if (!t) M.signals.invalid += 1;
147
- else if (String(e.userId) !== n || t.from === i || t.to && t.to !== i) M.signals.ignored += 1;
148
- else if (M.signals.received += 1, t.t !== "hello" && t.t !== "ack" && L(null, "ack", { of: t.mid }, {
149
- to: t.from,
150
- reliable: !1,
151
- sid: t.sid,
152
- gen: t.gen
153
- }), !R(`${t.from}:${t.mid}`)) M.signals.duplicates += 1, N();
154
- else {
155
- switch (t.t) {
156
- case "ack":
157
- ge(t);
158
- break;
159
- case "hello":
160
- _e(t);
161
- break;
162
- case "ready":
163
- ve(t);
164
- break;
165
- case "offer":
166
- ye(t);
167
- break;
168
- case "answer":
169
- be(t);
170
- break;
171
- case "ice":
172
- xe(t);
173
- break;
174
- case "bye": Se(t);
175
- }
176
- D && t.sid === D.sid && t.from === D.peerTab && t.at && (D.peerAt = Math.max(D.peerAt, t.at));
177
- }
178
- }), B = (e, t = u(), n = null) => ({
179
- role: e,
180
- sid: t,
181
- peerTab: n,
182
- gen: 0,
183
- pc: null,
184
- move: null,
185
- events: null,
186
- closed: !1,
187
- outbox: /* @__PURE__ */ new Map(),
188
- pendingIce: [],
189
- localIce: [],
190
- iceTimer: null,
191
- helloTimer: null,
192
- helloStarted: Date.now(),
193
- disconnectTimer: null,
194
- connectTimer: null,
195
- pingTimer: null,
196
- statsTimer: null,
197
- tickTimer: null,
198
- lastSeen: Date.now(),
199
- pingSeq: 0,
200
- moveSeq: 0,
201
- restarts: 0,
202
- open: 0,
203
- peerAt: 0
204
- }), V = (e, { bye: t = !1 } = {}) => {
205
- if (e && !e.closed) {
206
- if (t && e.peerTab && L(e, "bye", null, { reliable: !1 }), e.closed = !0, [
207
- e.iceTimer,
208
- e.disconnectTimer,
209
- e.connectTimer
210
- ].forEach((e) => clearTimeout(e)), [
211
- e.helloTimer,
212
- e.pingTimer,
213
- e.statsTimer,
214
- e.tickTimer
215
- ].forEach((e) => clearInterval(e)), e.outbox.forEach((e) => clearTimeout(e.timer)), e.outbox.clear(), [e.move, e.events].forEach((e) => {
216
- if (e) {
217
- e.onopen = e.onclose = e.onmessage = e.onerror = null;
218
- try {
219
- e.close();
220
- } catch {}
221
- }
222
- }), e.pc) {
223
- e.pc.onicecandidate = e.pc.oniceconnectionstatechange = e.pc.onconnectionstatechange = null, e.pc.onsignalingstatechange = e.pc.onicegatheringstatechange = null;
224
- try {
225
- e.pc.close();
226
- } catch {}
227
- }
228
- D === e && (D = null);
229
- }
230
- }, H = (e) => {
231
- if (E || !x || k) return;
232
- if (O >= re) {
233
- F("failed", `${e}; sin más reintentos`);
234
- return;
235
- }
236
- let t = Math.min(8e3, 1e3 * 2 ** O);
237
- O += 1, M.reconnects = O, F("reconnecting", e), k = setTimeout(() => {
238
- k = null, !E && !D && $();
239
- }, t);
240
- }, U = (e, t) => {
241
- if (e.closed) return;
242
- let n = e.role === "caller";
243
- A = e.sid, V(e, { bye: !0 }), n ? H(t) : F(T ? "listening" : "idle", t);
244
- }, W = (e) => {
245
- M.role = e.role, M.sid = e.sid, M.gen = e.gen, M.peerTab = e.peerTab, M.ice = "new", M.connection = "new", M.signalingState = "stable", M.gathering = "new", M.route = null, M.rtt = null, M.statsRtt = null, M.restarts = 0, M.move = b();
246
- }, G = (e) => {
247
- if (!C) return U(e, "webrtc_unavailable"), null;
248
- let t = new C({
249
- iceServers: o,
250
- iceTransportPolicy: s
251
- });
252
- return e.pc = t, t.onicecandidate = ({ candidate: t }) => {
253
- e.closed || (e.localIce.push(t ? t.toJSON?.() ?? t : null), e.iceTimer || (e.iceTimer = setTimeout(() => le(e), ne)));
254
- }, t.onicegatheringstatechange = () => {
255
- M.gathering = t.iceGatheringState, N();
256
- }, t.onsignalingstatechange = () => {
257
- M.signalingState = t.signalingState, N();
258
- }, t.onconnectionstatechange = () => {
259
- M.connection = t.connectionState, N();
260
- }, t.oniceconnectionstatechange = () => ue(e), e.move = t.createDataChannel("move", {
261
- negotiated: !0,
262
- id: 0,
263
- ordered: !1,
264
- maxRetransmits: 0
265
- }), e.events = t.createDataChannel("events", {
266
- negotiated: !0,
267
- id: 1,
268
- ordered: !0
269
- }), [e.move, e.events].forEach((t) => {
270
- t.onopen = () => de(e), t.onclose = () => {
271
- !e.closed && M.phase === "connected" && X(e, "canal cerrado");
272
- };
273
- }), e.move.onmessage = (t) => me(e, t.data), e.events.onmessage = (t) => pe(e, t.data), e.connectTimer = setTimeout(() => {
274
- M.phase !== "connected" && U(e, "connect_timeout");
275
- }, h), t;
276
- }, le = (e) => {
277
- if (e.iceTimer = null, e.closed || !e.localIce.length) return;
278
- let t = e.localIce.splice(0, e.localIce.length);
279
- for (let n = 0; n < t.length; n += 16) L(e, "ice", { c: t.slice(n, n + 16) });
280
- }, K = async (e, t) => {
281
- for (let n of t) try {
282
- n && await e.pc.addIceCandidate(n);
283
- } catch (e) {
284
- w(`ICE remoto rechazado: ${e?.message ?? e}`);
285
- }
286
- }, q = (e) => {
287
- let t = e.pendingIce.filter((t) => t.gen === e.gen);
288
- e.pendingIce = e.pendingIce.filter((t) => t.gen > e.gen), t.forEach((t) => void K(e, t.c));
289
- }, J = async (e, t = !1) => {
290
- try {
291
- let n = await e.pc.createOffer(t ? { iceRestart: !0 } : void 0);
292
- if (e.closed || (await e.pc.setLocalDescription(n), e.closed)) return;
293
- L(e, "offer", { sdp: e.pc.localDescription.sdp });
294
- } catch (t) {
295
- U(e, `offer: ${t?.message ?? t}`);
296
- }
297
- }, Y = (e) => {
298
- e.closed || e.role !== "caller" || (e.restarts >= v ? X(e, "ICE no se recupera") : (e.restarts += 1, M.restarts = e.restarts, e.gen += 1, M.gen = e.gen, F("restarting"), J(e, !0)));
299
- }, ue = (e) => {
300
- if (e.closed) return;
301
- let t = e.pc.iceConnectionState;
302
- M.ice = t, clearTimeout(e.disconnectTimer), t === "connected" || t === "completed" ? (M.phase === "restarting" && F("connected"), Q(e)) : t === "disconnected" ? e.disconnectTimer = setTimeout(() => Y(e), m) : t === "failed" && Y(e), N();
303
- }, de = (e) => {
304
- e.open += 1, !(e.open < 2 || e.closed) && (clearTimeout(e.connectTimer), O = 0, e.lastSeen = Date.now(), e.pingTimer = setInterval(() => fe(e), g), e.statsTimer = setInterval(() => void Q(e), 2e3), e.tickTimer = setInterval(() => he(e), 1e3), F("connected"), Q(e));
305
- }, X = (e, t) => U(e, t), fe = (e) => {
306
- Date.now() - e.lastSeen > _ ? X(e, "sin latido del rival") : Z(e.events, JSON.stringify({
307
- k: "ping",
308
- n: ++e.pingSeq,
309
- ts: performance.now()
310
- }));
311
- }, Z = (e, t) => {
312
- if (e?.readyState !== "open") return !1;
313
- try {
314
- return e.send(t), !0;
315
- } catch {
316
- return !1;
317
- }
318
- }, pe = (e, t) => {
319
- e.lastSeen = Date.now();
320
- let n;
321
- try {
322
- n = JSON.parse(t);
323
- } catch {
324
- return;
325
- }
326
- n?.k === "ping" ? Z(e.events, JSON.stringify({
327
- k: "pong",
328
- ts: n.ts
329
- })) : n?.k === "pong" ? M.rtt = Math.round((performance.now() - n.ts) * 10) / 10 : n?.k === "app" && (M.events.received += 1, ce(n.d));
330
- }, me = (e, t) => {
331
- e.lastSeen = Date.now();
332
- let n;
333
- try {
334
- n = JSON.parse(t);
335
- } catch {
336
- return;
337
- }
338
- if (!Array.isArray(n) || !Number.isInteger(n[0])) return;
339
- let [r, , i] = n, a = M.move;
340
- a.received += 1, a.windowIn += 1, a.firstSeq ?? (a.firstSeq = r), r < a.maxSeq ? a.outOfOrder += 1 : (a.maxSeq = r, se(i, { seq: r }));
341
- }, he = (e) => {
342
- let t = M.move;
343
- t.hzIn = t.windowIn, t.hzOut = t.windowOut, t.windowIn = 0, t.windowOut = 0;
344
- let n = t.firstSeq == null ? 0 : t.maxSeq - t.firstSeq + 1;
345
- t.lossPct = n > 0 ? Math.max(0, Math.round((1 - t.received / n) * 1e3) / 10) : 0, e.closed || N();
346
- }, Q = async (e) => {
347
- if (!e.closed && e.pc?.getStats) try {
348
- let t = await e.pc.getStats(), n = /* @__PURE__ */ new Map();
349
- t.forEach((e) => n.set(e.id, e));
350
- let r = null;
351
- if (t.forEach((e) => {
352
- e.type === "transport" && e.selectedCandidatePairId && (r = n.get(e.selectedCandidatePairId));
353
- }), r || t.forEach((e) => {
354
- e.type === "candidate-pair" && (e.selected || e.nominated) && e.state === "succeeded" && (r = e);
355
- }), !r) return;
356
- let i = n.get(r.localCandidateId), a = n.get(r.remoteCandidateId), o = i?.candidateType === "relay" || a?.candidateType === "relay", s = o ? "relay" : i?.candidateType ?? "host";
357
- M.route = {
358
- local: i?.candidateType ?? null,
359
- remote: a?.candidateType ?? null,
360
- protocol: i?.protocol ?? null,
361
- relay: o,
362
- label: ae[s] ?? s
363
- }, typeof r.currentRoundTripTime == "number" && (M.statsRtt = Math.round(r.currentRoundTripTime * 1e4) / 10), N();
364
- } catch {}
365
- }, ge = (e) => {
366
- let t = D?.outbox.get(e.d.of);
367
- t && (clearTimeout(t.timer), D.outbox.delete(e.d.of));
368
- }, _e = (e) => {
369
- if (D && D.sid === e.sid || D && D.peerTab === e.from && (e.at ?? 0) <= D.peerAt) return;
370
- let t = D?.role === "caller" && !D.peerTab;
371
- if (t && i < e.from) return;
372
- if (!T && !t) {
373
- M.signals.ignored += 1;
374
- return;
375
- }
376
- D && V(D, { bye: !t });
377
- let n = B("answerer", e.sid, e.from);
378
- D = n, W(n), G(n) && (L(n, "ready", null), F("negotiating"));
379
- }, ve = (e) => {
380
- let t = D;
381
- t && t.role === "caller" && t.sid === e.sid && (t.peerTab && t.peerTab !== e.from ? L(t, "bye", null, {
382
- to: e.from,
383
- reliable: !1
384
- }) : t.peerTab || (t.peerTab = e.from, M.peerTab = e.from, clearInterval(t.helloTimer), G(t) && (F("negotiating"), J(t))));
385
- }, ye = async (e) => {
386
- let t = D;
387
- if (!(!t || t.role !== "answerer" || t.sid !== e.sid || t.peerTab !== e.from || e.gen < t.gen)) {
388
- t.gen = e.gen, M.gen = t.gen;
389
- try {
390
- if (await t.pc.setRemoteDescription({
391
- type: "offer",
392
- sdp: e.d.sdp
393
- }), t.closed) return;
394
- q(t);
395
- let n = await t.pc.createAnswer();
396
- if (t.closed || (await t.pc.setLocalDescription(n), t.closed)) return;
397
- L(t, "answer", { sdp: t.pc.localDescription.sdp });
398
- } catch (e) {
399
- U(t, `answer: ${e?.message ?? e}`);
400
- }
401
- }
402
- }, be = async (e) => {
403
- let t = D;
404
- if (t && t.role === "caller" && t.sid === e.sid && t.peerTab === e.from && e.gen === t.gen && t.pc.signalingState === "have-local-offer") try {
405
- if (await t.pc.setRemoteDescription({
406
- type: "answer",
407
- sdp: e.d.sdp
408
- }), t.closed) return;
409
- q(t), M.phase === "restarting" && ["connected", "completed"].includes(t.pc.iceConnectionState) && F("connected");
410
- } catch (e) {
411
- U(t, `answer remota: ${e?.message ?? e}`);
412
- }
413
- }, xe = (e) => {
414
- let t = D;
415
- !t || t.sid !== e.sid || t.peerTab !== e.from || e.gen < t.gen || (e.gen > t.gen || !t.pc?.remoteDescription ? t.pendingIce.push({
416
- gen: e.gen,
417
- c: e.d.c
418
- }) : K(t, e.d.c));
419
- }, Se = (e) => {
420
- if (e.sid === A && (k || D?.role === "caller" && !D.peerTab)) {
421
- clearTimeout(k), k = null, O = 0, D && V(D), F(T ? "listening" : "idle", "el rival cerró la conexión");
422
- return;
423
- }
424
- let t = D;
425
- t && t.sid === e.sid && (t.peerTab && t.peerTab !== e.from || (V(t), F(T ? "listening" : "idle", "el rival cerró la conexión")));
426
- };
427
- function $() {
428
- if (E) return;
429
- clearTimeout(k), k = null, D && V(D, { bye: !0 });
430
- let e = B("caller");
431
- D = e, W(e), F("calling");
432
- let t = () => {
433
- e.closed || e.peerTab || (Date.now() - e.helloStarted > te ? (V(e), F("failed", "el rival no respondió")) : L(e, "hello", null, {
434
- to: null,
435
- reliable: !1
436
- }));
437
- };
438
- t(), e.helloTimer = setInterval(t, ee);
439
- }
440
- return T && F("listening"), {
441
- tabId: i,
442
- connect() {
443
- O = 0, $();
444
- },
445
- setListening(e) {
446
- T = !!e, D || F(T ? "listening" : "idle");
447
- },
448
- sendMove(e) {
449
- let t = D;
450
- if (!t || t.move?.readyState !== "open") return !1;
451
- if (t.move.bufferedAmount > y) return M.move.dropped += 1, !1;
452
- let n = Z(t.move, JSON.stringify([
453
- ++t.moveSeq,
454
- Date.now(),
455
- e
456
- ]));
457
- return n && (M.move.sent += 1, M.move.windowOut += 1), n;
458
- },
459
- sendEvent(e) {
460
- let t = Z(D?.events, JSON.stringify({
461
- k: "app",
462
- d: e
463
- }));
464
- return t && (M.events.sent += 1), t;
465
- },
466
- restartIce() {
467
- D && Y(D);
468
- },
469
- getState: P,
470
- hangup() {
471
- clearTimeout(k), k = null, D && V(D, { bye: !0 }), F(T ? "listening" : "idle");
472
- },
473
- destroy() {
474
- E || (clearTimeout(k), D && V(D, { bye: !0 }), E = !0, z?.());
475
- }
476
- };
477
- }
478
- export { l as a, e as i, x as n, c as o, t as r, a as s, d as t };
479
-
480
- //# sourceMappingURL=createPeerLink-CL7VZuHS.js.map