@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,1847 +0,0 @@
1
- import { a as e, c as t, i as n, n as r, r as i, s as a, t as o } from "./battleship-DXKuIZ1I.js";
2
- import { useSyncExternalStore as s } from "react";
3
- import { createStore as c } from "zustand/vanilla";
4
- import { useStore as l } from "zustand";
5
- import { Volume2 as u, VolumeX as d } from "lucide-react";
6
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
7
- // src/games/shared/protocol.js
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
- "carrier",
10
- "battleship",
11
- "cruiser",
12
- "submarine",
13
- "destroyer"
14
- ], C = (e) => Number.isInteger(e) && e >= 0 && e < 10, w = (e) => typeof e == "string" && /^[0-9a-f]{64}$/.test(e), T = (e) => Number.isInteger(e) && e >= 1 && e <= 200, ee = (e) => e === null || _(e) && S.includes(e.ship_id) && Array.isArray(e.cells) && e.cells.length >= 2 && e.cells.length <= 5 && e.cells.every((e) => Array.isArray(e) && e.length === 2 && C(e[0]) && C(e[1])), E = (e) => Array.isArray(e) && e.length === S.length && e.every((e) => _(e) && S.includes(e.ship_id) && C(e.row) && C(e.col) && (e.orientation === "horizontal" || e.orientation === "vertical")) && new Set(e.map((e) => e.ship_id)).size === e.length, te = (e, t) => Array.isArray(e) && C(e[0]) && C(e[1]) && (e.length === 2 && t || e.length === 3 && (e[2] === 0 || e[2] === 1) || e.length === 7 && e[2] === 2 && Number.isInteger(e[3]) && e[3] >= 0 && e[3] < S.length && C(e[4]) && C(e[5]) && (e[6] === 0 || e[6] === 1)), D = (e) => Array.isArray(e.commits) && e.commits.length === 2 && e.commits.every((e) => e === null || w(e)) && Array.isArray(e.log) && e.log.length <= 200 && e.log.every((t, n) => te(t, n === e.log.length - 1)) && y(e.head) && (e.accept_event_id === void 0 ? e.commits.every((e) => e === null) && e.log.length === 0 : y(e.accept_event_id)) && (e.log.length === 0 || e.commits.every(Boolean));
15
- function ne(e) {
16
- let t = e.data;
17
- switch (e.type) {
18
- case "game_invite": return v(t.opponent_id) && t.rules_version === 1;
19
- case "game_accept":
20
- case "game_decline": return y(t.invite_event_id);
21
- case "game_end": return ["closed", "win"].includes(t.reason) && (t.winner_id === void 0 || v(t.winner_id));
22
- case "bs_commit": return w(t.commitment);
23
- case "bs_fire": return T(t.ply) && C(t.row) && C(t.col) && y(t.prev_event_id);
24
- case "bs_result": return T(t.ply) && C(t.row) && C(t.col) && ["hit", "miss"].includes(t.result) && ee(t.sunk) && typeof t.defeated == "boolean" && (t.result === "hit" || t.sunk === null && !t.defeated);
25
- case "bs_reveal": return E(t.fleet) && typeof t.salt == "string" && /^[0-9a-f]{32}$/.test(t.salt);
26
- case "bs_sync_request": return D(t);
27
- case "bs_sync_state": return D(t) && y(t.request_event_id);
28
- default: return !1;
29
- }
30
- }
31
- function O(e) {
32
- return typeof e == "string" && e.startsWith("LIRA_GAME_V1:");
33
- }
34
- function k(e) {
35
- if (!_(e) || e.version !== 1 || !["connect4", "battleship"].includes(e.game) || !y(e.game_id) || !y(e.event_id) || !_(e.data)) return !1;
36
- if (e.game === "battleship") return ne(e);
37
- let t = e.data;
38
- switch (e.type) {
39
- case "game_invite": return v(t.opponent_id) && t.rules_version === 1;
40
- case "game_accept":
41
- case "game_decline": return y(t.invite_event_id);
42
- case "game_move": return Number.isInteger(t.column) && t.column >= 0 && t.column < 7 && Number.isInteger(t.ply) && t.ply >= 1 && t.ply <= 42 && y(t.prev_event_id);
43
- case "game_end": return [
44
- "closed",
45
- "win",
46
- "draw"
47
- ].includes(t.reason) && (t.winner_id === void 0 || v(t.winner_id)) && (t.final_move_event_id === void 0 || y(t.final_move_event_id)) && (t.reason !== "win" || v(t.winner_id) && y(t.final_move_event_id)) && (t.reason !== "draw" || y(t.final_move_event_id));
48
- case "game_resync_request": return x(t);
49
- case "game_resync_state": return x(t) && y(t.request_event_id);
50
- default: return !1;
51
- }
52
- }
53
- function re(e) {
54
- if (!O(e) || e.length > h) return null;
55
- try {
56
- let t = JSON.parse(e.slice(13));
57
- return k(t) ? t : null;
58
- } catch {
59
- return null;
60
- }
61
- }
62
- function A(e) {
63
- if (!k(e)) throw Error("Evento de juego inválido");
64
- let t = m + JSON.stringify(e);
65
- if (t.length > h) throw Error("Evento de juego demasiado grande");
66
- return t;
67
- }
68
- function j(e, { game_id: t, data: n, event_id: r = crypto.randomUUID(), game: i = "connect4" }) {
69
- let a = {
70
- version: 1,
71
- game: i,
72
- game_id: t,
73
- event_id: r,
74
- type: e,
75
- data: n
76
- };
77
- if (!k(a)) throw Error("Evento de juego inválido");
78
- return a;
79
- }
80
- function ie() {
81
- return Array.from({ length: 6 }, () => Array(7).fill(null));
82
- }
83
- var ae = [
84
- [0, 1],
85
- [1, 0],
86
- [1, 1],
87
- [1, -1]
88
- ];
89
- function oe(e) {
90
- for (let t = 0; t < 6; t += 1) for (let n = 0; n < 7; n += 1) {
91
- let r = e[t][n];
92
- if (r != null) for (let [i, a] of ae) {
93
- let o = [];
94
- for (let s = 0; s < 4; s += 1) {
95
- let c = t + i * s, l = n + a * s;
96
- if (c < 0 || c >= 6 || l < 0 || l >= 7 || e[c][l] !== r) break;
97
- o.push([c, l]);
98
- }
99
- if (o.length === 4) return o;
100
- }
101
- }
102
- return [];
103
- }
104
- function se(e) {
105
- let t = oe(e);
106
- return t.length ? e[t[0][0]][t[0][1]] : null;
107
- }
108
- function ce(e) {
109
- return e[0].every((e) => e !== null);
110
- }
111
- function le(e, t, n) {
112
- if (!Number.isInteger(t) || t < 0 || t >= 7 || n == null || se(e) !== null) return null;
113
- let r = 5;
114
- for (; r >= 0 && e[r][t] !== null;) --r;
115
- if (r < 0) return null;
116
- let i = e.map((e) => e.slice());
117
- i[r][t] = n;
118
- let a = oe(i), o = a.length ? i[a[0][0]][a[0][1]] : null;
119
- return {
120
- board: i,
121
- row: r,
122
- column: t,
123
- winner: o,
124
- draw: o === null && ce(i),
125
- winningCells: a
126
- };
127
- }
128
- // src/games/battleship/logic/game.js
129
- var ue = (e) => typeof e == "string" && e.length > 0 && e.length <= 256 && e.trim() === e;
130
- function de({ gameId: e, players: t, firstPlayerId: n = t?.[0] } = {}) {
131
- if (!ue(e) || !Array.isArray(t) || t.length !== 2 || !t.every(ue) || t[0] === t[1] || !t.includes(n)) throw TypeError("Supply a gameId, two distinct player IDs and a valid firstPlayerId.");
132
- return {
133
- game: "battleship",
134
- rulesVersion: 1,
135
- gameId: e,
136
- players: t.slice(),
137
- boards: [r(), r()],
138
- ready: [!1, !1],
139
- phase: "placement",
140
- turnId: null,
141
- firstPlayerId: n,
142
- winnerId: null,
143
- shotCount: 0,
144
- lastShot: null,
145
- revision: 0
146
- };
147
- }
148
- function fe(n, r) {
149
- if (!n || !r || typeof r != "object" || n.phase === "finished" || r.gameId !== void 0 && r.gameId !== n.gameId || r.expectedRevision !== void 0 && r.expectedRevision !== n.revision) return n;
150
- let o = n.players.indexOf(r.playerId);
151
- if (o < 0) return n;
152
- let s = n.boards[o];
153
- if (n.phase === "placement") {
154
- if (n.ready[o]) return n;
155
- if (r.type === "place_ship" || r.type === "remove_ship") {
156
- let e = r.type === "place_ship" ? a(s, r) : t(s, r.shipId);
157
- if (!e.ok) return n;
158
- let i = n.boards.slice();
159
- return i[o] = e.board, {
160
- ...n,
161
- boards: i,
162
- revision: n.revision + 1
163
- };
164
- }
165
- if (r.type === "ready" && e(s)) {
166
- let e = n.ready.slice();
167
- e[o] = !0;
168
- let t = e.every(Boolean);
169
- return {
170
- ...n,
171
- ready: e,
172
- phase: t ? "playing" : "placement",
173
- turnId: t ? n.firstPlayerId : null,
174
- revision: n.revision + 1
175
- };
176
- }
177
- return n;
178
- }
179
- if (n.phase !== "playing" || r.type !== "fire" || r.playerId !== n.turnId) return n;
180
- let c = 1 - o, l = i(n.boards[c], r);
181
- if (!l.ok) return n;
182
- let u = n.boards.slice();
183
- return u[c] = l.board, {
184
- ...n,
185
- boards: u,
186
- revision: n.revision + 1,
187
- shotCount: n.shotCount + 1,
188
- phase: l.defeated ? "finished" : "playing",
189
- turnId: l.defeated ? null : n.players[c],
190
- winnerId: l.defeated ? r.playerId : null,
191
- lastShot: {
192
- playerId: r.playerId,
193
- targetId: n.players[c],
194
- row: r.row,
195
- col: r.col,
196
- result: l.result,
197
- shipId: l.shipId,
198
- sunk: l.sunk,
199
- defeated: l.defeated
200
- }
201
- };
202
- }
203
- // src/games/battleship/net/session.js
204
- var M = o.reduce((e, t) => e + t.size, 0), pe = /^[0-9a-f]{32}$/, me = [
205
- "won",
206
- "closed",
207
- "declined"
208
- ], N = "La partida perdió sincronización. Se intentará resincronizar.", he = "Falta la aceptación de la partida. Ciérrala y vuelve a invitar.", ge = "El rival envió un resultado imposible para ese disparo.", _e = "Tu flota no está disponible en este dispositivo; no se pueden responder disparos.", P = () => Array.from({ length: 10 }, () => Array(10).fill(null)), ve = (e, t, n, r) => e.map((e, i) => i === t ? e.map((e, t) => t === n ? r : e) : e), ye = (e) => e.reduce((e, t) => e + t.filter((e) => e === "hit").length, 0), be = (e) => e.reduce((e, t) => e + t.filter((e) => e !== null).length, 0), xe = (e, t) => t % 2 == 1 ? e.hostId : e.guestId, Se = (e, t) => t === e.hostId ? e.guestId : e.hostId, Ce = (e, t) => t === e.hostId ? "hostCommitment" : "guestCommitment", F = (e, t) => ({
209
- ...e,
210
- status: "conflict",
211
- error: t
212
- }), I = (e) => `${e.row},${e.col}`, we = (e, t) => e.row - t.row || e.col - t.col, Te = (e, t) => e.length === t.length && e.map(I).sort().join("|") === t.map(I).sort().join("|");
213
- function Ee(e) {
214
- return {
215
- ...e,
216
- game: "battleship",
217
- status: "invited",
218
- turnId: null,
219
- myFleet: [],
220
- myReady: !1,
221
- opponentReady: !1,
222
- incomingShots: P(),
223
- targetShots: P(),
224
- sunkEnemyShips: [],
225
- pendingShot: null,
226
- lastShot: null,
227
- winnerId: null,
228
- verification: null,
229
- ply: 0,
230
- shots: [],
231
- acceptEventId: null,
232
- hostCommitment: null,
233
- guestCommitment: null,
234
- myCommitment: null,
235
- mySalt: null,
236
- myRevealSent: !1,
237
- opponentReveal: null,
238
- seen: e.seen ?? {},
239
- pending: !1,
240
- pendingEvent: null,
241
- error: "",
242
- sync: e.sync ?? null
243
- };
244
- }
245
- var L = (e) => e?.game === "battleship" && ["invited", "placement"].includes(e.status) && !e.myReady, De = (e) => e?.status === "active" && e.turnId === e.ownId && !e.pendingShot, R = (e) => ({
246
- id: e.id,
247
- size: e.size,
248
- orientation: e.orientation,
249
- cells: e.cells.map((e) => ({
250
- row: e.row,
251
- col: e.col
252
- }))
253
- }), Oe = (e) => ({
254
- shipId: e.id,
255
- row: e.cells[0].row,
256
- col: e.cells[0].col,
257
- orientation: e.orientation
258
- });
259
- function ke(e) {
260
- return !e || typeof e != "object" ? null : typeof e.ship_id == "string" ? {
261
- shipId: e.ship_id,
262
- row: e.row,
263
- col: e.col,
264
- orientation: e.orientation
265
- } : typeof e.id == "string" && Array.isArray(e.cells) && e.cells.length ? Oe(e) : null;
266
- }
267
- function z(e) {
268
- if (!Array.isArray(e)) return null;
269
- let t = r();
270
- for (let n of e) {
271
- let e = ke(n), r = e && a(t, e);
272
- if (!r?.ok) return null;
273
- t = r.board;
274
- }
275
- return t;
276
- }
277
- function B(e) {
278
- if (!Array.isArray(e)) return null;
279
- let t = e.map(ke);
280
- return t.some((e) => !e) ? null : t.map(({ shipId: e, row: t, col: n, orientation: r }) => ({
281
- ship_id: e,
282
- row: t,
283
- col: n,
284
- orientation: r
285
- })).sort((e, t) => e.ship_id < t.ship_id ? -1 : +(e.ship_id > t.ship_id));
286
- }
287
- function V(t) {
288
- let n = z(t);
289
- return n && e(n) ? n.ships.map(R) : null;
290
- }
291
- var Ae = (e) => !!V(e);
292
- function je(t) {
293
- let n = z(t?.myFleet);
294
- return n && e(n) ? {
295
- ...n,
296
- shots: t.incomingShots.map((e) => e.slice())
297
- } : null;
298
- }
299
- function Me(e, { shipId: t, row: n, col: r, orientation: i } = {}) {
300
- if (!L(e)) return e;
301
- let o = z(e.myFleet.filter((e) => e.id !== t)), s = o && a(o, {
302
- shipId: t,
303
- row: n,
304
- col: r,
305
- orientation: i
306
- });
307
- return s?.ok ? {
308
- ...e,
309
- myFleet: s.board.ships.map(R)
310
- } : e;
311
- }
312
- function Ne(e, t) {
313
- return !L(e) || !e.myFleet.some((e) => e.id === t) ? e : {
314
- ...e,
315
- myFleet: e.myFleet.filter((e) => e.id !== t)
316
- };
317
- }
318
- function Pe(e) {
319
- let t = Math.floor(4294967296 / e) * e, n = /* @__PURE__ */ new Uint32Array(1);
320
- do
321
- globalThis.crypto.getRandomValues(n);
322
- while (n[0] >= t);
323
- return n[0] % e;
324
- }
325
- function Fe(t = Pe) {
326
- for (let n = 0; n < 50; n += 1) {
327
- let n = r();
328
- for (let e of o) for (let r = 0; r < 300; r += 1) {
329
- let r = a(n, {
330
- shipId: e.id,
331
- row: t(10),
332
- col: t(10),
333
- orientation: t(2) === 0 ? "horizontal" : "vertical"
334
- });
335
- if (r.ok) {
336
- n = r.board;
337
- break;
338
- }
339
- }
340
- if (e(n)) return n.ships.map(R);
341
- }
342
- throw Error("No se pudo generar una flota aleatoria.");
343
- }
344
- var Ie = (e, t) => L(e) ? {
345
- ...e,
346
- myFleet: Fe(t)
347
- } : e, Le = (e) => Array.from(e, (e) => e.toString(16).padStart(2, "0")).join("");
348
- function Re() {
349
- let e = /* @__PURE__ */ new Uint8Array(16);
350
- return globalThis.crypto.getRandomValues(e), Le(e);
351
- }
352
- function ze(e, t) {
353
- let n = B(e);
354
- if (!n || typeof t != "string") throw TypeError("Flota inválida");
355
- return JSON.stringify({
356
- fleet: n,
357
- salt: t
358
- });
359
- }
360
- async function Be(e, t) {
361
- let n = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(ze(e, t)));
362
- return Le(new Uint8Array(n));
363
- }
364
- function Ve(e, t) {
365
- if (!e || !t) return null;
366
- let n = i(e, {
367
- row: t.row,
368
- col: t.col
369
- });
370
- if (!n.ok) return null;
371
- let r = n.sunk ? e.ships.find((e) => e.id === n.shipId) : null;
372
- return {
373
- ply: t.ply,
374
- row: t.row,
375
- col: t.col,
376
- result: n.result,
377
- sunk: r ? {
378
- ship_id: r.id,
379
- cells: r.cells.map((e) => [e.row, e.col])
380
- } : null,
381
- defeated: n.defeated
382
- };
383
- }
384
- function He(e) {
385
- let t = o.find((t) => t.id === e?.ship_id);
386
- if (!t || !Array.isArray(e.cells) || e.cells.length !== t.size) return null;
387
- let r = e.cells.map((e) => Array.isArray(e) ? {
388
- row: e[0],
389
- col: e[1]
390
- } : null);
391
- if (r.some((e) => !n(e))) return null;
392
- r.sort(we);
393
- let i = r.every((e, t) => e.row === r[0].row && e.col === r[0].col + t), a = r.every((e, t) => e.col === r[0].col && e.row === r[0].row + t);
394
- return !i && !a ? null : {
395
- id: t.id,
396
- size: t.size,
397
- orientation: i ? "horizontal" : "vertical",
398
- cells: r,
399
- sunk: !0
400
- };
401
- }
402
- function Ue(e, t) {
403
- let { row: n, col: r, result: i, sunk: a } = t, s = !!t.defeated;
404
- if (i !== "hit" && i !== "miss" || e.targetShots[n][r] !== null) return null;
405
- let c = ve(e.targetShots, n, r, i), l = ye(c), u = null;
406
- if (a) {
407
- if (u = i === "hit" ? He(a) : null, !u || e.sunkEnemyShips.some((e) => e.id === u.id)) return null;
408
- let t = new Set(e.sunkEnemyShips.flatMap((e) => e.cells.map(I)));
409
- if (!u.cells.some((e) => e.row === n && e.col === r) || u.cells.some((e) => c[e.row][e.col] !== "hit" || t.has(I(e)))) return null;
410
- }
411
- let d = e.sunkEnemyShips.length + +!!u;
412
- return l > M || s !== (l === M) || s !== (d === o.length) || !s && M - l > 100 - be(c) ? null : {
413
- shots: c,
414
- ship: u
415
- };
416
- }
417
- function We(e, t) {
418
- let n = Ve(je(e), t);
419
- if (!n || n.result !== t.result || n.defeated !== !!t.defeated || !!n.sunk != !!t.sunk) return null;
420
- let r = n.sunk ? He(n.sunk) : null;
421
- return r && (t.sunk.ship_id !== r.id || !Te(r.cells, t.sunk.cells.map(([e, t]) => ({
422
- row: e,
423
- col: t
424
- })))) ? null : {
425
- shots: ve(e.incomingShots, t.row, t.col, t.result),
426
- ship: r
427
- };
428
- }
429
- function Ge(e, t, n, r) {
430
- let i = Ce(e, t);
431
- if (e[i]) return e[i] === n ? e : null;
432
- let a = {
433
- ...e,
434
- [i]: n
435
- };
436
- if (t === e.ownId) {
437
- let t = r?.commitment === n ? V(r.fleet) : null;
438
- t && pe.test(r.salt ?? "") ? a = {
439
- ...a,
440
- myFleet: t,
441
- mySalt: r.salt,
442
- myCommitment: n
443
- } : e.myCommitment === n && e.mySalt || (a = {
444
- ...a,
445
- myFleet: [],
446
- mySalt: null,
447
- myCommitment: n,
448
- error: _e
449
- }), a.myReady = !0;
450
- } else a.opponentReady = !0;
451
- return a.hostCommitment && a.guestCommitment && (a = {
452
- ...a,
453
- status: "active",
454
- turnId: e.hostId,
455
- ply: 0,
456
- pendingShot: null
457
- }), a;
458
- }
459
- function Ke(e, t, { row: r, col: i, ply: a }, o) {
460
- let s = t === e.ownId ? e.targetShots : e.incomingShots;
461
- return !n({
462
- row: r,
463
- col: i
464
- }) || s[r][i] !== null ? null : {
465
- ...e,
466
- pendingShot: {
467
- row: r,
468
- col: i,
469
- ply: a,
470
- by: t
471
- },
472
- lastEventId: o ?? e.lastEventId
473
- };
474
- }
475
- function qe(e, t, n, r) {
476
- let i = e.pendingShot, a = t === e.ownId, o = a ? We(e, n) : Ue(e, n);
477
- if (!o) return null;
478
- let s = !!n.defeated, c = {
479
- ply: i.ply,
480
- by: i.by,
481
- row: i.row,
482
- col: i.col,
483
- result: n.result,
484
- sunk: o.ship,
485
- defeated: s
486
- };
487
- return {
488
- ...e,
489
- incomingShots: a ? o.shots : e.incomingShots,
490
- targetShots: a ? e.targetShots : o.shots,
491
- sunkEnemyShips: !a && o.ship ? [...e.sunkEnemyShips, o.ship] : e.sunkEnemyShips,
492
- ply: i.ply,
493
- shots: [...e.shots, c],
494
- pendingShot: null,
495
- lastShot: {
496
- ...c,
497
- eventId: r ?? null
498
- },
499
- lastEventId: r ?? e.lastEventId,
500
- turnId: s ? null : t,
501
- status: s ? "won" : "active",
502
- winnerId: s ? i.by : null,
503
- verification: s ? "pending" : e.verification
504
- };
505
- }
506
- function Je(e, t, n) {
507
- let { ply: r, row: i, col: a, prev_event_id: o } = t.data;
508
- return n === xe(e, r) ? e.status === "active" ? r <= e.ply ? e : e.pendingShot ? r === e.pendingShot.ply ? e : F(e, N) : r > e.ply + 1 ? F(e, N) : n === e.turnId ? o === e.lastEventId ? Ke(e, n, {
509
- row: i,
510
- col: a,
511
- ply: r
512
- }, t.event_id) ?? e : F(e, N) : e : F(e, e.status === "invited" ? he : N) : e;
513
- }
514
- function Ye(e, t, n) {
515
- let { ply: r, row: i, col: a } = t.data;
516
- if (e.status !== "active") return e.status === "placement" ? F(e, N) : e;
517
- let o = e.pendingShot;
518
- return o ? r === o.ply ? n === o.by ? e : i !== o.row || a !== o.col ? n === e.ownId ? e : F(e, "El rival respondió a un disparo distinto.") : qe(e, n, t.data, t.event_id) || (n === e.ownId ? e : F(e, ge)) : r < o.ply ? e : F(e, N) : r <= e.ply ? e : F(e, N);
519
- }
520
- function Xe(e, t, n) {
521
- return !e.winnerId || !["won", "closed"].includes(e.status) ? e : n === e.ownId ? e.myRevealSent ? e : {
522
- ...e,
523
- myRevealSent: !0
524
- } : e.opponentReveal ? e : {
525
- ...e,
526
- opponentReveal: {
527
- fleet: t.fleet.map((e) => ({ ...e })),
528
- salt: t.salt
529
- },
530
- verification: "pending"
531
- };
532
- }
533
- function Ze(e, t, n, r = {}) {
534
- if (!e || e.game !== "battleship" || t?.game !== "battleship" || t.game_id !== e.gameId || n !== e.hostId && n !== e.guestId) return e;
535
- let i = t.data;
536
- if (t.type === "game_end") return i.reason !== "closed" || [
537
- "closed",
538
- "declined",
539
- "won"
540
- ].includes(e.status) ? e : {
541
- ...e,
542
- status: "closed",
543
- closedBy: n,
544
- error: ""
545
- };
546
- if (t.type === "bs_reveal") return Xe(e, i, n);
547
- if (me.includes(e.status) || e.status === "conflict") return e;
548
- switch (t.type) {
549
- case "game_accept":
550
- case "game_decline": return n !== e.guestId || e.status !== "invited" || i.invite_event_id !== e.inviteEventId ? e : t.type === "game_accept" ? {
551
- ...e,
552
- status: "placement",
553
- acceptEventId: t.event_id,
554
- lastEventId: t.event_id
555
- } : {
556
- ...e,
557
- status: "declined",
558
- lastEventId: t.event_id
559
- };
560
- case "bs_commit": return e.status === "invited" ? F(e, he) : e.status === "placement" ? Ge(e, n, i.commitment, r.stored) ?? e : e;
561
- case "bs_fire": return Je(e, t, n);
562
- case "bs_result": return Ye(e, t, n);
563
- default: return e;
564
- }
565
- }
566
- function Qe(e, t) {
567
- let n = de({
568
- gameId: String(e.gameId),
569
- players: [e.hostId, e.guestId],
570
- firstPlayerId: e.hostId
571
- });
572
- for (let e of n.players) {
573
- for (let r of t[e]) n = fe(n, {
574
- type: "place_ship",
575
- playerId: e,
576
- ...Oe(r)
577
- });
578
- n = fe(n, {
579
- type: "ready",
580
- playerId: e
581
- });
582
- }
583
- if (n.phase !== "playing") return !1;
584
- for (let t of e.shots) {
585
- let e = fe(n, {
586
- type: "fire",
587
- playerId: t.by,
588
- row: t.row,
589
- col: t.col
590
- });
591
- if (e === n) return !1;
592
- let r = e.lastShot;
593
- if (r.result !== t.result || r.defeated !== t.defeated || r.sunk !== !!t.sunk) return !1;
594
- if (t.sunk) {
595
- let n = e.boards[e.players.indexOf(r.targetId)].ships.find((e) => e.id === r.shipId);
596
- if (t.sunk.id !== r.shipId || !Te(n.cells, t.sunk.cells)) return !1;
597
- }
598
- n = e;
599
- }
600
- return !e.winnerId || n.winnerId === e.winnerId;
601
- }
602
- async function $e(e, t = e?.opponentReveal) {
603
- if (!e || !t) return "pending";
604
- let n = Se(e, e.ownId), r = e[Ce(e, n)], i = V(t.fleet);
605
- if (!r || !i || typeof t.salt != "string" || !pe.test(t.salt)) return "mismatch";
606
- let a;
607
- try {
608
- a = await Be(t.fleet, t.salt);
609
- } catch {
610
- return "mismatch";
611
- }
612
- if (a !== r) return "mismatch";
613
- let o = V(e.myFleet);
614
- return o ? Qe(e, {
615
- [e.ownId]: o,
616
- [n]: i
617
- }) ? "ok" : "mismatch" : "pending";
618
- }
619
- var et = (e) => {
620
- if (e.result === "miss") return [
621
- e.row,
622
- e.col,
623
- 0
624
- ];
625
- if (!e.sunk) return [
626
- e.row,
627
- e.col,
628
- 1
629
- ];
630
- let t = e.sunk.cells[0];
631
- return [
632
- e.row,
633
- e.col,
634
- 2,
635
- o.findIndex((t) => t.id === e.sunk.id),
636
- t.row,
637
- t.col,
638
- +(e.sunk.orientation === "vertical")
639
- ];
640
- };
641
- function tt(e) {
642
- if (!e.acceptEventId) return {
643
- commits: [null, null],
644
- log: [],
645
- head: e.inviteEventId
646
- };
647
- let t = e.shots.map(et);
648
- return e.pendingShot && t.push([e.pendingShot.row, e.pendingShot.col]), {
649
- accept_event_id: e.acceptEventId,
650
- commits: [e.hostCommitment ?? null, e.guestCommitment ?? null],
651
- log: t,
652
- head: e.lastEventId
653
- };
654
- }
655
- function nt(e, t) {
656
- let n = e.accept_event_id ?? null, r = t.accept_event_id ?? null;
657
- if (n && r && n !== r) return "diverged";
658
- let i = /* @__PURE__ */ new Set();
659
- n && !r && i.add("ahead"), !n && r && i.add("behind");
660
- for (let n of [0, 1]) {
661
- let r = e.commits?.[n] ?? null, a = t.commits?.[n] ?? null;
662
- if (r && a && r !== a) return "diverged";
663
- r && !a && i.add("ahead"), !r && a && i.add("behind");
664
- }
665
- let a = e.log ?? [], o = t.log ?? [];
666
- for (let e = 0; e < Math.min(a.length, o.length); e += 1) {
667
- let t = a[e], n = o[e];
668
- if (t.length === n.length) {
669
- if (t.some((e, t) => e !== n[t])) return "diverged";
670
- } else if (t[0] !== n[0] || t[1] !== n[1]) return "diverged";
671
- else i.add(t.length === 2 ? "behind" : "ahead");
672
- }
673
- return a.length !== o.length && i.add(a.length < o.length ? "behind" : "ahead"), i.size === 2 ? "mixed" : i.size === 1 ? [...i][0] : a.length && e.head !== t.head ? "diverged" : "equal";
674
- }
675
- function rt(e, t) {
676
- if ((e.log ?? []).length || (t.log ?? []).length) return null;
677
- let n = e.accept_event_id ?? t.accept_event_id;
678
- return n ? {
679
- accept_event_id: n,
680
- commits: [0, 1].map((n) => e.commits?.[n] ?? t.commits?.[n] ?? null),
681
- log: [],
682
- head: n
683
- } : null;
684
- }
685
- function it(e, t, n = {}) {
686
- let r = {
687
- ...e,
688
- status: "invited",
689
- turnId: null,
690
- myReady: !1,
691
- opponentReady: !1,
692
- incomingShots: P(),
693
- targetShots: P(),
694
- sunkEnemyShips: [],
695
- pendingShot: null,
696
- lastShot: null,
697
- winnerId: null,
698
- verification: null,
699
- ply: 0,
700
- shots: [],
701
- acceptEventId: null,
702
- hostCommitment: null,
703
- guestCommitment: null,
704
- error: "",
705
- myRevealSent: !1,
706
- opponentReveal: null,
707
- closedBy: void 0
708
- }, i = t.log ?? [], a = t.commits ?? [null, null];
709
- if (!t.accept_event_id) return a.some(Boolean) || i.length ? null : {
710
- ...r,
711
- lastEventId: e.inviteEventId
712
- };
713
- if (t.accept_event_id === e.inviteEventId) return null;
714
- let s = e.ownId === e.hostId ? 0 : 1;
715
- if (e.myCommitment && a[s] && a[s] !== e.myCommitment && n.stored?.commitment !== a[s]) return null;
716
- let c = {
717
- ...r,
718
- status: "placement",
719
- acceptEventId: t.accept_event_id,
720
- lastEventId: t.accept_event_id
721
- };
722
- for (let [t, r] of [e.hostId, e.guestId].entries()) if (a[t] && (c = Ge(c, r, a[t], n.stored), !c)) return null;
723
- if (i.length && c.status !== "active") return null;
724
- for (let e = 0; e < i.length; e += 1) {
725
- let t = i[e], n = e + 1;
726
- if (c = Ke(c, xe(c, n), {
727
- row: t[0],
728
- col: t[1],
729
- ply: n
730
- }, null), !c) return null;
731
- if (t.length === 2) {
732
- if (e !== i.length - 1) return null;
733
- break;
734
- }
735
- let r = Se(c, c.pendingShot.by), a = null;
736
- if (t[2] === 2) {
737
- let e = o[t[3]];
738
- if (!e) return null;
739
- let n = t[6] === 1;
740
- a = {
741
- ship_id: e.id,
742
- cells: Array.from({ length: e.size }, (e, r) => [t[4] + (n ? r : 0), t[5] + (n ? 0 : r)])
743
- };
744
- }
745
- let s = ye(r === c.ownId ? c.incomingShots : c.targetShots) + (t[2] === 0 ? 0 : 1);
746
- if (c = qe(c, r, {
747
- ply: n,
748
- row: t[0],
749
- col: t[1],
750
- result: t[2] === 0 ? "miss" : "hit",
751
- sunk: a,
752
- defeated: s === M
753
- }, null), !c || c.status === "won" && e !== i.length - 1) return null;
754
- }
755
- return !i.length && t.head !== t.accept_event_id ? null : (c = {
756
- ...c,
757
- lastEventId: t.head
758
- }, c.winnerId && e.winnerId === c.winnerId && (c = {
759
- ...c,
760
- myRevealSent: e.myRevealSent,
761
- opponentReveal: e.opponentReveal,
762
- verification: e.verification
763
- }), c);
764
- }
765
- function at(e, t) {
766
- if (!e || !t) return !1;
767
- let n = e.log?.[(t.data?.ply ?? 0) - 1];
768
- switch (t.type) {
769
- case "game_accept": return e.accept_event_id === t.event_id;
770
- case "bs_commit": return (e.commits ?? []).includes(t.data.commitment);
771
- case "bs_fire": return !!(n && n[0] === t.data.row && n[1] === t.data.col);
772
- case "bs_result": return !!(n && n.length > 2 && n[0] === t.data.row && n[1] === t.data.col);
773
- default: return !1;
774
- }
775
- }
776
- function ot(e, t) {
777
- let n = { ...e };
778
- return t.acceptEventId && (n[t.acceptEventId] = !0), t.lastEventId && (n[t.lastEventId] = !0), n;
779
- }
780
- // src/games/battleship/net/fleetStorage.js
781
- var st = "lira:bs:", ct = 12096e5, lt = (e, t) => `${st}${e}:${t}`, ut = () => {
782
- try {
783
- return globalThis.localStorage ?? null;
784
- } catch {
785
- return null;
786
- }
787
- };
788
- function dt(e) {
789
- return typeof e == "object" && !!e && Array.isArray(e.fleet) && e.fleet.length === 5 && typeof e.salt == "string" && /^[0-9a-f]{32}$/.test(e.salt) && typeof e.commitment == "string" && /^[0-9a-f]{64}$/.test(e.commitment);
790
- }
791
- function ft(e) {
792
- let t = Date.now();
793
- for (let n = e.length - 1; n >= 0; --n) {
794
- let r = e.key(n);
795
- if (r?.startsWith(st)) try {
796
- let n = JSON.parse(e.getItem(r));
797
- dt(n) && t - n.savedAt < ct || e.removeItem(r);
798
- } catch {
799
- e.removeItem(r);
800
- }
801
- }
802
- }
803
- function pt(e, t, { fleet: n, salt: r, commitment: i }) {
804
- try {
805
- let a = ut();
806
- return a ? (ft(a), a.setItem(lt(e, t), JSON.stringify({
807
- fleet: n,
808
- salt: r,
809
- commitment: i,
810
- savedAt: Date.now()
811
- })), !0) : !1;
812
- } catch {
813
- return !1;
814
- }
815
- }
816
- function mt(e, t) {
817
- try {
818
- let n = JSON.parse(ut()?.getItem(lt(e, t)) ?? "null");
819
- return dt(n) ? {
820
- fleet: n.fleet,
821
- salt: n.salt,
822
- commitment: n.commitment
823
- } : null;
824
- } catch {
825
- return null;
826
- }
827
- }
828
- // src/games/shared/useChatGames.js
829
- var ht = ["connect4", "battleship"], H = (e) => e?.game ?? "connect4", U = (e) => H(e) === "battleship", gt = 250, W = (e) => [
830
- "won",
831
- "draw",
832
- "closed",
833
- "declined"
834
- ].includes(e.status), _t = (e, t, n) => JSON.stringify([
835
- e,
836
- String(t),
837
- n
838
- ]), vt = (e) => {
839
- let t = Object.keys(e).filter((t) => W(e[t]));
840
- if (t.length <= 80) return e;
841
- let n = { ...e };
842
- return t.slice(0, t.length - 80).forEach((e) => {
843
- delete n[e];
844
- }), n;
845
- };
846
- function yt(e, t, n) {
847
- if (![e.hostId, e.guestId].includes(n)) return e;
848
- if (t.type === "game_end" && t.data.reason === "closed") return ["closed", "declined"].includes(e.status) ? e : {
849
- ...e,
850
- status: "closed",
851
- closedBy: n,
852
- error: ""
853
- };
854
- if (W(e) || e.status === "conflict") return e;
855
- if (t.type === "game_accept" || t.type === "game_decline") return n !== e.guestId || e.status !== "invited" || t.data.invite_event_id !== e.inviteEventId ? e : {
856
- ...e,
857
- status: t.type === "game_accept" ? "active" : "declined",
858
- lastEventId: t.event_id,
859
- acceptEventId: t.type === "game_accept" ? t.event_id : e.acceptEventId
860
- };
861
- if (t.type !== "game_move") return e;
862
- let { ply: r, prev_event_id: i, column: a } = t.data;
863
- if (n !== (r % 2 == 1 ? e.hostId : e.guestId)) return e;
864
- if (e.status !== "active") return {
865
- ...e,
866
- status: "conflict",
867
- error: "Falta la aceptación de la partida. Ciérrala y vuelve a invitar."
868
- };
869
- if (r <= e.ply || r > e.ply + 1 || i !== e.lastEventId) return {
870
- ...e,
871
- status: "conflict",
872
- error: "La partida perdió sincronización. Ciérrala y envía una nueva invitación."
873
- };
874
- if (n !== e.turnId) return e;
875
- let o = le(e.board, a, n);
876
- return o ? {
877
- ...e,
878
- board: o.board,
879
- ply: r,
880
- lastEventId: t.event_id,
881
- moves: [...e.moves ?? [], [a, t.event_id]],
882
- lastMove: {
883
- row: o.row,
884
- column: a,
885
- eventId: t.event_id
886
- },
887
- winnerId: o.winner || null,
888
- winningCells: o.winningCells,
889
- status: o.winner ? "won" : o.draw ? "draw" : "active",
890
- turnId: n === e.hostId ? e.guestId : e.hostId
891
- } : e;
892
- }
893
- var bt = 8e3, G = {
894
- status: "idle",
895
- requestId: null,
896
- requestedAt: 0,
897
- auto: !1,
898
- outgoing: [],
899
- replies: [],
900
- offer: null,
901
- message: ""
902
- }, xt = (e) => [
903
- "game_resync_request",
904
- "game_resync_state",
905
- "bs_sync_request",
906
- "bs_sync_state"
907
- ].includes(e), St = (e) => e.acceptEventId ? {
908
- accept_event_id: e.acceptEventId,
909
- moves: e.moves ?? [],
910
- rev: (e.moves ?? []).length
911
- } : {
912
- moves: [],
913
- rev: 0
914
- };
915
- function Ct(e, t, n) {
916
- let r = {
917
- ...e,
918
- board: ie(),
919
- ply: 0,
920
- turnId: e.hostId,
921
- winnerId: null,
922
- winningCells: [],
923
- lastMove: null,
924
- moves: [],
925
- error: ""
926
- };
927
- if (!t) return n.length ? null : {
928
- ...r,
929
- status: "invited",
930
- acceptEventId: null,
931
- lastEventId: e.inviteEventId
932
- };
933
- if (t === e.inviteEventId) return null;
934
- let i = {
935
- ...r,
936
- status: "active",
937
- acceptEventId: t,
938
- lastEventId: t
939
- }, a = /* @__PURE__ */ new Set([e.inviteEventId, t]);
940
- for (let t = 0; t < n.length; t += 1) {
941
- let [r, o] = n[t];
942
- if (a.has(o)) return null;
943
- a.add(o);
944
- let s = t % 2 == 0 ? e.hostId : e.guestId, c = yt(i, {
945
- type: "game_move",
946
- event_id: o,
947
- data: {
948
- column: r,
949
- ply: t + 1,
950
- prev_event_id: i.lastEventId
951
- }
952
- }, s);
953
- if (c.status === "conflict" || c.ply !== t + 1 || c.lastEventId !== o) return null;
954
- i = c;
955
- }
956
- return i;
957
- }
958
- function wt(e, t) {
959
- if (e.acceptEventId && t.acceptEventId && e.acceptEventId !== t.acceptEventId) return "diverged";
960
- let n = Math.min(e.moves.length, t.moves.length);
961
- for (let r = 0; r < n; r += 1) if (e.moves[r][0] !== t.moves[r][0] || e.moves[r][1] !== t.moves[r][1]) return "diverged";
962
- return e.moves.length === t.moves.length ? e.acceptEventId && !t.acceptEventId ? "ahead" : !e.acceptEventId && t.acceptEventId ? "behind" : "equal" : e.moves.length < t.moves.length ? "behind" : "ahead";
963
- }
964
- var Tt = (e) => e.pendingEvent?.type === "game_move" && !e.pending ? e.pendingEvent.event_id : null, Et = {
965
- requestType: "game_resync_request",
966
- stateType: "game_resync_state",
967
- historyOf: St,
968
- rebuild: (e, t) => Ct(e, t.accept_event_id ?? null, t.moves),
969
- compare: (e, t) => wt({
970
- acceptEventId: e.acceptEventId ?? null,
971
- moves: e.moves ?? []
972
- }, {
973
- acceptEventId: t.accept_event_id ?? null,
974
- moves: t.moves
975
- }),
976
- offerOf: (e) => ({
977
- accept_event_id: e.accept_event_id ?? null,
978
- moves: e.moves
979
- }),
980
- covers: (e, t) => {
981
- let n = Tt(e);
982
- return !!(n && t.moves?.some((e) => e[1] === n));
983
- },
984
- markSeen: (e, t) => {
985
- let n = { ...e };
986
- return t.acceptEventId && (n[t.acceptEventId] = !0), (t.moves ?? []).forEach((e) => {
987
- n[e[1]] = !0;
988
- }), n;
989
- },
990
- merge: () => null
991
- }, Dt = (e) => ({
992
- requestType: "bs_sync_request",
993
- stateType: "bs_sync_state",
994
- historyOf: tt,
995
- rebuild: (t, n) => it(t, n, { stored: e(t.scope, t.gameId) }),
996
- compare: (e, t) => nt(tt(e), t),
997
- offerOf: (e) => ({
998
- accept_event_id: e.accept_event_id,
999
- commits: e.commits,
1000
- log: e.log,
1001
- head: e.head
1002
- }),
1003
- covers: (e, t) => !!(e.pendingEvent && !e.pending && at(t, e.pendingEvent)),
1004
- markSeen: ot,
1005
- merge: (e, t) => rt(tt(e), t)
1006
- }), Ot = (e, t, n) => j(t, {
1007
- game_id: e.gameId,
1008
- data: n,
1009
- game: H(e)
1010
- });
1011
- function kt() {
1012
- let e = null, t = /* @__PURE__ */ new Map(), n = (e, n) => t.get(`${e}:${n}`) ?? mt(e, n), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Set(), s = Dt(n), l = (e) => U(e) ? s : Et;
1013
- return c((s, c) => ({
1014
- games: {},
1015
- configureTransport: (t) => {
1016
- e = t;
1017
- },
1018
- clear: () => {
1019
- r.forEach((e) => clearTimeout(e)), r.clear(), o.forEach((e) => clearTimeout(e)), o.clear(), t.clear(), i.clear(), a.clear(), s({ games: {} });
1020
- },
1021
- markDisconnected: (e) => s((t) => ({ games: Object.fromEntries(Object.entries(t.games).map(([t, n]) => [t, n.scope === e && !W(n) ? {
1022
- ...n,
1023
- status: "conflict",
1024
- error: "Conexión interrumpida. Se intentará resincronizar al reconectar.",
1025
- sync: {
1026
- ...G,
1027
- ...n.sync,
1028
- status: "idle",
1029
- auto: !1
1030
- }
1031
- } : n])) })),
1032
- ingest: (t, r, i) => {
1033
- let o = typeof r == "object" ? r : {
1034
- scope: r,
1035
- currentUserId: i
1036
- }, l = o?.scope ?? e?.getScope?.(), u = String(o?.currentUserId ?? e?.getUserId?.() ?? ""), d = t.data ?? t.payload, f = d && typeof d == "object" ? {
1037
- ...d,
1038
- ...t
1039
- } : t, p = f.message ?? f.text;
1040
- if (typeof p != "string" || !p.startsWith("LIRA_GAME_V1:")) return !1;
1041
- let m = re(p), h = String(f.room_id ?? ""), g = String(f.user_id ?? "");
1042
- if (!m || !l || !u || !g || !h.startsWith("private_")) return !0;
1043
- let _ = h.slice(8).split("_");
1044
- if (_.length !== 2 || !_.includes(u) || !_.includes(g)) return !0;
1045
- let v = _t(l, h, m.game_id), y = c().games[v];
1046
- if (y && H(y) !== m.game) return !0;
1047
- if (xt(m.type)) return y && !y.seen[m.event_id] && c().handleResync(v, m, g, u), !0;
1048
- if (!y && m.type !== "game_invite") {
1049
- let e = Date.now();
1050
- for (let [t, n] of a) e - n.at > 3e4 && a.delete(t);
1051
- !a.has(v) && a.size >= 32 && a.delete(a.keys().next().value);
1052
- let t = a.get(v) ?? {
1053
- at: e,
1054
- messages: []
1055
- };
1056
- return t.messages.length < 8 && !t.messages.some((e) => e.eventId === m.event_id) && t.messages.push({
1057
- eventId: m.event_id,
1058
- message: f
1059
- }), a.set(v, t), !0;
1060
- }
1061
- if (y?.seen[m.event_id]) return !0;
1062
- let b = y;
1063
- if (m.type === "game_invite") {
1064
- let e = m.data.opponent_id;
1065
- if (y || e === g || !_.includes(e)) return !0;
1066
- b = m.game === "battleship" ? Ee({
1067
- key: v,
1068
- gameId: m.game_id,
1069
- game_id: m.game_id,
1070
- scope: l,
1071
- roomId: h,
1072
- ownId: u,
1073
- hostId: g,
1074
- guestId: e,
1075
- createdAt: f.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
1076
- inviteEventId: m.event_id,
1077
- lastEventId: m.event_id,
1078
- seen: {},
1079
- sync: { ...G }
1080
- }) : {
1081
- key: v,
1082
- gameId: m.game_id,
1083
- game_id: m.game_id,
1084
- game: "connect4",
1085
- scope: l,
1086
- roomId: h,
1087
- ownId: u,
1088
- hostId: g,
1089
- guestId: e,
1090
- turnId: g,
1091
- status: "invited",
1092
- board: ie(),
1093
- ply: 0,
1094
- winnerId: null,
1095
- lastMove: null,
1096
- createdAt: f.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
1097
- inviteEventId: m.event_id,
1098
- lastEventId: m.event_id,
1099
- seen: {},
1100
- pending: !1,
1101
- error: "",
1102
- pendingEvent: null,
1103
- acceptEventId: null,
1104
- moves: [],
1105
- sync: { ...G }
1106
- };
1107
- } else U(y) ? b = Ze(y, m, g, { stored: m.type === "bs_commit" && g === u ? n(l, m.game_id) : null }) : y && (b = yt(y, m, g));
1108
- if (!b || b === y) return !0;
1109
- if (b = {
1110
- ...b,
1111
- seen: {
1112
- ...b.seen,
1113
- [m.event_id]: !0
1114
- }
1115
- }, s((e) => {
1116
- let t = {
1117
- ...e.games,
1118
- [v]: b
1119
- };
1120
- if (m.type === "game_invite") {
1121
- let e = Object.values(t).filter((e) => e.scope === l && e.roomId === h && !W(e)), n = e.sort((e, t) => e.gameId < t.gameId ? -1 : +(e.gameId > t.gameId))[0];
1122
- e.forEach((e) => {
1123
- e.key !== n?.key && (t[e.key] = {
1124
- ...e,
1125
- status: "closed",
1126
- error: "Se conserva la otra invitación de esta conversación."
1127
- });
1128
- });
1129
- }
1130
- return { games: vt(t) };
1131
- }), b.status === "conflict" && y?.status !== "conflict" && queueMicrotask(() => {
1132
- c().requestResync(v, { auto: !0 });
1133
- }), U(b) && c().bsScheduleEffects(v), m.type === "game_invite") {
1134
- let e = a.get(v);
1135
- a.delete(v), e && Date.now() - e.at <= 3e4 && e.messages.forEach((e) => c().ingest(e.message, l, u));
1136
- }
1137
- return !0;
1138
- },
1139
- invite: async ({ roomId: t, opponentId: n, gameType: r = "connect4" }) => {
1140
- if (!e) throw Error("Chat no disponible");
1141
- if (!ht.includes(r)) throw Error("Juego no disponible");
1142
- let i = e.getScope();
1143
- if (!String(e.getUserId() ?? "") || !String(t).startsWith("private_")) throw Error("Abre un chat privado para jugar.");
1144
- if (Object.values(c().games).some((e) => e.scope === i && e.roomId === String(t) && (!W(e) || e.pendingEvent))) throw Error("Cierra la partida actual antes de invitar.");
1145
- let a = j("game_invite", {
1146
- game_id: crypto.randomUUID(),
1147
- data: {
1148
- opponent_id: String(n),
1149
- rules_version: 1
1150
- },
1151
- game: r
1152
- });
1153
- return c().sendEvent(t, a);
1154
- },
1155
- act: async (t, n, r = {}) => {
1156
- let i = c().games[t], a = String(e?.getUserId?.() ?? "");
1157
- if (!i || i.scope !== e?.getScope?.()) throw Error("Partida no disponible");
1158
- if (n !== "game_end" && (i.pending || i.pendingEvent)) throw Error("Reintenta el envío pendiente antes de continuar.");
1159
- let o = r;
1160
- if (n === "game_accept" || n === "game_decline") {
1161
- if (i.status !== "invited" || a !== i.guestId) return;
1162
- o = { invite_event_id: i.inviteEventId };
1163
- } else if (n === "game_move") {
1164
- if (U(i) || i.status !== "active" || a !== i.turnId || !le(i.board, r.column, a)) return;
1165
- o = {
1166
- column: r.column,
1167
- ply: i.ply + 1,
1168
- prev_event_id: i.lastEventId
1169
- };
1170
- } else if (n === "game_end") o = { reason: "closed" };
1171
- else return;
1172
- return c().sendEvent(i.roomId, j(n, {
1173
- game_id: i.gameId,
1174
- data: o,
1175
- game: H(i)
1176
- }));
1177
- },
1178
- bsUpdateLocal: (e, t) => {
1179
- let n = c().games[e];
1180
- if (!U(n)) return !1;
1181
- let r = t(n);
1182
- return r !== n && (s((t) => t.games[e] === n ? { games: {
1183
- ...t.games,
1184
- [e]: r
1185
- } } : t), c().games[e] === r);
1186
- },
1187
- bsPlaceShip: (e, t) => c().bsUpdateLocal(e, (e) => Me(e, t)),
1188
- bsRemoveShip: (e, t) => c().bsUpdateLocal(e, (e) => Ne(e, t)),
1189
- bsRandomFleet: (e) => c().bsUpdateLocal(e, (e) => Ie(e)),
1190
- bsReady: async (n) => {
1191
- let r = c().games[n];
1192
- if (!U(r) || r.status !== "placement" || r.myReady) return;
1193
- if (r.scope !== e?.getScope?.()) throw Error("Partida no disponible");
1194
- if (r.pending || r.pendingEvent) throw Error("Reintenta el envío pendiente antes de continuar.");
1195
- let i = B(r.myFleet);
1196
- if (!Ae(i)) throw Error("Coloca los cinco barcos antes de continuar.");
1197
- let a = Re(), o = await Be(i, a), s = c().games[n];
1198
- if (!(!s || s.myReady || s.status !== "placement" || s.pending || s.pendingEvent || JSON.stringify(B(s.myFleet)) !== JSON.stringify(i))) return t.set(`${r.scope}:${r.gameId}`, {
1199
- fleet: i,
1200
- salt: a,
1201
- commitment: o
1202
- }), pt(r.scope, r.gameId, {
1203
- fleet: i,
1204
- salt: a,
1205
- commitment: o
1206
- }), c().sendEvent(r.roomId, j("bs_commit", {
1207
- game_id: r.gameId,
1208
- data: { commitment: o },
1209
- game: "battleship"
1210
- }));
1211
- },
1212
- bsFire: async (t, { row: n, col: r } = {}) => {
1213
- let i = c().games[t];
1214
- if (!U(i) || i.scope !== e?.getScope?.()) throw Error("Partida no disponible");
1215
- if (i.pending || i.pendingEvent) throw Error("Reintenta el envío pendiente antes de continuar.");
1216
- if (De(i) && i.targetShots[n]?.[r] === null) return c().sendEvent(i.roomId, j("bs_fire", {
1217
- game_id: i.gameId,
1218
- data: {
1219
- ply: i.ply + 1,
1220
- row: n,
1221
- col: r,
1222
- prev_event_id: i.lastEventId
1223
- },
1224
- game: "battleship"
1225
- }));
1226
- },
1227
- bsScheduleEffects: (e) => {
1228
- r.has(e) || r.set(e, setTimeout(() => {
1229
- r.delete(e), c().bsRunEffects(e);
1230
- }, gt));
1231
- },
1232
- bsRunEffects: (t) => {
1233
- let r = c().games[t];
1234
- if (!U(r) || !e || r.scope !== e.getScope?.()) return;
1235
- if (r.opponentReveal && r.verification === "pending" && !i.has(t)) {
1236
- let e = r.opponentReveal;
1237
- i.add(t), $e(r, e).then((n) => s((r) => {
1238
- let i = r.games[t];
1239
- return !i || i.opponentReveal !== e || i.verification === n ? r : { games: {
1240
- ...r.games,
1241
- [t]: {
1242
- ...i,
1243
- verification: n
1244
- }
1245
- } };
1246
- })).catch(() => {}).finally(() => {
1247
- i.delete(t);
1248
- });
1249
- }
1250
- if (r.pending || r.pendingEvent) return;
1251
- let a = (e, t) => {
1252
- c().sendEvent(r.roomId, j(e, {
1253
- game_id: r.gameId,
1254
- data: t,
1255
- game: "battleship"
1256
- })).catch(() => {});
1257
- };
1258
- if (r.status === "active" && r.pendingShot && r.pendingShot.by !== r.ownId) {
1259
- let e = Ve(je(r), r.pendingShot);
1260
- e ? a("bs_result", e) : r.error || s((e) => ({ games: {
1261
- ...e.games,
1262
- [t]: {
1263
- ...e.games[t],
1264
- error: "Tu flota no está disponible en este dispositivo; no se pueden responder disparos."
1265
- }
1266
- } }));
1267
- return;
1268
- }
1269
- let o = String(r.winnerId) !== String(r.ownId) || !!r.opponentReveal;
1270
- if (r.winnerId && ["won", "closed"].includes(r.status) && !r.myRevealSent && o) {
1271
- let e = B(r.myFleet), t = r.mySalt ?? n(r.scope, r.gameId)?.salt;
1272
- Ae(e) && t && a("bs_reveal", {
1273
- fleet: e,
1274
- salt: t
1275
- });
1276
- }
1277
- },
1278
- sendEvent: async (t, n) => {
1279
- if (!e) throw Error("Chat no disponible");
1280
- let r = e, i = r.getScope(), a = String(r.getUserId() ?? ""), o = _t(i, t, n.game_id), l = A(n);
1281
- if (c().ingest({
1282
- room_id: t,
1283
- user_id: a,
1284
- message: l
1285
- }, i, a), !c().games[o]?.seen[n.event_id]) throw Error("Evento de partida inválido");
1286
- let u = (e, t = !0) => s((r) => {
1287
- let i = r.games[o];
1288
- return !i || t && i.pendingEvent?.event_id !== n.event_id ? r : { games: {
1289
- ...r.games,
1290
- [o]: {
1291
- ...i,
1292
- ...e
1293
- }
1294
- } };
1295
- });
1296
- u({
1297
- pending: !0,
1298
- pendingEvent: n,
1299
- error: ""
1300
- }, !1);
1301
- try {
1302
- await r.send(t, l), u({
1303
- pending: !1,
1304
- pendingEvent: null
1305
- }), n.game === "battleship" && c().bsScheduleEffects(o);
1306
- } catch (e) {
1307
- throw u({
1308
- pending: !1,
1309
- error: e.message || "No se pudo enviar. Reintenta el mismo evento."
1310
- }), e;
1311
- }
1312
- return o;
1313
- },
1314
- handleResync: (e, t, n, r) => {
1315
- let i = c().games[e], a = l(i), o = {
1316
- ...i.seen,
1317
- [t.event_id]: !0
1318
- }, u = (t) => {
1319
- s((n) => ({ games: {
1320
- ...n.games,
1321
- [e]: t
1322
- } })), U(t) && c().bsScheduleEffects(e);
1323
- };
1324
- if (n === r || ![i.hostId, i.guestId].includes(n) || ["closed", "declined"].includes(i.status)) {
1325
- u({
1326
- ...i,
1327
- seen: o
1328
- });
1329
- return;
1330
- }
1331
- let d = {
1332
- ...G,
1333
- ...i.sync
1334
- };
1335
- if (![a.requestType, a.stateType].includes(t.type)) {
1336
- u({
1337
- ...i,
1338
- seen: o
1339
- });
1340
- return;
1341
- }
1342
- let f = t.type === a.stateType;
1343
- if (f && !d.outgoing.includes(t.data.request_event_id)) {
1344
- u({
1345
- ...i,
1346
- seen: o
1347
- });
1348
- return;
1349
- }
1350
- let p = a.rebuild(i, t.data);
1351
- if (!p) {
1352
- u({
1353
- ...i,
1354
- seen: o,
1355
- sync: f ? {
1356
- ...d,
1357
- status: "failed",
1358
- message: "El rival envió un estado de partida inválido."
1359
- } : d
1360
- });
1361
- return;
1362
- }
1363
- let m = a.compare(i, t.data), h = {
1364
- ...d,
1365
- status: "ok",
1366
- offer: null,
1367
- auto: !1,
1368
- message: ""
1369
- }, g, _ = !f, v = !1, y = m === "mixed" ? a.merge(i, t.data) : null;
1370
- if (m === "equal" || m === "behind") g = {
1371
- ...p,
1372
- sync: h
1373
- }, a.covers(i, t.data) && (g = {
1374
- ...g,
1375
- pendingEvent: null
1376
- });
1377
- else if (y) {
1378
- let e = a.rebuild(i, y);
1379
- g = e ? {
1380
- ...e,
1381
- sync: h
1382
- } : {
1383
- ...i,
1384
- sync: {
1385
- ...d,
1386
- status: "failed",
1387
- message: "No se pudo reconstruir la partida local."
1388
- }
1389
- }, _ = !!e, v = !!e;
1390
- } else if (m === "ahead" || n === i.guestId) {
1391
- let e = a.rebuild(i, a.historyOf(i));
1392
- g = e ? {
1393
- ...e,
1394
- sync: h
1395
- } : {
1396
- ...i,
1397
- sync: {
1398
- ...d,
1399
- status: "failed",
1400
- message: "No se pudo reconstruir la partida local."
1401
- }
1402
- }, _ = !!e, v = !!e;
1403
- } else g = {
1404
- ...i,
1405
- status: "conflict",
1406
- error: "El anfitrión tiene otra versión de la partida. Revísala antes de aceptarla.",
1407
- sync: {
1408
- ...d,
1409
- status: "incompatible",
1410
- offer: a.offerOf(t.data),
1411
- message: ""
1412
- }
1413
- };
1414
- g = {
1415
- ...g,
1416
- seen: a.markSeen(o, g)
1417
- };
1418
- let b = Date.now(), x = g.sync.replies.filter((e) => b - e < 3e4), S = null;
1419
- if (_ && x.length < 6) try {
1420
- S = Ot(i, a.stateType, {
1421
- ...a.historyOf(g),
1422
- request_event_id: t.event_id
1423
- });
1424
- } catch {
1425
- S = null;
1426
- }
1427
- S && (g = {
1428
- ...g,
1429
- seen: {
1430
- ...g.seen,
1431
- [S.event_id]: !0
1432
- },
1433
- sync: {
1434
- ...g.sync,
1435
- replies: [...x, b],
1436
- outgoing: [...g.sync.outgoing, S.event_id].slice(-8)
1437
- }
1438
- }), u(g), S && c().sendResync(e, S).then(() => {
1439
- v && (s((t) => {
1440
- let n = t.games[e];
1441
- return !n || !l(n).covers(n, l(n).historyOf(n)) ? t : { games: {
1442
- ...t.games,
1443
- [e]: {
1444
- ...n,
1445
- pendingEvent: null,
1446
- error: ""
1447
- }
1448
- } };
1449
- }), U(c().games[e]) && c().bsScheduleEffects(e));
1450
- }).catch(() => {});
1451
- },
1452
- sendResync: async (t, n) => {
1453
- let r = c().games[t];
1454
- if (!e || !r || r.scope !== e.getScope?.()) throw Error("Chat no disponible");
1455
- await e.send(r.roomId, A(n));
1456
- },
1457
- requestResync: async (t, { auto: n = !1 } = {}) => {
1458
- let r = c().games[t];
1459
- if (!r || !e || ["closed", "declined"].includes(r.status) || r.scope !== e.getScope?.()) return;
1460
- let i = {
1461
- ...G,
1462
- ...r.sync
1463
- };
1464
- if (i.status === "requesting" && Date.now() - i.requestedAt < bt || n && i.auto) return;
1465
- let a;
1466
- try {
1467
- a = Ot(r, l(r).requestType, l(r).historyOf(r));
1468
- } catch {
1469
- return;
1470
- }
1471
- let u = (e) => s((n) => {
1472
- let r = n.games[t];
1473
- return r?.sync?.requestId !== a.event_id || r.sync.status !== "requesting" ? n : { games: {
1474
- ...n.games,
1475
- [t]: {
1476
- ...r,
1477
- sync: {
1478
- ...r.sync,
1479
- status: "failed",
1480
- message: e
1481
- }
1482
- }
1483
- } };
1484
- });
1485
- s((e) => {
1486
- let r = e.games[t];
1487
- return r ? { games: {
1488
- ...e.games,
1489
- [t]: {
1490
- ...r,
1491
- seen: {
1492
- ...r.seen,
1493
- [a.event_id]: !0
1494
- },
1495
- sync: {
1496
- ...i,
1497
- status: "requesting",
1498
- requestId: a.event_id,
1499
- requestedAt: Date.now(),
1500
- auto: i.auto || n,
1501
- message: "",
1502
- outgoing: [...i.outgoing, a.event_id].slice(-8)
1503
- }
1504
- }
1505
- } } : e;
1506
- });
1507
- let d = setTimeout(() => {
1508
- o.delete(d), u("El rival no respondió a la sincronización. Reintenta cuando esté conectado.");
1509
- }, bt);
1510
- o.add(d);
1511
- try {
1512
- await c().sendResync(t, a);
1513
- } catch (e) {
1514
- u(e.message || "No se pudo enviar la solicitud de sincronización.");
1515
- }
1516
- },
1517
- adoptResyncOffer: (e) => {
1518
- let t = c().games[e], n = t?.sync?.offer;
1519
- if (!n || t.sync.status !== "incompatible") return !1;
1520
- let r = l(t), i = r.rebuild(t, n);
1521
- return s((n) => ({ games: {
1522
- ...n.games,
1523
- [e]: i ? {
1524
- ...i,
1525
- seen: r.markSeen(t.seen, i),
1526
- pending: !1,
1527
- pendingEvent: null,
1528
- sync: {
1529
- ...t.sync,
1530
- status: "ok",
1531
- offer: null,
1532
- auto: !1,
1533
- message: ""
1534
- }
1535
- } : {
1536
- ...t,
1537
- sync: {
1538
- ...t.sync,
1539
- status: "failed",
1540
- offer: null,
1541
- message: "El estado del anfitrión ya no es válido."
1542
- }
1543
- }
1544
- } })), i && U(i) && c().bsScheduleEffects(e), !!i;
1545
- },
1546
- resyncConflicts: (e) => {
1547
- Object.values(c().games).filter((t) => t.scope === e && t.status === "conflict").forEach((e) => {
1548
- c().requestResync(e.key, { auto: !0 });
1549
- });
1550
- },
1551
- retry: (t) => {
1552
- let n = c().games[t];
1553
- return !n?.pendingEvent || n.pending ? Promise.resolve() : n.scope === e?.getScope?.() ? c().sendEvent(n.roomId, n.pendingEvent) : Promise.reject(/* @__PURE__ */ Error("La sesión de esta partida ya no está activa."));
1554
- }
1555
- }));
1556
- }
1557
- var K = kt(), At = (e) => l(K, e);
1558
- Object.assign(At, {
1559
- getState: K.getState,
1560
- setState: K.setState,
1561
- subscribe: K.subscribe
1562
- });
1563
- // src/assets/chatAssets.js
1564
- var jt = "/sounds", Mt = jt, Nt = (e) => String(e).replace(/\/+$/, "");
1565
- function Pt(e) {
1566
- Mt = e == null ? jt : Nt(e);
1567
- }
1568
- function Ft() {
1569
- return Mt;
1570
- }
1571
- function It(e) {
1572
- return `${Mt}/${String(e).replace(/^\/+/, "")}`;
1573
- }
1574
- // src/core/connection/connectionStore.js
1575
- var Lt = c(() => ({ status: "idle" }));
1576
- function Rt(e) {
1577
- Lt.setState({ status: e });
1578
- }
1579
- function zt() {
1580
- return l(Lt, (e) => e.status);
1581
- }
1582
- // src/games/shared/gameStatus.js
1583
- var q = (e, t) => e != null && t != null && String(e) === String(t), Bt = (e) => [
1584
- "won",
1585
- "draw",
1586
- "declined",
1587
- "closed"
1588
- ].includes(e?.status), Vt = (e) => !!e && ([
1589
- "invited",
1590
- "placement",
1591
- "active",
1592
- "conflict"
1593
- ].includes(e.status) || !!e.pendingEvent), J = (e) => e?.game === "battleship", Ht = (e) => J(e) ? "Batalla Naval" : "Conecta 4", Ut = {
1594
- ok: "Partida verificada",
1595
- mismatch: "Resultados inconsistentes del rival",
1596
- pending: "Verificando…"
1597
- }, Wt = (e) => Ut[e?.verification] || "";
1598
- function Gt(e, t) {
1599
- let n = q(t, e.turnId);
1600
- return e.status === "placement" ? e.myReady ? e.opponentReady ? "Iniciando batalla…" : "Esperando a que el rival coloque su flota" : "Coloca tu flota" : e.status === "active" ? e.pendingShot ? "Esperando resultado…" : n ? "Tu turno · elige una casilla" : "Turno del rival" : e.status === "won" ? q(t, e.winnerId) ? "¡Ganaste!" : "Tu rival ganó" : null;
1601
- }
1602
- function Kt(e, t) {
1603
- if (J(e)) {
1604
- let n = Gt(e, t);
1605
- if (n) return n;
1606
- }
1607
- let n = e.status === "active" && q(t, e.turnId);
1608
- return e.status === "invited" ? q(t, e.guestId) ? "Te han invitado a jugar" : "Esperando respuesta a la invitación" : e.status === "active" ? n ? "Tu turno · elige una columna" : "Turno de tu rival" : e.status === "won" ? q(t, e.winnerId) ? "¡Ganaste la partida!" : "Tu rival ganó la partida" : e.status === "draw" ? "Empate · tablero completo" : e.status === "declined" ? "Invitación rechazada" : e.status === "closed" ? "Partida finalizada" : e.status === "conflict" ? "Partida pausada por un conflicto de sincronización" : "Esperando respuesta a la invitación";
1609
- }
1610
- function qt(e, t) {
1611
- if (J(e)) {
1612
- if (e.status === "placement") return e.myReady ? "Esperando al rival" : "Coloca tu flota";
1613
- if (e.status === "active" && e.pendingShot) return "Esperando resultado…";
1614
- }
1615
- return e.status === "active" ? q(t, e.turnId) ? "Tu turno" : "Turno del rival" : e.status === "invited" ? q(t, e.guestId) ? "Invitación recibida" : "Invitación enviada" : e.status === "conflict" ? e.sync?.status === "requesting" ? "Sincronizando…" : "Sin sincronizar" : Kt(e, t);
1616
- }
1617
- // src/audio/useSoundSettings.js
1618
- function Jt(e) {
1619
- return s(e.subscribe, e.getSettings, e.getSettings);
1620
- }
1621
- // src/games/shared/GameSoundControls.jsx
1622
- function Yt({ manager: e }) {
1623
- let { volume: t, muted: n } = Jt(e), r = n || t === 0;
1624
- return /* @__PURE__ */ p("div", {
1625
- className: "chat-game-sound",
1626
- children: [/* @__PURE__ */ f("button", {
1627
- type: "button",
1628
- className: "chat-game-sound-toggle",
1629
- onClick: e.toggleMuted,
1630
- "aria-pressed": r,
1631
- "aria-label": r ? "Activar sonido del juego" : "Silenciar sonido del juego",
1632
- title: r ? "Activar sonido" : "Silenciar",
1633
- children: f(r ? d : u, { size: 15 })
1634
- }), /* @__PURE__ */ f("input", {
1635
- type: "range",
1636
- min: "0",
1637
- max: "100",
1638
- step: "5",
1639
- value: Math.round((n ? 0 : t) * 100),
1640
- onChange: (t) => e.setVolume(Number(t.target.value) / 100),
1641
- "aria-label": "Volumen del juego"
1642
- })]
1643
- });
1644
- }
1645
- // src/audio/createSoundManager.js
1646
- var Xt = [
1647
- "pointerdown",
1648
- "keydown",
1649
- "touchend"
1650
- ], Zt = 300, Qt = 800, Y = (e) => Math.min(1, Math.max(0, Number(e) || 0));
1651
- function $t(e, t) {
1652
- try {
1653
- let n = JSON.parse(localStorage.getItem(e) ?? "null");
1654
- if (n && typeof n == "object") return {
1655
- volume: Y(n.volume ?? t.volume),
1656
- muted: !!n.muted
1657
- };
1658
- } catch {}
1659
- return {
1660
- volume: Y(t.volume),
1661
- muted: !1
1662
- };
1663
- }
1664
- var en = 1.5, tn = .6;
1665
- function nn({ id: e, baseUrl: t, sounds: n, levels: r = {}, defaultVolume: i = .6, settingsFrom: a = null }) {
1666
- let o = `lira.sound.${e}`, s = typeof window < "u" ? window.AudioContext || window.webkitAudioContext : null, c = a ? a.getSettings() : $t(o, { volume: i }), l = null, u = null, d = !1, f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Set(), h = /* @__PURE__ */ new Set(), g = /* @__PURE__ */ new Set(), _ = /* @__PURE__ */ new Set(), v = /* @__PURE__ */ new Map(), y = !1, b = !1, x = null, S = (e) => `${String(typeof t == "function" ? t() : t).replace(/\/$/, "")}/${n[e]}`, C = (e) => (f.has(e) || f.set(e, fetch(S(e)).then((e) => e.ok ? e.arrayBuffer() : null).catch(() => null)), f.get(e)), w = () => {
1667
- if (!s) return null;
1668
- if (!l) try {
1669
- l = new s(), u = l.createGain(), u.gain.value = c.muted ? 0 : c.volume, u.connect(l.destination);
1670
- } catch {
1671
- return l = null, null;
1672
- }
1673
- return l.state === "suspended" && l.resume().catch(() => {}), l;
1674
- }, T = (e) => {
1675
- if (m.has(e) || !n[e]) return Promise.resolve(null);
1676
- if (!p.has(e)) {
1677
- let t = w();
1678
- if (!t) return Promise.resolve(null);
1679
- p.set(e, C(e).then((e) => e ? new Promise((n) => {
1680
- t.decodeAudioData(e.slice(0), n, () => n(null));
1681
- }) : null).then((t) => (t || m.add(e), t)).catch(() => (m.add(e), null)));
1682
- }
1683
- return p.get(e);
1684
- }, ee = (e) => Y(r[e] ?? 1), E = (e) => {
1685
- if (!_.has(e) || v.has(e) || !d) return;
1686
- let t = w();
1687
- if (!t) return;
1688
- let n = {};
1689
- v.set(e, n), T(e).then((r) => {
1690
- if (v.get(e) === n) {
1691
- if (!r || t.state === "closed") v.delete(e);
1692
- else try {
1693
- let n = t.createGain();
1694
- n.gain.setValueAtTime(0, t.currentTime), n.gain.linearRampToValueAtTime(ee(e), t.currentTime + en), n.connect(u);
1695
- let i = t.createBufferSource();
1696
- i.buffer = r, i.loop = !0, i.connect(n), i.start(), v.set(e, {
1697
- source: i,
1698
- level: n
1699
- });
1700
- } catch {
1701
- v.delete(e);
1702
- }
1703
- }
1704
- });
1705
- }, te = (e) => {
1706
- let t = v.get(e);
1707
- if (v.delete(e), t?.source && l) try {
1708
- let e = l.currentTime;
1709
- t.level.gain.cancelScheduledValues(e), t.level.gain.setValueAtTime(t.level.gain.value, e), t.level.gain.linearRampToValueAtTime(0, e + tn), t.source.stop(e + tn + .05);
1710
- } catch {}
1711
- }, D = () => {
1712
- d || (d = !0, ne(), w() && Object.keys(n).forEach((e) => {
1713
- f.has(e) && T(e);
1714
- }), _.forEach(E));
1715
- };
1716
- function ne() {
1717
- b && (b = !1, Xt.forEach((e) => window.removeEventListener(e, D, !0)));
1718
- }
1719
- let O = (e) => !h.has(e) && (h.add(e), h.size > Zt && h.delete(h.values().next().value), !0), k = () => g.forEach((e) => e()), re = (e) => {
1720
- c = e, u && (u.gain.value = c.muted ? 0 : c.volume), k();
1721
- }, A = (e) => {
1722
- let t = {
1723
- volume: Y(e.volume ?? c.volume),
1724
- muted: e.muted ?? c.muted
1725
- };
1726
- try {
1727
- localStorage.setItem(o, JSON.stringify(t));
1728
- } catch {}
1729
- re(t);
1730
- }, j = () => {
1731
- y || (y = !0, a && (c = a.getSettings(), x = a.subscribe(() => re(a.getSettings()))), !(typeof window > "u" || d) && (typeof navigator < "u" && navigator.userActivation?.hasBeenActive ? d = !0 : (b = !0, Xt.forEach((e) => window.addEventListener(e, D, {
1732
- capture: !0,
1733
- passive: !0
1734
- })))));
1735
- };
1736
- return {
1737
- start: j,
1738
- dispose: () => {
1739
- ne(), x && (x(), x = null), y = !1, _.clear(), v.forEach((e) => {
1740
- try {
1741
- e?.source?.stop();
1742
- } catch {}
1743
- }), v.clear(), p.clear();
1744
- let e = l;
1745
- l = null, u = null, e && e.state !== "closed" && e.close().catch(() => {});
1746
- },
1747
- preload(e = Object.keys(n)) {
1748
- j(), e.forEach((e) => {
1749
- n[e] && !m.has(e) && (C(e), l && T(e));
1750
- });
1751
- },
1752
- play(e, { key: t } = {}) {
1753
- if (j(), t != null && !O(`${e}:${t}`) || !n[e] || m.has(e) || !d || c.muted || c.volume === 0) return !1;
1754
- let r = w();
1755
- if (!r) return !1;
1756
- let i = Date.now();
1757
- return T(e).then((t) => {
1758
- if (!(!t || r.state === "closed" || Date.now() - i > Qt)) try {
1759
- let n = r.createBufferSource();
1760
- n.buffer = t;
1761
- let i = ee(e);
1762
- if (i === 1) n.connect(u);
1763
- else {
1764
- let e = r.createGain();
1765
- e.gain.value = i, n.connect(e), e.connect(u);
1766
- }
1767
- n.start();
1768
- } catch {}
1769
- }), !0;
1770
- },
1771
- markPlayed(e, t) {
1772
- O(`${e}:${t}`);
1773
- },
1774
- startLoop(e) {
1775
- j(), n[e] && !m.has(e) && (_.add(e), E(e));
1776
- },
1777
- stopLoop(e) {
1778
- _.delete(e), te(e);
1779
- },
1780
- getSettings: () => a && !y ? a.getSettings() : c,
1781
- setVolume: a ? a.setVolume : (e) => A({
1782
- volume: e,
1783
- muted: Y(e) === 0 && c.muted
1784
- }),
1785
- setMuted: a ? a.setMuted : (e) => A({ muted: !!e }),
1786
- toggleMuted: a ? a.toggleMuted : () => A({ muted: !c.muted }),
1787
- subscribe(e) {
1788
- return j(), g.add(e), () => g.delete(e);
1789
- }
1790
- };
1791
- }
1792
- // src/games/connect4/connect4Sounds.js
1793
- var X = nn({
1794
- id: "connect4",
1795
- baseUrl: () => It("connect4"),
1796
- sounds: {
1797
- invite: "invite.ogg",
1798
- start: "start.ogg",
1799
- drop: "drop.ogg",
1800
- turn: "turn.ogg",
1801
- win: "win.ogg",
1802
- lose: "lose.ogg",
1803
- draw: "draw.ogg",
1804
- close: "close.ogg"
1805
- }
1806
- }), rn = 140, Z = /* @__PURE__ */ new Map(), Q = /* @__PURE__ */ new Set(), $ = null, an = (e, t) => e != null && t != null && String(e) === String(t), on = () => typeof window < "u" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
1807
- function sn(e, t) {
1808
- e.status === "won" ? X.play(an(e.winnerId, e.ownId) ? "win" : "lose", { key: t }) : e.status === "draw" ? X.play("draw", { key: t }) : e.status === "active" && an(e.turnId, e.ownId) && X.play("turn", { key: t });
1809
- }
1810
- function cn(e) {
1811
- let t = Z.get(e);
1812
- if (!t) return;
1813
- clearTimeout(t.timer), Z.delete(e), X.play("drop", { key: e });
1814
- let n = setTimeout(() => {
1815
- Q.delete(n), sn(t.game, e);
1816
- }, rn);
1817
- Q.add(n);
1818
- }
1819
- function ln(e) {
1820
- let t = e.lastMove?.eventId;
1821
- if (!t || Z.has(t)) return;
1822
- let n = on() ? 0 : 440;
1823
- Z.set(t, {
1824
- game: e,
1825
- timer: setTimeout(() => cn(t), n)
1826
- });
1827
- }
1828
- function un(e, t) {
1829
- t ? t.status === "invited" && e.status === "active" ? X.play("start", { key: e.lastEventId }) : e.ply > t.ply ? ln(e) : (e.status === "closed" && e.closedBy != null || e.status === "declined") && t.status !== e.status && X.play("close", { key: e.gameId }) : e.status === "invited" && an(e.guestId, e.ownId) && X.play("invite", { key: e.inviteEventId });
1830
- }
1831
- var dn = () => $ != null;
1832
- function fn() {
1833
- if ($) return $;
1834
- X.start();
1835
- let e = At.subscribe((e, t) => {
1836
- e.games !== t.games && Object.entries(e.games).forEach(([e, n]) => {
1837
- let r = t.games[e];
1838
- n.game && n.game !== "connect4" || n !== r && n.ownId != null && un(n, r);
1839
- });
1840
- }), t = () => {
1841
- $ === t && ($ = null, e(), Z.forEach(({ timer: e }) => clearTimeout(e)), Z.clear(), Q.forEach(clearTimeout), Q.clear());
1842
- };
1843
- return $ = t, t;
1844
- }
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
-
1847
- //# sourceMappingURL=connect4Sounds-9u0p-dAf.js.map