@minicode-dev/chat 0.1.13 → 0.1.15

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 (114) hide show
  1. package/CHANGELOG.md +112 -5
  2. package/README.md +401 -312
  3. package/assets/sounds/effects/avalanche.mp3 +0 -0
  4. package/assets/sounds/racing/car_boost.mp3 +0 -0
  5. package/assets/sounds/racing/car_boost.ogg +0 -0
  6. package/assets/sounds/racing/car_bump.mp3 +0 -0
  7. package/assets/sounds/racing/car_bump.ogg +0 -0
  8. package/assets/sounds/racing/car_drift_loop.mp3 +0 -0
  9. package/assets/sounds/racing/car_drift_loop.ogg +0 -0
  10. package/assets/sounds/racing/car_engine_loop.mp3 +0 -0
  11. package/assets/sounds/racing/car_engine_loop.ogg +0 -0
  12. package/assets/sounds/racing/car_engine_start.mp3 +0 -0
  13. package/assets/sounds/racing/car_engine_start.ogg +0 -0
  14. package/assets/sounds/racing/countdown_beep.mp3 +0 -0
  15. package/assets/sounds/racing/countdown_beep.ogg +0 -0
  16. package/assets/sounds/racing/countdown_go.mp3 +0 -0
  17. package/assets/sounds/racing/countdown_go.ogg +0 -0
  18. package/assets/sounds/racing/final_lap.mp3 +0 -0
  19. package/assets/sounds/racing/final_lap.ogg +0 -0
  20. package/assets/sounds/racing/finish_line.mp3 +0 -0
  21. package/assets/sounds/racing/finish_line.ogg +0 -0
  22. package/assets/sounds/racing/lap_complete.mp3 +0 -0
  23. package/assets/sounds/racing/lap_complete.ogg +0 -0
  24. package/assets/sounds/racing/music_circuit.mp3 +0 -0
  25. package/assets/sounds/racing/music_circuit.ogg +0 -0
  26. package/assets/sounds/racing/music_final_lap.mp3 +0 -0
  27. package/assets/sounds/racing/music_final_lap.ogg +0 -0
  28. package/assets/sounds/racing/race_defeat.mp3 +0 -0
  29. package/assets/sounds/racing/race_defeat.ogg +0 -0
  30. package/assets/sounds/racing/race_victory.mp3 +0 -0
  31. package/assets/sounds/racing/race_victory.ogg +0 -0
  32. package/assets/sounds/tanks/barrel_explode.mp3 +0 -0
  33. package/assets/sounds/tanks/barrel_explode.ogg +0 -0
  34. package/assets/sounds/tanks/crate_break.mp3 +0 -0
  35. package/assets/sounds/tanks/crate_break.ogg +0 -0
  36. package/assets/sounds/tanks/health_pickup.mp3 +0 -0
  37. package/assets/sounds/tanks/health_pickup.ogg +0 -0
  38. package/assets/sounds/tanks/last_life.mp3 +0 -0
  39. package/assets/sounds/tanks/last_life.ogg +0 -0
  40. package/assets/sounds/tanks/life_lost.mp3 +0 -0
  41. package/assets/sounds/tanks/life_lost.ogg +0 -0
  42. package/assets/sounds/tanks/respawn.mp3 +0 -0
  43. package/assets/sounds/tanks/respawn.ogg +0 -0
  44. package/assets/sounds/tanks/shield_end.mp3 +0 -0
  45. package/assets/sounds/tanks/shield_end.ogg +0 -0
  46. package/assets/sounds/tanks/shield_loop.mp3 +0 -0
  47. package/assets/sounds/tanks/shield_loop.ogg +0 -0
  48. package/assets/sounds/tanks/wall_hit.mp3 +0 -0
  49. package/assets/sounds/tanks/wall_hit.ogg +0 -0
  50. package/dist/chunks/{BattleshipGameCard-iRk8d4vR.js → BattleshipGameCard-8H-sBCsv.js} +146 -144
  51. package/dist/chunks/{BattleshipGameCard-iRk8d4vR.js.map → BattleshipGameCard-8H-sBCsv.js.map} +1 -1
  52. package/dist/chunks/{ChatContext-DjIEifGY.js → ChatContext-CVW58bzC.js} +2 -2
  53. package/dist/chunks/{ChatContext-DjIEifGY.js.map → ChatContext-CVW58bzC.js.map} +1 -1
  54. package/dist/chunks/RacingLiveGameCard-8j9QLnxW.js +1654 -0
  55. package/dist/chunks/RacingLiveGameCard-8j9QLnxW.js.map +1 -0
  56. package/dist/chunks/{TanksGameCard-GrqmdwJ7.js → TanksGameCard-DnCufSH6.js} +168 -166
  57. package/dist/chunks/{TanksGameCard-GrqmdwJ7.js.map → TanksGameCard-DnCufSH6.js.map} +1 -1
  58. package/dist/chunks/TanksLiveGameCard-D_27Jomp.js +1274 -0
  59. package/dist/chunks/TanksLiveGameCard-D_27Jomp.js.map +1 -0
  60. package/dist/chunks/avalancheScene3d-CIE2WKQn.js +1300 -0
  61. package/dist/chunks/avalancheScene3d-CIE2WKQn.js.map +1 -0
  62. package/dist/chunks/cars-D1PM7mVD.js +340 -0
  63. package/dist/chunks/cars-D1PM7mVD.js.map +1 -0
  64. package/dist/chunks/connect4Sounds-BqEHULjv.js +235 -0
  65. package/dist/chunks/connect4Sounds-BqEHULjv.js.map +1 -0
  66. package/dist/chunks/connectionStore-DwgIUl30.js +13 -0
  67. package/dist/chunks/connectionStore-DwgIUl30.js.map +1 -0
  68. package/dist/chunks/createLiveScene-MTGRv8rx.js +758 -0
  69. package/dist/chunks/createLiveScene-MTGRv8rx.js.map +1 -0
  70. package/dist/chunks/createRaceScene-BiEtQsVs.js +306 -0
  71. package/dist/chunks/createRaceScene-BiEtQsVs.js.map +1 -0
  72. package/dist/chunks/{createTankScene-6asWHKFf.js → createTankScene-yhX6la27.js} +125 -123
  73. package/dist/chunks/{createTankScene-6asWHKFf.js.map → createTankScene-yhX6la27.js.map} +1 -1
  74. package/dist/chunks/decor-CyyCnmct.js +418 -0
  75. package/dist/chunks/decor-CyyCnmct.js.map +1 -0
  76. package/dist/chunks/fx-1ZwzmPWj.js +458 -0
  77. package/dist/chunks/fx-1ZwzmPWj.js.map +1 -0
  78. package/dist/chunks/fx-DhXerGyt.js +248 -0
  79. package/dist/chunks/fx-DhXerGyt.js.map +1 -0
  80. package/dist/chunks/gameStatus-BChd29yI.js +62 -0
  81. package/dist/chunks/gameStatus-BChd29yI.js.map +1 -0
  82. package/dist/chunks/games-Bl_8raG6.js +3681 -0
  83. package/dist/chunks/games-Bl_8raG6.js.map +1 -0
  84. package/dist/chunks/rolldown-runtime-CGnMp29N.js +10 -0
  85. package/dist/chunks/tank-DjEQ4FXF.js +553 -0
  86. package/dist/chunks/tank-DjEQ4FXF.js.map +1 -0
  87. package/dist/chunks/tanks-live-BcKmrhnV.js +261 -0
  88. package/dist/chunks/tanks-live-BcKmrhnV.js.map +1 -0
  89. package/dist/chunks/{tanksSounds-CUNDIOal.js → tanksSounds-DTnidbiq.js} +44 -12
  90. package/dist/chunks/tanksSounds-DTnidbiq.js.map +1 -0
  91. package/dist/chunks/track-BcnnpnAm.js +259 -0
  92. package/dist/chunks/track-BcnnpnAm.js.map +1 -0
  93. package/dist/chunks/util-DwI9bfS7.js +57 -0
  94. package/dist/chunks/util-DwI9bfS7.js.map +1 -0
  95. package/dist/index.js +822 -635
  96. package/dist/index.js.map +1 -1
  97. package/dist/styles.css +1 -1
  98. package/index.d.ts +3 -1
  99. package/package.json +1 -1
  100. package/dist/chunks/TanksLiveGameCard-DSmQcUMh.js +0 -1225
  101. package/dist/chunks/TanksLiveGameCard-DSmQcUMh.js.map +0 -1
  102. package/dist/chunks/avalancheScene3d-Dnl2E3EA.js +0 -1878
  103. package/dist/chunks/avalancheScene3d-Dnl2E3EA.js.map +0 -1
  104. package/dist/chunks/connect4Sounds-Cv0q31VW.js +0 -3245
  105. package/dist/chunks/connect4Sounds-Cv0q31VW.js.map +0 -1
  106. package/dist/chunks/createLiveScene-819NWv84.js +0 -365
  107. package/dist/chunks/createLiveScene-819NWv84.js.map +0 -1
  108. package/dist/chunks/fx-BNJvJYOu.js +0 -871
  109. package/dist/chunks/fx-BNJvJYOu.js.map +0 -1
  110. package/dist/chunks/gameStatus-Cu1Z8un9.js +0 -69
  111. package/dist/chunks/gameStatus-Cu1Z8un9.js.map +0 -1
  112. package/dist/chunks/tank-DIn6Jyt8.js +0 -605
  113. package/dist/chunks/tank-DIn6Jyt8.js.map +0 -1
  114. package/dist/chunks/tanksSounds-CUNDIOal.js.map +0 -1
@@ -1,3245 +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 "./board-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/core/ids/randomUuid.js
8
- function m(e = globalThis.crypto) {
9
- if (typeof e?.randomUUID == "function") return e.randomUUID();
10
- let t = /* @__PURE__ */ new Uint8Array(16);
11
- if (typeof e?.getRandomValues == "function") e.getRandomValues(t);
12
- else for (let e = 0; e < t.length; e += 1) t[e] = Math.floor(Math.random() * 256);
13
- t[6] = t[6] & 15 | 64, t[8] = t[8] & 63 | 128;
14
- let n = Array.from(t, (e) => e.toString(16).padStart(2, "0")).join("");
15
- return `${n.slice(0, 8)}-${n.slice(8, 12)}-${n.slice(12, 16)}-${n.slice(16, 20)}-${n.slice(20)}`;
16
- }
17
- // src/games/tanks-live/session.js
18
- var h = (e) => typeof e == "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e), g = (e) => typeof e == "string" && e.length > 0 && e.length <= 256 && e.trim() === e;
19
- function _(e) {
20
- let t = e.data;
21
- switch (e.type) {
22
- case "game_invite": return g(t.opponent_id) && t.rules_version === 1 && (t.rematch_of === void 0 || h(t.rematch_of));
23
- case "game_accept":
24
- case "game_decline": return h(t.invite_event_id);
25
- case "game_end": return t.reason === "closed";
26
- default: return !1;
27
- }
28
- }
29
- function v(e, t) {
30
- return {
31
- ...e,
32
- game: "tanks_live",
33
- status: "invited",
34
- turnId: null,
35
- winnerId: null,
36
- rematchOf: t.rematch_of ?? null,
37
- pending: !1,
38
- pendingEvent: null,
39
- error: "",
40
- acceptEventId: null
41
- };
42
- }
43
- function y(e, t, n) {
44
- return [e.hostId, e.guestId].includes(n) ? t.type === "game_end" ? ["closed", "declined"].includes(e.status) ? e : {
45
- ...e,
46
- status: "closed",
47
- closedBy: n,
48
- error: ""
49
- } : e.status !== "invited" || n !== e.guestId || t.data.invite_event_id !== e.inviteEventId ? e : t.type === "game_decline" ? {
50
- ...e,
51
- status: "declined",
52
- lastEventId: t.event_id
53
- } : t.type === "game_accept" ? {
54
- ...e,
55
- status: "active",
56
- acceptEventId: t.event_id,
57
- lastEventId: t.event_id
58
- } : e : e;
59
- }
60
- // src/net/webrtc/rtcSignals.js
61
- var b = /* @__PURE__ */ new Set(), x = {
62
- emit(e) {
63
- b.forEach((t) => {
64
- try {
65
- t(e);
66
- } catch {}
67
- });
68
- },
69
- subscribe(e) {
70
- return b.add(e), () => b.delete(e);
71
- }
72
- }, S = ({ send: e, roomId: t }) => ({
73
- send: (n) => e(t, n),
74
- subscribe: (e) => x.subscribe((n) => {
75
- String(n.roomId) === String(t) && e(n);
76
- })
77
- }), ee = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, te = /^[0-9a-f]{16}$/, C = /^[0-9a-f]{32}$/, ne = /^[0-9a-f]{64}$/, re = (e) => typeof e == "object" && !!e && !Array.isArray(e), ie = (e) => typeof e == "string" && e.length > 0 && e.length <= 256 && e.trim() === e, w = (e) => typeof e == "string" && ee.test(e), T = (e, t, n) => Number.isInteger(e) && e >= t && e <= n, E = Object.freeze([
78
- "standard",
79
- "heavy",
80
- "cluster"
81
- ]), ae = (e) => T(e, 1, 120), oe = (e) => T(e.move, -16, 16) && T(e.yaw, 0, 359) && T(e.pitch, 5, 80) && T(e.power, 0, 100) && T(e.ammo, 0, E.length - 1);
82
- function se(e) {
83
- return Array.isArray(e) ? e[0] === 1 ? e.length === 6 && oe({
84
- move: e[1],
85
- yaw: e[2],
86
- pitch: e[3],
87
- power: e[4],
88
- ammo: e[5]
89
- }) : e[0] === 2 ? e.length === 1 : e[0] === 3 && e.length === 2 && (e[1] === 0 || e[1] === 1) : !1;
90
- }
91
- var D = (e) => Array.isArray(e.log) && e.log.length <= 120 && e.log.every(se) && w(e.head) && (e.accept_event_id === void 0 ? e.log.length === 0 && e.seed_b === void 0 && e.seed_a === void 0 : w(e.accept_event_id) && typeof e.seed_b == "string" && C.test(e.seed_b)) && (e.seed_a === void 0 ? e.log.length === 0 : C.test(e.seed_a) && w(e.seed_event_id));
92
- function O(e) {
93
- let t = e.data;
94
- switch (e.type) {
95
- case "game_invite": return ie(t.opponent_id) && t.rules_version === 1 && typeof t.seed_commit == "string" && ne.test(t.seed_commit) && (t.first_player_id === void 0 || ie(t.first_player_id)) && (t.rematch_of === void 0 || w(t.rematch_of));
96
- case "game_accept": return w(t.invite_event_id) && typeof t.seed_b == "string" && C.test(t.seed_b);
97
- case "game_decline": return w(t.invite_event_id);
98
- case "game_end": return t.reason === "closed";
99
- case "tk_seed": return typeof t.seed_a == "string" && C.test(t.seed_a);
100
- case "tk_turn": return ae(t.ply) && w(t.prev_event_id) && oe(t) && typeof t.hash == "string" && te.test(t.hash);
101
- case "tk_skip":
102
- case "tk_resign": return ae(t.ply) && w(t.prev_event_id);
103
- case "tk_sync_request": return re(t) && D(t);
104
- case "tk_sync_state": return re(t) && D(t) && w(t.request_event_id);
105
- default: return !1;
106
- }
107
- }
108
- // src/games/shared/protocol.js
109
- var ce = "LIRA_GAME_V1:", le = 4096, ue = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, de = (e) => typeof e == "object" && !!e && !Array.isArray(e), fe = (e) => typeof e == "string" && e.length > 0 && e.length <= 256 && e.trim() === e, k = (e) => typeof e == "string" && ue.test(e), pe = (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 && k(e[1])) && new Set(e.map((e) => e[1])).size === e.length, me = (e) => pe(e.moves) && e.rev === e.moves.length && (e.accept_event_id === void 0 ? e.moves.length === 0 : k(e.accept_event_id)), he = [
110
- "carrier",
111
- "battleship",
112
- "cruiser",
113
- "submarine",
114
- "destroyer"
115
- ], A = (e) => Number.isInteger(e) && e >= 0 && e < 10, ge = (e) => typeof e == "string" && /^[0-9a-f]{64}$/.test(e), _e = (e) => Number.isInteger(e) && e >= 1 && e <= 200, ve = (e) => e === null || de(e) && he.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 && A(e[0]) && A(e[1])), ye = (e) => Array.isArray(e) && e.length === he.length && e.every((e) => de(e) && he.includes(e.ship_id) && A(e.row) && A(e.col) && (e.orientation === "horizontal" || e.orientation === "vertical")) && new Set(e.map((e) => e.ship_id)).size === e.length, be = (e, t) => Array.isArray(e) && A(e[0]) && A(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] < he.length && A(e[4]) && A(e[5]) && (e[6] === 0 || e[6] === 1)), xe = (e) => Array.isArray(e.commits) && e.commits.length === 2 && e.commits.every((e) => e === null || ge(e)) && Array.isArray(e.log) && e.log.length <= 200 && e.log.every((t, n) => be(t, n === e.log.length - 1)) && k(e.head) && (e.accept_event_id === void 0 ? e.commits.every((e) => e === null) && e.log.length === 0 : k(e.accept_event_id)) && (e.log.length === 0 || e.commits.every(Boolean));
116
- function Se(e) {
117
- let t = e.data;
118
- switch (e.type) {
119
- case "game_invite": return fe(t.opponent_id) && t.rules_version === 1;
120
- case "game_accept":
121
- case "game_decline": return k(t.invite_event_id);
122
- case "game_end": return ["closed", "win"].includes(t.reason) && (t.winner_id === void 0 || fe(t.winner_id));
123
- case "bs_commit": return ge(t.commitment);
124
- case "bs_fire": return _e(t.ply) && A(t.row) && A(t.col) && k(t.prev_event_id);
125
- case "bs_result": return _e(t.ply) && A(t.row) && A(t.col) && ["hit", "miss"].includes(t.result) && ve(t.sunk) && typeof t.defeated == "boolean" && (t.result === "hit" || t.sunk === null && !t.defeated);
126
- case "bs_reveal": return ye(t.fleet) && typeof t.salt == "string" && /^[0-9a-f]{32}$/.test(t.salt);
127
- case "bs_sync_request": return xe(t);
128
- case "bs_sync_state": return xe(t) && k(t.request_event_id);
129
- default: return !1;
130
- }
131
- }
132
- function Ce(e) {
133
- return typeof e == "string" && e.startsWith("LIRA_GAME_V1:");
134
- }
135
- function we(e) {
136
- let t = e.data;
137
- switch (e.type) {
138
- case "game_invite": return fe(t.opponent_id) && t.rules_version === 1;
139
- case "game_accept":
140
- case "game_decline": return k(t.invite_event_id);
141
- case "game_move": return Number.isInteger(t.column) && t.column >= 0 && t.column < 7 && Number.isInteger(t.ply) && t.ply >= 1 && t.ply <= 42 && k(t.prev_event_id);
142
- case "game_end": return [
143
- "closed",
144
- "win",
145
- "draw"
146
- ].includes(t.reason) && (t.winner_id === void 0 || fe(t.winner_id)) && (t.final_move_event_id === void 0 || k(t.final_move_event_id)) && (t.reason !== "win" || fe(t.winner_id) && k(t.final_move_event_id)) && (t.reason !== "draw" || k(t.final_move_event_id));
147
- case "game_resync_request": return me(t);
148
- case "game_resync_state": return me(t) && k(t.request_event_id);
149
- default: return !1;
150
- }
151
- }
152
- var Te = {
153
- connect4: we,
154
- battleship: Se,
155
- tanks: O,
156
- tanks_live: _
157
- }, Ee = Object.freeze(Object.keys(Te));
158
- function De(e) {
159
- return !de(e) || e.version !== 1 || !Object.hasOwn(Te, e.game) || !k(e.game_id) || !k(e.event_id) || !de(e.data) ? !1 : Te[e.game](e);
160
- }
161
- function Oe(e) {
162
- if (!Ce(e) || e.length > le) return null;
163
- try {
164
- let t = JSON.parse(e.slice(13));
165
- return De(t) ? t : null;
166
- } catch {
167
- return null;
168
- }
169
- }
170
- function ke(e) {
171
- if (!De(e)) throw Error("Evento de juego inválido");
172
- let t = ce + JSON.stringify(e);
173
- if (t.length > le) throw Error("Evento de juego demasiado grande");
174
- return t;
175
- }
176
- function j(e, { game_id: t, data: n, event_id: r = m(), game: i = "connect4" }) {
177
- let a = {
178
- version: 1,
179
- game: i,
180
- game_id: t,
181
- event_id: r,
182
- type: e,
183
- data: n
184
- };
185
- if (!De(a)) throw Error("Evento de juego inválido");
186
- return a;
187
- }
188
- function Ae() {
189
- return Array.from({ length: 6 }, () => Array(7).fill(null));
190
- }
191
- var je = [
192
- [0, 1],
193
- [1, 0],
194
- [1, 1],
195
- [1, -1]
196
- ];
197
- function Me(e) {
198
- for (let t = 0; t < 6; t += 1) for (let n = 0; n < 7; n += 1) {
199
- let r = e[t][n];
200
- if (r != null) for (let [i, a] of je) {
201
- let o = [];
202
- for (let s = 0; s < 4; s += 1) {
203
- let c = t + i * s, l = n + a * s;
204
- if (c < 0 || c >= 6 || l < 0 || l >= 7 || e[c][l] !== r) break;
205
- o.push([c, l]);
206
- }
207
- if (o.length === 4) return o;
208
- }
209
- }
210
- return [];
211
- }
212
- function Ne(e) {
213
- let t = Me(e);
214
- return t.length ? e[t[0][0]][t[0][1]] : null;
215
- }
216
- function Pe(e) {
217
- return e[0].every((e) => e !== null);
218
- }
219
- function Fe(e, t, n) {
220
- if (!Number.isInteger(t) || t < 0 || t >= 7 || n == null || Ne(e) !== null) return null;
221
- let r = 5;
222
- for (; r >= 0 && e[r][t] !== null;) --r;
223
- if (r < 0) return null;
224
- let i = e.map((e) => e.slice());
225
- i[r][t] = n;
226
- let a = Me(i), o = a.length ? i[a[0][0]][a[0][1]] : null;
227
- return {
228
- board: i,
229
- row: r,
230
- column: t,
231
- winner: o,
232
- draw: o === null && Pe(i),
233
- winningCells: a
234
- };
235
- }
236
- // src/games/battleship/logic/game.js
237
- var Ie = (e) => typeof e == "string" && e.length > 0 && e.length <= 256 && e.trim() === e;
238
- function Le({ gameId: e, players: t, firstPlayerId: n = t?.[0] } = {}) {
239
- if (!Ie(e) || !Array.isArray(t) || t.length !== 2 || !t.every(Ie) || t[0] === t[1] || !t.includes(n)) throw TypeError("Supply a gameId, two distinct player IDs and a valid firstPlayerId.");
240
- return {
241
- game: "battleship",
242
- rulesVersion: 1,
243
- gameId: e,
244
- players: t.slice(),
245
- boards: [r(), r()],
246
- ready: [!1, !1],
247
- phase: "placement",
248
- turnId: null,
249
- firstPlayerId: n,
250
- winnerId: null,
251
- shotCount: 0,
252
- lastShot: null,
253
- revision: 0
254
- };
255
- }
256
- function Re(n, r) {
257
- 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;
258
- let o = n.players.indexOf(r.playerId);
259
- if (o < 0) return n;
260
- let s = n.boards[o];
261
- if (n.phase === "placement") {
262
- if (n.ready[o]) return n;
263
- if (r.type === "place_ship" || r.type === "remove_ship") {
264
- let e = r.type === "place_ship" ? a(s, r) : t(s, r.shipId);
265
- if (!e.ok) return n;
266
- let i = n.boards.slice();
267
- return i[o] = e.board, {
268
- ...n,
269
- boards: i,
270
- revision: n.revision + 1
271
- };
272
- }
273
- if (r.type === "ready" && e(s)) {
274
- let e = n.ready.slice();
275
- e[o] = !0;
276
- let t = e.every(Boolean);
277
- return {
278
- ...n,
279
- ready: e,
280
- phase: t ? "playing" : "placement",
281
- turnId: t ? n.firstPlayerId : null,
282
- revision: n.revision + 1
283
- };
284
- }
285
- return n;
286
- }
287
- if (n.phase !== "playing" || r.type !== "fire" || r.playerId !== n.turnId) return n;
288
- let c = 1 - o, l = i(n.boards[c], r);
289
- if (!l.ok) return n;
290
- let u = n.boards.slice();
291
- return u[c] = l.board, {
292
- ...n,
293
- boards: u,
294
- revision: n.revision + 1,
295
- shotCount: n.shotCount + 1,
296
- phase: l.defeated ? "finished" : "playing",
297
- turnId: l.defeated ? null : n.players[c],
298
- winnerId: l.defeated ? r.playerId : null,
299
- lastShot: {
300
- playerId: r.playerId,
301
- targetId: n.players[c],
302
- row: r.row,
303
- col: r.col,
304
- result: l.result,
305
- shipId: l.shipId,
306
- sunk: l.sunk,
307
- defeated: l.defeated
308
- }
309
- };
310
- }
311
- // src/games/battleship/net/session.js
312
- var ze = o.reduce((e, t) => e + t.size, 0), Be = /^[0-9a-f]{32}$/, Ve = [
313
- "won",
314
- "closed",
315
- "declined"
316
- ], M = "La partida perdió sincronización. Se intentará resincronizar.", He = "Falta la aceptación de la partida. Ciérrala y vuelve a invitar.", Ue = "El rival envió un resultado imposible para ese disparo.", We = "Tu flota no está disponible en este dispositivo; no se pueden responder disparos.", Ge = () => Array.from({ length: 10 }, () => Array(10).fill(null)), Ke = (e, t, n, r) => e.map((e, i) => i === t ? e.map((e, t) => t === n ? r : e) : e), qe = (e) => e.reduce((e, t) => e + t.filter((e) => e === "hit").length, 0), Je = (e) => e.reduce((e, t) => e + t.filter((e) => e !== null).length, 0), Ye = (e, t) => t % 2 == 1 ? e.hostId : e.guestId, Xe = (e, t) => t === e.hostId ? e.guestId : e.hostId, Ze = (e, t) => t === e.hostId ? "hostCommitment" : "guestCommitment", N = (e, t) => ({
317
- ...e,
318
- status: "conflict",
319
- error: t
320
- }), Qe = (e) => `${e.row},${e.col}`, $e = (e, t) => e.row - t.row || e.col - t.col, et = (e, t) => e.length === t.length && e.map(Qe).sort().join("|") === t.map(Qe).sort().join("|");
321
- function tt(e) {
322
- return {
323
- ...e,
324
- game: "battleship",
325
- status: "invited",
326
- turnId: null,
327
- myFleet: [],
328
- myReady: !1,
329
- opponentReady: !1,
330
- incomingShots: Ge(),
331
- targetShots: Ge(),
332
- sunkEnemyShips: [],
333
- pendingShot: null,
334
- lastShot: null,
335
- winnerId: null,
336
- verification: null,
337
- ply: 0,
338
- shots: [],
339
- acceptEventId: null,
340
- hostCommitment: null,
341
- guestCommitment: null,
342
- myCommitment: null,
343
- mySalt: null,
344
- myRevealSent: !1,
345
- opponentReveal: null,
346
- seen: e.seen ?? {},
347
- pending: !1,
348
- pendingEvent: null,
349
- error: "",
350
- sync: e.sync ?? null
351
- };
352
- }
353
- var nt = (e) => e?.game === "battleship" && ["invited", "placement"].includes(e.status) && !e.myReady, rt = (e) => e?.status === "active" && e.turnId === e.ownId && !e.pendingShot, it = (e) => ({
354
- id: e.id,
355
- size: e.size,
356
- orientation: e.orientation,
357
- cells: e.cells.map((e) => ({
358
- row: e.row,
359
- col: e.col
360
- }))
361
- }), at = (e) => ({
362
- shipId: e.id,
363
- row: e.cells[0].row,
364
- col: e.cells[0].col,
365
- orientation: e.orientation
366
- });
367
- function ot(e) {
368
- return !e || typeof e != "object" ? null : typeof e.ship_id == "string" ? {
369
- shipId: e.ship_id,
370
- row: e.row,
371
- col: e.col,
372
- orientation: e.orientation
373
- } : typeof e.id == "string" && Array.isArray(e.cells) && e.cells.length ? at(e) : null;
374
- }
375
- function st(e) {
376
- if (!Array.isArray(e)) return null;
377
- let t = r();
378
- for (let n of e) {
379
- let e = ot(n), r = e && a(t, e);
380
- if (!r?.ok) return null;
381
- t = r.board;
382
- }
383
- return t;
384
- }
385
- function ct(e) {
386
- if (!Array.isArray(e)) return null;
387
- let t = e.map(ot);
388
- return t.some((e) => !e) ? null : t.map(({ shipId: e, row: t, col: n, orientation: r }) => ({
389
- ship_id: e,
390
- row: t,
391
- col: n,
392
- orientation: r
393
- })).sort((e, t) => e.ship_id < t.ship_id ? -1 : +(e.ship_id > t.ship_id));
394
- }
395
- function lt(t) {
396
- let n = st(t);
397
- return n && e(n) ? n.ships.map(it) : null;
398
- }
399
- var ut = (e) => !!lt(e);
400
- function dt(t) {
401
- let n = st(t?.myFleet);
402
- return n && e(n) ? {
403
- ...n,
404
- shots: t.incomingShots.map((e) => e.slice())
405
- } : null;
406
- }
407
- function ft(e, { shipId: t, row: n, col: r, orientation: i } = {}) {
408
- if (!nt(e)) return e;
409
- let o = st(e.myFleet.filter((e) => e.id !== t)), s = o && a(o, {
410
- shipId: t,
411
- row: n,
412
- col: r,
413
- orientation: i
414
- });
415
- return s?.ok ? {
416
- ...e,
417
- myFleet: s.board.ships.map(it)
418
- } : e;
419
- }
420
- function pt(e, t) {
421
- return !nt(e) || !e.myFleet.some((e) => e.id === t) ? e : {
422
- ...e,
423
- myFleet: e.myFleet.filter((e) => e.id !== t)
424
- };
425
- }
426
- function mt(e) {
427
- let t = Math.floor(4294967296 / e) * e, n = /* @__PURE__ */ new Uint32Array(1);
428
- do
429
- globalThis.crypto.getRandomValues(n);
430
- while (n[0] >= t);
431
- return n[0] % e;
432
- }
433
- function ht(t = mt) {
434
- for (let n = 0; n < 50; n += 1) {
435
- let n = r();
436
- for (let e of o) for (let r = 0; r < 300; r += 1) {
437
- let r = a(n, {
438
- shipId: e.id,
439
- row: t(10),
440
- col: t(10),
441
- orientation: t(2) === 0 ? "horizontal" : "vertical"
442
- });
443
- if (r.ok) {
444
- n = r.board;
445
- break;
446
- }
447
- }
448
- if (e(n)) return n.ships.map(it);
449
- }
450
- throw Error("No se pudo generar una flota aleatoria.");
451
- }
452
- var gt = (e, t) => nt(e) ? {
453
- ...e,
454
- myFleet: ht(t)
455
- } : e, _t = (e) => Array.from(e, (e) => e.toString(16).padStart(2, "0")).join("");
456
- function vt() {
457
- let e = /* @__PURE__ */ new Uint8Array(16);
458
- return globalThis.crypto.getRandomValues(e), _t(e);
459
- }
460
- function yt(e, t) {
461
- let n = ct(e);
462
- if (!n || typeof t != "string") throw TypeError("Flota inválida");
463
- return JSON.stringify({
464
- fleet: n,
465
- salt: t
466
- });
467
- }
468
- async function bt(e, t) {
469
- let n = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(yt(e, t)));
470
- return _t(new Uint8Array(n));
471
- }
472
- function xt(e, t) {
473
- if (!e || !t) return null;
474
- let n = i(e, {
475
- row: t.row,
476
- col: t.col
477
- });
478
- if (!n.ok) return null;
479
- let r = n.sunk ? e.ships.find((e) => e.id === n.shipId) : null;
480
- return {
481
- ply: t.ply,
482
- row: t.row,
483
- col: t.col,
484
- result: n.result,
485
- sunk: r ? {
486
- ship_id: r.id,
487
- cells: r.cells.map((e) => [e.row, e.col])
488
- } : null,
489
- defeated: n.defeated
490
- };
491
- }
492
- function St(e) {
493
- let t = o.find((t) => t.id === e?.ship_id);
494
- if (!t || !Array.isArray(e.cells) || e.cells.length !== t.size) return null;
495
- let r = e.cells.map((e) => Array.isArray(e) ? {
496
- row: e[0],
497
- col: e[1]
498
- } : null);
499
- if (r.some((e) => !n(e))) return null;
500
- r.sort($e);
501
- 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);
502
- return !i && !a ? null : {
503
- id: t.id,
504
- size: t.size,
505
- orientation: i ? "horizontal" : "vertical",
506
- cells: r,
507
- sunk: !0
508
- };
509
- }
510
- function Ct(e, t) {
511
- let { row: n, col: r, result: i, sunk: a } = t, s = !!t.defeated;
512
- if (i !== "hit" && i !== "miss" || e.targetShots[n][r] !== null) return null;
513
- let c = Ke(e.targetShots, n, r, i), l = qe(c), u = null;
514
- if (a) {
515
- if (u = i === "hit" ? St(a) : null, !u || e.sunkEnemyShips.some((e) => e.id === u.id)) return null;
516
- let t = new Set(e.sunkEnemyShips.flatMap((e) => e.cells.map(Qe)));
517
- if (!u.cells.some((e) => e.row === n && e.col === r) || u.cells.some((e) => c[e.row][e.col] !== "hit" || t.has(Qe(e)))) return null;
518
- }
519
- let d = e.sunkEnemyShips.length + +!!u;
520
- return l > ze || s !== (l === ze) || s !== (d === o.length) || !s && ze - l > 100 - Je(c) ? null : {
521
- shots: c,
522
- ship: u
523
- };
524
- }
525
- function wt(e, t) {
526
- let n = xt(dt(e), t);
527
- if (!n || n.result !== t.result || n.defeated !== !!t.defeated || !!n.sunk != !!t.sunk) return null;
528
- let r = n.sunk ? St(n.sunk) : null;
529
- return r && (t.sunk.ship_id !== r.id || !et(r.cells, t.sunk.cells.map(([e, t]) => ({
530
- row: e,
531
- col: t
532
- })))) ? null : {
533
- shots: Ke(e.incomingShots, t.row, t.col, t.result),
534
- ship: r
535
- };
536
- }
537
- function Tt(e, t, n, r) {
538
- let i = Ze(e, t);
539
- if (e[i]) return e[i] === n ? e : null;
540
- let a = {
541
- ...e,
542
- [i]: n
543
- };
544
- if (t === e.ownId) {
545
- let t = r?.commitment === n ? lt(r.fleet) : null;
546
- t && Be.test(r.salt ?? "") ? a = {
547
- ...a,
548
- myFleet: t,
549
- mySalt: r.salt,
550
- myCommitment: n
551
- } : e.myCommitment === n && e.mySalt || (a = {
552
- ...a,
553
- myFleet: [],
554
- mySalt: null,
555
- myCommitment: n,
556
- error: We
557
- }), a.myReady = !0;
558
- } else a.opponentReady = !0;
559
- return a.hostCommitment && a.guestCommitment && (a = {
560
- ...a,
561
- status: "active",
562
- turnId: e.hostId,
563
- ply: 0,
564
- pendingShot: null
565
- }), a;
566
- }
567
- function Et(e, t, { row: r, col: i, ply: a }, o) {
568
- let s = t === e.ownId ? e.targetShots : e.incomingShots;
569
- return !n({
570
- row: r,
571
- col: i
572
- }) || s[r][i] !== null ? null : {
573
- ...e,
574
- pendingShot: {
575
- row: r,
576
- col: i,
577
- ply: a,
578
- by: t
579
- },
580
- lastEventId: o ?? e.lastEventId
581
- };
582
- }
583
- function Dt(e, t, n, r) {
584
- let i = e.pendingShot, a = t === e.ownId, o = a ? wt(e, n) : Ct(e, n);
585
- if (!o) return null;
586
- let s = !!n.defeated, c = {
587
- ply: i.ply,
588
- by: i.by,
589
- row: i.row,
590
- col: i.col,
591
- result: n.result,
592
- sunk: o.ship,
593
- defeated: s
594
- };
595
- return {
596
- ...e,
597
- incomingShots: a ? o.shots : e.incomingShots,
598
- targetShots: a ? e.targetShots : o.shots,
599
- sunkEnemyShips: !a && o.ship ? [...e.sunkEnemyShips, o.ship] : e.sunkEnemyShips,
600
- ply: i.ply,
601
- shots: [...e.shots, c],
602
- pendingShot: null,
603
- lastShot: {
604
- ...c,
605
- eventId: r ?? null
606
- },
607
- lastEventId: r ?? e.lastEventId,
608
- turnId: s ? null : t,
609
- status: s ? "won" : "active",
610
- winnerId: s ? i.by : null,
611
- verification: s ? "pending" : e.verification
612
- };
613
- }
614
- function Ot(e, t, n) {
615
- let { ply: r, row: i, col: a, prev_event_id: o } = t.data;
616
- return n === Ye(e, r) ? e.status === "active" ? r <= e.ply ? e : e.pendingShot ? r === e.pendingShot.ply ? e : N(e, M) : r > e.ply + 1 ? N(e, M) : n === e.turnId ? o === e.lastEventId ? Et(e, n, {
617
- row: i,
618
- col: a,
619
- ply: r
620
- }, t.event_id) ?? e : N(e, M) : e : N(e, e.status === "invited" ? He : M) : e;
621
- }
622
- function kt(e, t, n) {
623
- let { ply: r, row: i, col: a } = t.data;
624
- if (e.status !== "active") return e.status === "placement" ? N(e, M) : e;
625
- let o = e.pendingShot;
626
- return o ? r === o.ply ? n === o.by ? e : i !== o.row || a !== o.col ? n === e.ownId ? e : N(e, "El rival respondió a un disparo distinto.") : Dt(e, n, t.data, t.event_id) || (n === e.ownId ? e : N(e, Ue)) : r < o.ply ? e : N(e, M) : r <= e.ply ? e : N(e, M);
627
- }
628
- function At(e, t, n) {
629
- return !e.winnerId || !["won", "closed"].includes(e.status) ? e : n === e.ownId ? e.myRevealSent ? e : {
630
- ...e,
631
- myRevealSent: !0
632
- } : e.opponentReveal ? e : {
633
- ...e,
634
- opponentReveal: {
635
- fleet: t.fleet.map((e) => ({ ...e })),
636
- salt: t.salt
637
- },
638
- verification: "pending"
639
- };
640
- }
641
- function jt(e, t, n, r = {}) {
642
- if (!e || e.game !== "battleship" || t?.game !== "battleship" || t.game_id !== e.gameId || n !== e.hostId && n !== e.guestId) return e;
643
- let i = t.data;
644
- if (t.type === "game_end") return i.reason !== "closed" || [
645
- "closed",
646
- "declined",
647
- "won"
648
- ].includes(e.status) ? e : {
649
- ...e,
650
- status: "closed",
651
- closedBy: n,
652
- error: ""
653
- };
654
- if (t.type === "bs_reveal") return At(e, i, n);
655
- if (Ve.includes(e.status) || e.status === "conflict") return e;
656
- switch (t.type) {
657
- case "game_accept":
658
- case "game_decline": return n !== e.guestId || e.status !== "invited" || i.invite_event_id !== e.inviteEventId ? e : t.type === "game_accept" ? {
659
- ...e,
660
- status: "placement",
661
- acceptEventId: t.event_id,
662
- lastEventId: t.event_id
663
- } : {
664
- ...e,
665
- status: "declined",
666
- lastEventId: t.event_id
667
- };
668
- case "bs_commit": return e.status === "invited" ? N(e, He) : e.status === "placement" ? Tt(e, n, i.commitment, r.stored) ?? e : e;
669
- case "bs_fire": return Ot(e, t, n);
670
- case "bs_result": return kt(e, t, n);
671
- default: return e;
672
- }
673
- }
674
- function Mt(e, t) {
675
- let n = Le({
676
- gameId: String(e.gameId),
677
- players: [e.hostId, e.guestId],
678
- firstPlayerId: e.hostId
679
- });
680
- for (let e of n.players) {
681
- for (let r of t[e]) n = Re(n, {
682
- type: "place_ship",
683
- playerId: e,
684
- ...at(r)
685
- });
686
- n = Re(n, {
687
- type: "ready",
688
- playerId: e
689
- });
690
- }
691
- if (n.phase !== "playing") return !1;
692
- for (let t of e.shots) {
693
- let e = Re(n, {
694
- type: "fire",
695
- playerId: t.by,
696
- row: t.row,
697
- col: t.col
698
- });
699
- if (e === n) return !1;
700
- let r = e.lastShot;
701
- if (r.result !== t.result || r.defeated !== t.defeated || r.sunk !== !!t.sunk) return !1;
702
- if (t.sunk) {
703
- let n = e.boards[e.players.indexOf(r.targetId)].ships.find((e) => e.id === r.shipId);
704
- if (t.sunk.id !== r.shipId || !et(n.cells, t.sunk.cells)) return !1;
705
- }
706
- n = e;
707
- }
708
- return !e.winnerId || n.winnerId === e.winnerId;
709
- }
710
- async function Nt(e, t = e?.opponentReveal) {
711
- if (!e || !t) return "pending";
712
- let n = Xe(e, e.ownId), r = e[Ze(e, n)], i = lt(t.fleet);
713
- if (!r || !i || typeof t.salt != "string" || !Be.test(t.salt)) return "mismatch";
714
- let a;
715
- try {
716
- a = await bt(t.fleet, t.salt);
717
- } catch {
718
- return "mismatch";
719
- }
720
- if (a !== r) return "mismatch";
721
- let o = lt(e.myFleet);
722
- return o ? Mt(e, {
723
- [e.ownId]: o,
724
- [n]: i
725
- }) ? "ok" : "mismatch" : "pending";
726
- }
727
- var Pt = (e) => {
728
- if (e.result === "miss") return [
729
- e.row,
730
- e.col,
731
- 0
732
- ];
733
- if (!e.sunk) return [
734
- e.row,
735
- e.col,
736
- 1
737
- ];
738
- let t = e.sunk.cells[0];
739
- return [
740
- e.row,
741
- e.col,
742
- 2,
743
- o.findIndex((t) => t.id === e.sunk.id),
744
- t.row,
745
- t.col,
746
- +(e.sunk.orientation === "vertical")
747
- ];
748
- };
749
- function Ft(e) {
750
- if (!e.acceptEventId) return {
751
- commits: [null, null],
752
- log: [],
753
- head: e.inviteEventId
754
- };
755
- let t = e.shots.map(Pt);
756
- return e.pendingShot && t.push([e.pendingShot.row, e.pendingShot.col]), {
757
- accept_event_id: e.acceptEventId,
758
- commits: [e.hostCommitment ?? null, e.guestCommitment ?? null],
759
- log: t,
760
- head: e.lastEventId
761
- };
762
- }
763
- function It(e, t) {
764
- let n = e.accept_event_id ?? null, r = t.accept_event_id ?? null;
765
- if (n && r && n !== r) return "diverged";
766
- let i = /* @__PURE__ */ new Set();
767
- n && !r && i.add("ahead"), !n && r && i.add("behind");
768
- for (let n of [0, 1]) {
769
- let r = e.commits?.[n] ?? null, a = t.commits?.[n] ?? null;
770
- if (r && a && r !== a) return "diverged";
771
- r && !a && i.add("ahead"), !r && a && i.add("behind");
772
- }
773
- let a = e.log ?? [], o = t.log ?? [];
774
- for (let e = 0; e < Math.min(a.length, o.length); e += 1) {
775
- let t = a[e], n = o[e];
776
- if (t.length === n.length) {
777
- if (t.some((e, t) => e !== n[t])) return "diverged";
778
- } else if (t[0] !== n[0] || t[1] !== n[1]) return "diverged";
779
- else i.add(t.length === 2 ? "behind" : "ahead");
780
- }
781
- 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";
782
- }
783
- function Lt(e, t) {
784
- if ((e.log ?? []).length || (t.log ?? []).length) return null;
785
- let n = e.accept_event_id ?? t.accept_event_id;
786
- return n ? {
787
- accept_event_id: n,
788
- commits: [0, 1].map((n) => e.commits?.[n] ?? t.commits?.[n] ?? null),
789
- log: [],
790
- head: n
791
- } : null;
792
- }
793
- function Rt(e, t, n = {}) {
794
- let r = {
795
- ...e,
796
- status: "invited",
797
- turnId: null,
798
- myReady: !1,
799
- opponentReady: !1,
800
- incomingShots: Ge(),
801
- targetShots: Ge(),
802
- sunkEnemyShips: [],
803
- pendingShot: null,
804
- lastShot: null,
805
- winnerId: null,
806
- verification: null,
807
- ply: 0,
808
- shots: [],
809
- acceptEventId: null,
810
- hostCommitment: null,
811
- guestCommitment: null,
812
- error: "",
813
- myRevealSent: !1,
814
- opponentReveal: null,
815
- closedBy: void 0
816
- }, i = t.log ?? [], a = t.commits ?? [null, null];
817
- if (!t.accept_event_id) return a.some(Boolean) || i.length ? null : {
818
- ...r,
819
- lastEventId: e.inviteEventId
820
- };
821
- if (t.accept_event_id === e.inviteEventId) return null;
822
- let s = e.ownId === e.hostId ? 0 : 1;
823
- if (e.myCommitment && a[s] && a[s] !== e.myCommitment && n.stored?.commitment !== a[s]) return null;
824
- let c = {
825
- ...r,
826
- status: "placement",
827
- acceptEventId: t.accept_event_id,
828
- lastEventId: t.accept_event_id
829
- };
830
- for (let [t, r] of [e.hostId, e.guestId].entries()) if (a[t] && (c = Tt(c, r, a[t], n.stored), !c)) return null;
831
- if (i.length && c.status !== "active") return null;
832
- for (let e = 0; e < i.length; e += 1) {
833
- let t = i[e], n = e + 1;
834
- if (c = Et(c, Ye(c, n), {
835
- row: t[0],
836
- col: t[1],
837
- ply: n
838
- }, null), !c) return null;
839
- if (t.length === 2) {
840
- if (e !== i.length - 1) return null;
841
- break;
842
- }
843
- let r = Xe(c, c.pendingShot.by), a = null;
844
- if (t[2] === 2) {
845
- let e = o[t[3]];
846
- if (!e) return null;
847
- let n = t[6] === 1;
848
- a = {
849
- ship_id: e.id,
850
- cells: Array.from({ length: e.size }, (e, r) => [t[4] + (n ? r : 0), t[5] + (n ? 0 : r)])
851
- };
852
- }
853
- let s = qe(r === c.ownId ? c.incomingShots : c.targetShots) + (t[2] === 0 ? 0 : 1);
854
- if (c = Dt(c, r, {
855
- ply: n,
856
- row: t[0],
857
- col: t[1],
858
- result: t[2] === 0 ? "miss" : "hit",
859
- sunk: a,
860
- defeated: s === ze
861
- }, null), !c || c.status === "won" && e !== i.length - 1) return null;
862
- }
863
- return !i.length && t.head !== t.accept_event_id ? null : (c = {
864
- ...c,
865
- lastEventId: t.head
866
- }, c.winnerId && e.winnerId === c.winnerId && (c = {
867
- ...c,
868
- myRevealSent: e.myRevealSent,
869
- opponentReveal: e.opponentReveal,
870
- verification: e.verification
871
- }), c);
872
- }
873
- function zt(e, t) {
874
- if (!e || !t) return !1;
875
- let n = e.log?.[(t.data?.ply ?? 0) - 1];
876
- switch (t.type) {
877
- case "game_accept": return e.accept_event_id === t.event_id;
878
- case "bs_commit": return (e.commits ?? []).includes(t.data.commitment);
879
- case "bs_fire": return !!(n && n[0] === t.data.row && n[1] === t.data.col);
880
- case "bs_result": return !!(n && n.length > 2 && n[0] === t.data.row && n[1] === t.data.col);
881
- default: return !1;
882
- }
883
- }
884
- function Bt(e, t) {
885
- let n = { ...e };
886
- return t.acceptEventId && (n[t.acceptEventId] = !0), t.lastEventId && (n[t.lastEventId] = !0), n;
887
- }
888
- // src/games/battleship/net/fleetStorage.js
889
- var Vt = "lira:bs:", Ht = 12096e5, Ut = (e, t) => `${Vt}${e}:${t}`, Wt = () => {
890
- try {
891
- return globalThis.localStorage ?? null;
892
- } catch {
893
- return null;
894
- }
895
- };
896
- function Gt(e) {
897
- 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);
898
- }
899
- function Kt(e) {
900
- let t = Date.now();
901
- for (let n = e.length - 1; n >= 0; --n) {
902
- let r = e.key(n);
903
- if (r?.startsWith(Vt)) try {
904
- let n = JSON.parse(e.getItem(r));
905
- Gt(n) && t - n.savedAt < Ht || e.removeItem(r);
906
- } catch {
907
- e.removeItem(r);
908
- }
909
- }
910
- }
911
- function qt(e, t, { fleet: n, salt: r, commitment: i }) {
912
- try {
913
- let a = Wt();
914
- return a ? (Kt(a), a.setItem(Ut(e, t), JSON.stringify({
915
- fleet: n,
916
- salt: r,
917
- commitment: i,
918
- savedAt: Date.now()
919
- })), !0) : !1;
920
- } catch {
921
- return !1;
922
- }
923
- }
924
- function Jt(e, t) {
925
- try {
926
- let n = JSON.parse(Wt()?.getItem(Ut(e, t)) ?? "null");
927
- return Gt(n) ? {
928
- fleet: n.fleet,
929
- salt: n.salt,
930
- commitment: n.commitment
931
- } : null;
932
- } catch {
933
- return null;
934
- }
935
- }
936
- // src/games/tanks/logic/constants.js
937
- var P = 1e5, Yt = 160 * P, F = 2 * P, Xt = 20 * P;
938
- 2 * P;
939
- var Zt = 1 * P;
940
- 4 * P, 4 * P;
941
- var Qt = 18e4, $t = 25e4, en = 5e4, I = 25e3, tn = 60 * P, nn = 4 * P, L = Object.freeze({
942
- move: Object.freeze([-16, 16]),
943
- yaw: Object.freeze([0, 359]),
944
- pitch: Object.freeze([5, 80]),
945
- power: Object.freeze([0, 100])
946
- }), R = Object.freeze({
947
- standard: Object.freeze({
948
- id: "standard",
949
- cost: 0,
950
- radius: 6 * P,
951
- maxDmg: 40,
952
- depth: 15e4,
953
- speedPct: 100
954
- }),
955
- heavy: Object.freeze({
956
- id: "heavy",
957
- cost: 1,
958
- radius: 8 * P,
959
- maxDmg: 55,
960
- depth: 25e4,
961
- speedPct: 85
962
- }),
963
- cluster: Object.freeze({
964
- id: "cluster",
965
- cost: 1,
966
- radius: 4 * P,
967
- maxDmg: 15,
968
- depth: 8e4,
969
- speedPct: 100
970
- })
971
- }), rn = Object.freeze({
972
- radius: 4 * P,
973
- maxDmg: 15,
974
- depth: 8e4
975
- }), an = Object.freeze([
976
- Object.freeze([
977
- 0,
978
- 0,
979
- 0
980
- ]),
981
- Object.freeze([
982
- 6e3,
983
- 0,
984
- 0
985
- ]),
986
- Object.freeze([
987
- -6e3,
988
- 0,
989
- 0
990
- ]),
991
- Object.freeze([
992
- 0,
993
- 0,
994
- 6e3
995
- ]),
996
- Object.freeze([
997
- 0,
998
- 0,
999
- -6e3
1000
- ])
1001
- ]), on = Object.freeze({
1002
- heavy: 2,
1003
- cluster: 2
1004
- }), sn = Object.freeze([
1005
- 0,
1006
- 17452,
1007
- 34899,
1008
- 52336,
1009
- 69756,
1010
- 87156,
1011
- 104528,
1012
- 121869,
1013
- 139173,
1014
- 156434,
1015
- 173648,
1016
- 190809,
1017
- 207912,
1018
- 224951,
1019
- 241922,
1020
- 258819,
1021
- 275637,
1022
- 292372,
1023
- 309017,
1024
- 325568,
1025
- 342020,
1026
- 358368,
1027
- 374607,
1028
- 390731,
1029
- 406737,
1030
- 422618,
1031
- 438371,
1032
- 453990,
1033
- 469472,
1034
- 484810,
1035
- 5e5,
1036
- 515038,
1037
- 529919,
1038
- 544639,
1039
- 559193,
1040
- 573576,
1041
- 587785,
1042
- 601815,
1043
- 615661,
1044
- 629320,
1045
- 642788,
1046
- 656059,
1047
- 669131,
1048
- 681998,
1049
- 694658,
1050
- 707107,
1051
- 719340,
1052
- 731354,
1053
- 743145,
1054
- 754710,
1055
- 766044,
1056
- 777146,
1057
- 788011,
1058
- 798636,
1059
- 809017,
1060
- 819152,
1061
- 829038,
1062
- 838671,
1063
- 848048,
1064
- 857167,
1065
- 866025,
1066
- 874620,
1067
- 882948,
1068
- 891007,
1069
- 898794,
1070
- 906308,
1071
- 913545,
1072
- 920505,
1073
- 927184,
1074
- 933580,
1075
- 939693,
1076
- 945519,
1077
- 951057,
1078
- 956305,
1079
- 961262,
1080
- 965926,
1081
- 970296,
1082
- 974370,
1083
- 978148,
1084
- 981627,
1085
- 984808,
1086
- 987688,
1087
- 990268,
1088
- 992546,
1089
- 994522,
1090
- 996195,
1091
- 997564,
1092
- 998630,
1093
- 999391,
1094
- 999848,
1095
- 1e6
1096
- ]), cn = 1e6;
1097
- function ln(e) {
1098
- let t = (e % 360 + 360) % 360;
1099
- return t <= 90 ? sn[t] : t <= 180 ? sn[180 - t] : t <= 270 ? -sn[t - 180] : -sn[360 - t];
1100
- }
1101
- function un(e) {
1102
- return ln(e + 90);
1103
- }
1104
- function z(e, t) {
1105
- return Math.trunc(e * t / cn);
1106
- }
1107
- // src/games/tanks/logic/rng.js
1108
- var dn = (e) => Number.isInteger(e) && e >= 0 && e <= 4294967295;
1109
- function fn(e) {
1110
- let t = e >>> 0;
1111
- return function() {
1112
- t = t + 1831565813 >>> 0;
1113
- let e = t;
1114
- return e = Math.imul(e ^ e >>> 15, e | 1), e ^= e + Math.imul(e ^ e >>> 7, e | 61), (e ^ e >>> 14) >>> 0;
1115
- };
1116
- }
1117
- function B(e, t, n) {
1118
- return t + e() % (n - t + 1);
1119
- }
1120
- function pn(e, t) {
1121
- let n = fn((e ^ Math.imul(t, 2654435761)) >>> 0);
1122
- return {
1123
- x: B(n, -40, 40),
1124
- z: B(n, -40, 40)
1125
- };
1126
- }
1127
- // src/games/tanks/logic/terrain.js
1128
- var V = (e, t, n) => e < t ? t : e > n ? n : e, H = (e, t, n, r) => e + Math.trunc((t - e) * n / r);
1129
- function U(e, t, n) {
1130
- let r = V(t, 0, Yt), i = V(n, 0, Yt), a = Math.min(Math.trunc(r / F), 79), o = Math.min(Math.trunc(i / F), 79), s = r - a * F, c = i - o * F, l = o * 81;
1131
- return H(H(e[l + a], e[l + a + 1], s, F), H(e[l + 81 + a], e[l + 81 + a + 1], s, F), c, F);
1132
- }
1133
- function mn(e, t, n, r) {
1134
- let i = Math.trunc(80 / t) + 1, a = [];
1135
- for (let t = 0; t < i * i; t += 1) a.push(B(e, n, r) * 1e3);
1136
- return {
1137
- n: i,
1138
- step: t,
1139
- values: a
1140
- };
1141
- }
1142
- function hn({ n: e, step: t, values: n }, r, i) {
1143
- let a = Math.min(Math.trunc(r / t), e - 2), o = Math.min(Math.trunc(i / t), e - 2), s = r - a * t, c = i - o * t, l = (t, r) => n[r * e + t];
1144
- return H(H(l(a, o), l(a + 1, o), s, t), H(l(a, o + 1), l(a + 1, o + 1), s, t), c, t);
1145
- }
1146
- function gn(e) {
1147
- let t = new Int32Array(e.length);
1148
- for (let n = 0; n < 81; n += 1) for (let r = 0; r < 81; r += 1) {
1149
- let i = 0;
1150
- for (let t = -1; t <= 1; t += 1) for (let a = -1; a <= 1; a += 1) i += e[V(n + t, 0, 80) * 81 + V(r + a, 0, 80)];
1151
- t[n * 81 + r] = Math.trunc(i / 9);
1152
- }
1153
- return t;
1154
- }
1155
- function _n(e, t, n, r, i) {
1156
- let a = U(e, t, n), o = r * r, s = i * i;
1157
- for (let r = 0; r < 81; r += 1) for (let c = 0; c < 81; c += 1) {
1158
- let l = c * F - t, u = r * F - n;
1159
- if (l > i || l < -i || u > i || u < -i) continue;
1160
- let d = l * l + u * u;
1161
- if (d >= s) continue;
1162
- let f = r * 81 + c;
1163
- if (d <= o) e[f] = a;
1164
- else {
1165
- let t = Math.trunc((d - o) * 1e3 / (s - o));
1166
- e[f] = a + Math.trunc((e[f] - a) * t / 1e3);
1167
- }
1168
- }
1169
- }
1170
- var W = (e, t, n) => B(e, t, n) * (P / 2), vn = (e, t, n, r, i) => {
1171
- let a = e - n, o = t - r;
1172
- return a > i || a < -i || o > i || o < -i ? !1 : a * a + o * o < i * i;
1173
- }, yn = (e, t, n, r) => t >= e.x - e.w / 2 - r && t <= e.x + e.w / 2 + r && n >= e.z - e.d / 2 - r && n <= e.z + e.d / 2 + r;
1174
- function bn(e) {
1175
- let t = fn(e), n = mn(t, 20, 0, 1200), r = mn(t, 10, -250, 250), i = mn(t, 4, -60, 60), a = /* @__PURE__ */ new Int32Array(6561);
1176
- for (let e = 0; e < 81; e += 1) for (let t = 0; t < 81; t += 1) {
1177
- let o = 3 * P + hn(n, t, e) + hn(r, t, e) + hn(i, t, e);
1178
- a[e * 81 + t] = V(o, 0, Xt);
1179
- }
1180
- a = gn(gn(a));
1181
- let o = [{
1182
- x: 20 * P + W(t, -4, 4),
1183
- z: 80 * P + W(t, -40, 40)
1184
- }, {
1185
- x: 140 * P + W(t, -4, 4),
1186
- z: 80 * P + W(t, -40, 40)
1187
- }];
1188
- for (let e of o) _n(a, e.x, e.z, nn, nn + 3 * P);
1189
- let s = [], c = B(t, 4, 6);
1190
- for (let e = 0; e < 200 && s.length < c; e += 1) {
1191
- let e = t() % 2 == 0 ? "rock" : "wall", n = W(t, 4, 12), r = W(t, 4, 12);
1192
- e === "wall" && (n >= r ? r = 2 * P : n = 2 * P);
1193
- let i = W(t, 4, 10), c = W(t, 100, 220), l = W(t, 40, 280), u = 12 * P + (n > r ? n : r);
1194
- if (o.some((e) => vn(e.x, e.z, c, l, u))) continue;
1195
- let d = {
1196
- x: c,
1197
- z: l,
1198
- w: n,
1199
- d: r
1200
- };
1201
- if (s.some((e) => yn(e, c, l, (n > r ? n : r) + 4e5))) continue;
1202
- let f = [
1203
- [-1, -1],
1204
- [1, -1],
1205
- [-1, 1],
1206
- [1, 1]
1207
- ].map(([e, t]) => U(a, c + e * n / 2, l + t * r / 2)), p = Math.min(U(a, c, l), ...f);
1208
- s.push({
1209
- id: s.length,
1210
- kind: e,
1211
- ...d,
1212
- h: i,
1213
- y: p
1214
- });
1215
- }
1216
- let l = [], u = B(t, 30, 60);
1217
- for (let e = 0; e < u * 10 && l.length < u; e += 1) {
1218
- let e = W(t, 4, 316), n = W(t, 4, 316), r = t() % 3 == 0 ? "rock" : "tree", i = B(t, 80, 140);
1219
- o.some((t) => vn(t.x, t.z, e, n, 1e6)) || s.some((t) => yn(t, e, n, 2e5)) || l.push({
1220
- id: l.length,
1221
- kind: r,
1222
- x: e,
1223
- z: n,
1224
- scale: i
1225
- });
1226
- }
1227
- return {
1228
- heights: a,
1229
- spawns: o,
1230
- obstacles: s,
1231
- decor: l
1232
- };
1233
- }
1234
- function xn(e, { x: t, z: n, radius: r, depth: i }) {
1235
- let a = r * r, o = (e) => V(Math.trunc(e / F) - 1, 0, 80);
1236
- for (let s = o(n - r); s <= o(n + r) + 2 && s < 81; s += 1) for (let c = o(t - r); c <= o(t + r) + 2 && c < 81; c += 1) {
1237
- let o = c * F - t, l = s * F - n;
1238
- if (o > r || o < -r || l > r || l < -r) continue;
1239
- let u = o * o + l * l;
1240
- if (u >= a) continue;
1241
- let d = Math.trunc((a - u) * 4096 / a), f = s * 81 + c, p = e[f] - Math.trunc(i * d / 4096);
1242
- e[f] = p < 0 ? 0 : p;
1243
- }
1244
- return e;
1245
- }
1246
- function Sn(e, t) {
1247
- return e.filter((e) => !t.some((t) => vn(t.x, t.z, e.x, e.z, t.radius)));
1248
- }
1249
- // src/games/tanks/logic/ballistics.js
1250
- function Cn(e, t) {
1251
- return Math.trunc((2e4 + 600 * e) * R[t].speedPct / 100);
1252
- }
1253
- function wn(e, { yaw: t, pitch: n, power: r, ammo: i }) {
1254
- let a = un(n), o = ln(n), s = un(t), c = ln(t), l = z($t, a), u = Cn(r, i), d = z(u, a);
1255
- return {
1256
- x: e.x + z(l, s),
1257
- y: e.y + Qt + z($t, o),
1258
- z: e.z + z(l, c),
1259
- vx: z(d, s),
1260
- vy: z(u, o),
1261
- vz: z(d, c)
1262
- };
1263
- }
1264
- function Tn(e, t, n, r, i, a, o) {
1265
- let s = e - r, c = t - i, l = n - a;
1266
- return s > o || s < -o || c > o || c < -o || l > o || l < -o ? !1 : s * s + c * c + l * l < o * o;
1267
- }
1268
- function En(e, { wind: t, heights: n, tanks: r, obstacles: i, maxTicks: a = 600, split: o = !1 }) {
1269
- let { x: s, y: c, z: l, vx: u, vy: d, vz: f } = e, p = [
1270
- s,
1271
- c,
1272
- l
1273
- ];
1274
- for (let e = 1; e <= a; e += 1) {
1275
- let a = d;
1276
- u += t.x, d -= 392, f += t.z, s += u, c += d, l += f;
1277
- let m = null;
1278
- for (let e of r) if (Tn(s, c, l, e.x, e.y + 1e5, e.z, 2e5)) {
1279
- m = {
1280
- x: s,
1281
- y: c,
1282
- z: l,
1283
- kind: "tank",
1284
- tankId: e.id
1285
- };
1286
- break;
1287
- }
1288
- if (!m) {
1289
- let e = i.find((e) => c <= e.y + e.h && yn(e, s, l, 0));
1290
- e && (m = {
1291
- x: s,
1292
- y: c,
1293
- z: l,
1294
- kind: "obstacle",
1295
- obstacleId: e.id
1296
- });
1297
- }
1298
- if (!m && (s < 0 || s > 16e6 || l < 0 || l > 16e6) && (m = {
1299
- x: s,
1300
- y: c,
1301
- z: l,
1302
- kind: "out"
1303
- }), !m) {
1304
- let e = U(n, s, l);
1305
- c <= e && (m = {
1306
- x: s,
1307
- y: e,
1308
- z: l,
1309
- kind: "terrain"
1310
- });
1311
- }
1312
- if (!m && o && a > 0 && d <= 0 && (m = {
1313
- x: s,
1314
- y: c,
1315
- z: l,
1316
- kind: "split"
1317
- }), m) return p.push(m.x, m.y, m.z), {
1318
- samples: p,
1319
- ticks: e,
1320
- impact: m,
1321
- velocity: {
1322
- vx: u,
1323
- vy: d,
1324
- vz: f
1325
- }
1326
- };
1327
- e % 2 == 0 && p.push(s, c, l);
1328
- }
1329
- return {
1330
- samples: p,
1331
- ticks: a,
1332
- impact: {
1333
- x: s,
1334
- y: c,
1335
- z: l,
1336
- kind: "out"
1337
- },
1338
- velocity: {
1339
- vx: u,
1340
- vy: d,
1341
- vz: f
1342
- }
1343
- };
1344
- }
1345
- var Dn = (e, t, n, r) => ({
1346
- role: e,
1347
- startTick: t,
1348
- samples: n.samples,
1349
- ticks: n.ticks,
1350
- impact: n.impact,
1351
- radius: n.impact.kind === "split" ? 0 : r.radius,
1352
- maxDmg: n.impact.kind === "split" ? 0 : r.maxDmg,
1353
- depth: n.impact.kind === "split" ? 0 : r.depth
1354
- });
1355
- function On(e, t, n) {
1356
- let r = wn(e, t);
1357
- if (t.ammo !== "cluster") return [Dn("main", 0, En(r, n), R[t.ammo])];
1358
- let i = En(r, {
1359
- ...n,
1360
- split: !0
1361
- }), a = [Dn("carrier", 0, i, rn)];
1362
- if (i.impact.kind !== "split") return a;
1363
- let o = (n.maxTicks ?? 600) - i.ticks;
1364
- for (let [e, t, r] of an) {
1365
- let { x: s, y: c, z: l } = i.impact, { vx: u, vy: d, vz: f } = i.velocity, p = En({
1366
- x: s,
1367
- y: c,
1368
- z: l,
1369
- vx: u + e,
1370
- vy: d + t,
1371
- vz: f + r
1372
- }, {
1373
- ...n,
1374
- maxTicks: o,
1375
- split: !1
1376
- });
1377
- a.push(Dn("bomblet", i.ticks, p, rn));
1378
- }
1379
- return a;
1380
- }
1381
- function kn(e, t) {
1382
- let n = t.map(() => 0);
1383
- for (let r of e) {
1384
- let { impact: e, radius: i, maxDmg: a } = r;
1385
- if (e.kind === "out" || e.kind === "split") continue;
1386
- let o = i * i;
1387
- t.forEach((t, r) => {
1388
- let s = t.y + Zt;
1389
- e.kind === "tank" && e.tankId === t.id && (n[r] += 25);
1390
- let c = e.x - t.x, l = e.y - s, u = e.z - t.z;
1391
- if (c >= i || c <= -i || l >= i || l <= -i || u >= i || u <= -i) return;
1392
- let d = c * c + l * l + u * u;
1393
- d < o && (n[r] += Math.trunc(a * (o - d) / o));
1394
- });
1395
- }
1396
- return n;
1397
- }
1398
- function An(e) {
1399
- return e.filter((e) => e.impact.kind !== "out" && e.impact.kind !== "split").map((e) => ({
1400
- x: e.impact.x,
1401
- z: e.impact.z,
1402
- radius: e.radius,
1403
- depth: e.depth
1404
- }));
1405
- }
1406
- // src/games/tanks/logic/movement.js
1407
- function jn(e, t, { heights: n, obstacles: r, others: i }) {
1408
- let a = t < 0 ? -1 : 1, o = (t < 0 ? -t : t) * (en / I), s = Math.min(o, Math.trunc(e.fuel / I)), c = a * z(I, un(e.hullYaw)), l = a * z(I, ln(e.hullYaw)), { x: u, z: d } = e, f = U(n, u, d), p = [{
1409
- x: u,
1410
- y: f,
1411
- z: d
1412
- }], m = 0, h = s < o ? "fuel" : null;
1413
- for (let e = 0; e < s; e += 1) {
1414
- let e = u + c, t = d + l;
1415
- if (e < 4e5 || e > 156e5 || t < 4e5 || t > 156e5) {
1416
- h = "border";
1417
- break;
1418
- }
1419
- if (r.some((n) => yn(n, e, t, 2e5))) {
1420
- h = "obstacle";
1421
- break;
1422
- }
1423
- if (i.some((n) => {
1424
- let r = n.x - e, i = n.z - t;
1425
- return r * r + i * i < 16e10;
1426
- })) {
1427
- h = "tank";
1428
- break;
1429
- }
1430
- let a = U(n, e, t);
1431
- if ((a > f ? a - f : f - a) * 1e3 > 175e5) {
1432
- h = "slope";
1433
- break;
1434
- }
1435
- u = e, d = t, f = a, m += 1, m % 2 == 0 && p.push({
1436
- x: u,
1437
- y: f,
1438
- z: d
1439
- });
1440
- }
1441
- return m % 2 == 1 && p.push({
1442
- x: u,
1443
- y: f,
1444
- z: d
1445
- }), {
1446
- path: p,
1447
- x: u,
1448
- y: f,
1449
- z: d,
1450
- used: m * I,
1451
- stop: h
1452
- };
1453
- }
1454
- // src/games/tanks/logic/game.js
1455
- var Mn = (e) => typeof e == "string" && e.length > 0 && e.length <= 256 && e.trim() === e, G = (e) => ({
1456
- ok: !1,
1457
- reason: e
1458
- }), Nn = (e, [t, n]) => Number.isInteger(e) && e >= t && e <= n;
1459
- function Pn({ gameId: e, players: t, firstPlayerId: n = t?.[0], seed: r } = {}) {
1460
- if (!Mn(e) || !Array.isArray(t) || t.length !== 2 || !t.every(Mn) || t[0] === t[1] || !t.includes(n)) throw TypeError("Supply a gameId, two distinct player IDs and a valid firstPlayerId.");
1461
- if (!dn(r)) throw TypeError("Supply an integer seed in 0..0xffffffff.");
1462
- let { heights: i, spawns: a, obstacles: o, decor: s } = bn(r), c = t.map((e, t) => ({
1463
- id: e,
1464
- x: a[t].x,
1465
- y: U(i, a[t].x, a[t].z),
1466
- z: a[t].z,
1467
- hullYaw: t === 0 ? 0 : 180,
1468
- yaw: t === 0 ? 0 : 180,
1469
- pitch: 30,
1470
- hp: 100,
1471
- fuel: tn,
1472
- ammo: { ...on },
1473
- skips: 0
1474
- }));
1475
- return {
1476
- game: "tanks",
1477
- rulesVersion: 1,
1478
- gameId: e,
1479
- seed: r,
1480
- players: t.slice(),
1481
- firstPlayerId: n,
1482
- phase: "playing",
1483
- turnIndex: t.indexOf(n),
1484
- ply: 0,
1485
- maxShots: 30,
1486
- shots: 0,
1487
- tanks: c,
1488
- heights: i,
1489
- obstacles: o,
1490
- decor: s,
1491
- winnerId: null,
1492
- result: null,
1493
- reason: null,
1494
- lastTurn: null,
1495
- revision: 0
1496
- };
1497
- }
1498
- function Fn(e, t) {
1499
- return !e || !t || typeof t != "object" ? G("invalid_action") : e.phase === "finished" ? G("game_finished") : t.gameId !== void 0 && t.gameId !== e.gameId ? G("wrong_game") : t.expectedRevision !== void 0 && t.expectedRevision !== e.revision ? G("stale_revision") : e.players.includes(t.playerId) ? { ok: !0 } : G("unknown_player");
1500
- }
1501
- function In(e, t) {
1502
- let n = Fn(e, t);
1503
- if (!n.ok) return n;
1504
- let r = e.players.indexOf(t.playerId);
1505
- if (r !== e.turnIndex) return G("not_your_turn");
1506
- if (!Nn(t.move, L.move)) return G("invalid_move");
1507
- if (!Nn(t.yaw, L.yaw)) return G("invalid_yaw");
1508
- if (!Nn(t.pitch, L.pitch)) return G("invalid_pitch");
1509
- if (!Nn(t.power, L.power)) return G("invalid_power");
1510
- if (typeof t.ammo != "string" || !Object.hasOwn(R, t.ammo)) return G("unknown_ammo");
1511
- let i = R[t.ammo].cost;
1512
- return i > 0 && e.tanks[r].ammo[t.ammo] < i ? G("out_of_ammo") : { ok: !0 };
1513
- }
1514
- function Ln(e, t, { maxTicks: n = 600 } = {}) {
1515
- let r = e.players.indexOf(t.playerId), i = e.tanks[r], a = e.tanks[1 - r], o = pn(e.seed, e.ply), s = jn(i, t.move ?? 0, {
1516
- heights: e.heights,
1517
- obstacles: e.obstacles,
1518
- others: [a]
1519
- }), c = {
1520
- x: s.x,
1521
- y: s.y,
1522
- z: s.z
1523
- }, l = e.tanks.map((e, t) => t === r ? {
1524
- id: e.id,
1525
- ...c
1526
- } : {
1527
- id: e.id,
1528
- x: e.x,
1529
- y: e.y,
1530
- z: e.z
1531
- }), u = On(c, t, {
1532
- wind: o,
1533
- heights: e.heights,
1534
- tanks: l,
1535
- obstacles: e.obstacles,
1536
- maxTicks: n
1537
- }), d = kn(u, l), f = {};
1538
- return e.players.forEach((e, t) => {
1539
- f[e] = d[t];
1540
- }), {
1541
- playerId: t.playerId,
1542
- movePath: s.path,
1543
- moveStop: s.stop,
1544
- fuelUsed: s.used,
1545
- tankAfter: c,
1546
- shots: u,
1547
- damage: f,
1548
- craters: An(u),
1549
- wind: o
1550
- };
1551
- }
1552
- function Rn(e, t, n, r) {
1553
- return {
1554
- ...e,
1555
- ...r,
1556
- phase: "finished",
1557
- winnerId: t < 0 ? null : e.players[t],
1558
- result: t < 0 ? "draw" : "win",
1559
- reason: n,
1560
- revision: e.revision + 1
1561
- };
1562
- }
1563
- function zn(e, t) {
1564
- let n = e.turnIndex, r = {
1565
- playerId: t.playerId,
1566
- move: t.move,
1567
- yaw: t.yaw,
1568
- pitch: t.pitch,
1569
- power: t.power,
1570
- ammo: t.ammo
1571
- }, i = Ln(e, r), a = e.heights;
1572
- if (i.craters.length) {
1573
- a = Int32Array.from(e.heights);
1574
- for (let e of i.craters) xn(a, e);
1575
- }
1576
- let o = i.craters.length ? Sn(e.decor, i.craters) : e.decor, s = e.tanks.map((e, t) => {
1577
- let o = t === n ? i.tankAfter : e, s = {
1578
- ...e,
1579
- ammo: { ...e.ammo },
1580
- x: o.x,
1581
- z: o.z,
1582
- y: U(a, o.x, o.z),
1583
- hp: Math.max(0, e.hp - i.damage[e.id])
1584
- };
1585
- if (t === n) {
1586
- s.fuel = e.fuel - i.fuelUsed, s.yaw = r.yaw, s.pitch = r.pitch, s.skips = 0;
1587
- let t = R[r.ammo].cost;
1588
- t > 0 && (s.ammo[r.ammo] -= t);
1589
- }
1590
- return s;
1591
- }), c = {
1592
- ...e,
1593
- tanks: s,
1594
- heights: a,
1595
- decor: o,
1596
- shots: e.shots + 1,
1597
- ply: e.ply + 1,
1598
- turnIndex: 1 - n,
1599
- lastTurn: {
1600
- type: "turn",
1601
- ply: e.ply,
1602
- input: r,
1603
- ...i
1604
- }
1605
- }, l = s.map((e) => e.hp === 0);
1606
- if (l[0] && l[1]) return Rn(c, -1, "destroyed");
1607
- if (l[0] || l[1]) return Rn(c, +!!l[0], "destroyed");
1608
- if (c.shots >= c.maxShots) {
1609
- let [e, t] = s.map((e) => e.hp);
1610
- return Rn(c, e === t ? -1 : e > t ? 0 : 1, "max_shots");
1611
- }
1612
- return {
1613
- ...c,
1614
- revision: e.revision + 1
1615
- };
1616
- }
1617
- function Bn(e, t) {
1618
- if (!t || typeof t != "object") return e;
1619
- if (t.type === "turn") return In(e, t).ok ? zn(e, t) : e;
1620
- if (!Fn(e, t).ok) return e;
1621
- let n = e.players.indexOf(t.playerId);
1622
- if (t.type === "resign") return Rn(e, 1 - n, "resign");
1623
- if (t.type === "skip") {
1624
- if (n !== e.turnIndex || t.reason !== void 0 && t.reason !== "timeout") return e;
1625
- let r = e.tanks[n].skips + 1, i = e.tanks.map((e, t) => t === n ? {
1626
- ...e,
1627
- skips: r
1628
- } : e), a = {
1629
- ...e,
1630
- tanks: i,
1631
- ply: e.ply + 1,
1632
- turnIndex: 1 - n,
1633
- lastTurn: {
1634
- type: "skip",
1635
- ply: e.ply,
1636
- playerId: t.playerId
1637
- }
1638
- };
1639
- return r >= 3 ? Rn(a, 1 - n, "timeout") : {
1640
- ...a,
1641
- revision: e.revision + 1
1642
- };
1643
- }
1644
- return e;
1645
- }
1646
- function Vn(e, t) {
1647
- let n = (e.lo ^ t) >>> 0, r = n * 435, i = r >>> 0, a = (r - i) / 4294967296;
1648
- e.hi = Math.imul(e.hi, 435) + a + (n << 8) >>> 0, e.lo = i;
1649
- }
1650
- function Hn(e, t) {
1651
- let n = t | 0;
1652
- Vn(e, n & 255), Vn(e, n >>> 8 & 255), Vn(e, n >>> 16 & 255), Vn(e, n >>> 24 & 255);
1653
- }
1654
- function Un(e) {
1655
- let t = {
1656
- hi: 3421674724,
1657
- lo: 2216829733
1658
- }, n = 0;
1659
- for (let t = 0; t < e.heights.length; t += 1) n = Math.imul(n, 31) + e.heights[t] | 0;
1660
- let r = e.winnerId === null ? -1 : e.players.indexOf(e.winnerId), i = [
1661
- e.rulesVersion,
1662
- e.ply,
1663
- e.turnIndex,
1664
- e.shots,
1665
- +(e.phase === "finished"),
1666
- e.result === "win" ? 1 : e.result === "draw" ? 2 : 0,
1667
- r
1668
- ];
1669
- for (let t of e.tanks) i.push(t.x, t.y, t.z, t.hp, t.fuel, t.ammo.heavy, t.ammo.cluster, t.skips, t.yaw, t.pitch);
1670
- i.push(n, e.decor.length);
1671
- for (let e of i) Hn(t, e);
1672
- return t.hi.toString(16).padStart(8, "0") + t.lo.toString(16).padStart(8, "0");
1673
- }
1674
- // src/games/tanks/net/sha256.js
1675
- var Wn = new Uint32Array([
1676
- 1116352408,
1677
- 1899447441,
1678
- 3049323471,
1679
- 3921009573,
1680
- 961987163,
1681
- 1508970993,
1682
- 2453635748,
1683
- 2870763221,
1684
- 3624381080,
1685
- 310598401,
1686
- 607225278,
1687
- 1426881987,
1688
- 1925078388,
1689
- 2162078206,
1690
- 2614888103,
1691
- 3248222580,
1692
- 3835390401,
1693
- 4022224774,
1694
- 264347078,
1695
- 604807628,
1696
- 770255983,
1697
- 1249150122,
1698
- 1555081692,
1699
- 1996064986,
1700
- 2554220882,
1701
- 2821834349,
1702
- 2952996808,
1703
- 3210313671,
1704
- 3336571891,
1705
- 3584528711,
1706
- 113926993,
1707
- 338241895,
1708
- 666307205,
1709
- 773529912,
1710
- 1294757372,
1711
- 1396182291,
1712
- 1695183700,
1713
- 1986661051,
1714
- 2177026350,
1715
- 2456956037,
1716
- 2730485921,
1717
- 2820302411,
1718
- 3259730800,
1719
- 3345764771,
1720
- 3516065817,
1721
- 3600352804,
1722
- 4094571909,
1723
- 275423344,
1724
- 430227734,
1725
- 506948616,
1726
- 659060556,
1727
- 883997877,
1728
- 958139571,
1729
- 1322822218,
1730
- 1537002063,
1731
- 1747873779,
1732
- 1955562222,
1733
- 2024104815,
1734
- 2227730452,
1735
- 2361852424,
1736
- 2428436474,
1737
- 2756734187,
1738
- 3204031479,
1739
- 3329325298
1740
- ]), K = (e, t) => e >>> t | e << 32 - t;
1741
- function Gn(e) {
1742
- let t = new TextEncoder().encode(String(e)), n = t.length, r = new Uint8Array((n + 9 >> 6) + 1 << 6);
1743
- r.set(t), r[n] = 128;
1744
- let i = new DataView(r.buffer);
1745
- i.setUint32(r.length - 8, Math.floor(n / 536870912)), i.setUint32(r.length - 4, n << 3 >>> 0);
1746
- let a = new Uint32Array([
1747
- 1779033703,
1748
- 3144134277,
1749
- 1013904242,
1750
- 2773480762,
1751
- 1359893119,
1752
- 2600822924,
1753
- 528734635,
1754
- 1541459225
1755
- ]), o = /* @__PURE__ */ new Uint32Array(64);
1756
- for (let e = 0; e < r.length; e += 64) {
1757
- for (let t = 0; t < 16; t += 1) o[t] = i.getUint32(e + t * 4);
1758
- for (let e = 16; e < 64; e += 1) {
1759
- let t = K(o[e - 15], 7) ^ K(o[e - 15], 18) ^ o[e - 15] >>> 3, n = K(o[e - 2], 17) ^ K(o[e - 2], 19) ^ o[e - 2] >>> 10;
1760
- o[e] = o[e - 16] + t + o[e - 7] + n >>> 0;
1761
- }
1762
- let [t, n, r, s, c, l, u, d] = a;
1763
- for (let e = 0; e < 64; e += 1) {
1764
- let i = d + (K(c, 6) ^ K(c, 11) ^ K(c, 25)) + (c & l ^ ~c & u) + Wn[e] + o[e] >>> 0, a = (K(t, 2) ^ K(t, 13) ^ K(t, 22)) + (t & n ^ t & r ^ n & r) >>> 0;
1765
- d = u, u = l, l = c, c = s + i >>> 0, s = r, r = n, n = t, t = i + a >>> 0;
1766
- }
1767
- a[0] += t, a[1] += n, a[2] += r, a[3] += s, a[4] += c, a[5] += l, a[6] += u, a[7] += d;
1768
- }
1769
- return Array.from(a, (e) => e.toString(16).padStart(8, "0")).join("");
1770
- }
1771
- // src/games/tanks/net/session.js
1772
- var Kn = "La partida perdió sincronización. Se intentará resincronizar.", qn = "Falta la aceptación de la partida. Ciérrala y vuelve a invitar.", Jn = "El rival reveló una semilla que no coincide con su invitación.", Yn = "Los resultados del disparo no coinciden entre dispositivos.", Xn = [
1773
- "won",
1774
- "draw",
1775
- "closed",
1776
- "declined"
1777
- ], Zn = (e, t) => ({
1778
- ...e,
1779
- status: "conflict",
1780
- error: t
1781
- }), Qn = (e) => Array.from(e, (e) => e.toString(16).padStart(2, "0")).join("");
1782
- function $n() {
1783
- let e = /* @__PURE__ */ new Uint8Array(16);
1784
- return globalThis.crypto.getRandomValues(e), Qn(e);
1785
- }
1786
- var er = (e) => Gn(`lira-tanks-seed:${e}`), tr = (e, t) => parseInt(Gn(`lira-tanks-map:${e}:${t}`).slice(0, 8), 16) >>> 0;
1787
- function nr(e, t) {
1788
- let n = t.first_player_id === e.guestId ? e.guestId : e.hostId;
1789
- return {
1790
- ...e,
1791
- game: "tanks",
1792
- status: "invited",
1793
- turnId: null,
1794
- firstPlayerId: n,
1795
- seedCommit: t.seed_commit,
1796
- rematchOf: t.rematch_of ?? null,
1797
- seedA: null,
1798
- seedB: null,
1799
- seedEventId: null,
1800
- acceptEventId: null,
1801
- logic: null,
1802
- log: [],
1803
- ply: 0,
1804
- lastAction: null,
1805
- winnerId: null,
1806
- result: null,
1807
- seen: e.seen ?? {},
1808
- pending: !1,
1809
- pendingEvent: null,
1810
- error: "",
1811
- sync: e.sync ?? null
1812
- };
1813
- }
1814
- var q = (e) => [e.hostId, e.guestId], rr = (e) => e.logic && e.logic.phase === "playing" ? q(e)[e.logic.turnIndex] : null, ir = (e) => e?.status === "active" && !e.pendingEvent && rr(e) === e.ownId, ar = (e, t, n) => e === "tk_turn" ? [
1815
- 1,
1816
- t.move,
1817
- t.yaw,
1818
- t.pitch,
1819
- t.power,
1820
- t.ammo
1821
- ] : e === "tk_skip" ? [2] : [3, n], or = (e, t) => e.length === t.length && e.every((e, n) => e === t[n]);
1822
- function sr(e, t) {
1823
- let n = q(e);
1824
- if (t[0] === 3) return {
1825
- type: "resign",
1826
- playerId: n[t[1]]
1827
- };
1828
- let r = rr(e);
1829
- return t[0] === 2 ? {
1830
- type: "skip",
1831
- playerId: r,
1832
- reason: "timeout"
1833
- } : {
1834
- type: "turn",
1835
- playerId: r,
1836
- move: t[1],
1837
- yaw: t[2],
1838
- pitch: t[3],
1839
- power: t[4],
1840
- ammo: E[t[5]]
1841
- };
1842
- }
1843
- function cr(e, t, n, r) {
1844
- let i = Bn(e.logic, sr(e, t));
1845
- if (i === e.logic) return null;
1846
- let a = i.phase === "finished";
1847
- return {
1848
- ...e,
1849
- logic: i,
1850
- log: [...e.log, t],
1851
- ply: e.ply + 1,
1852
- lastEventId: n,
1853
- lastAction: {
1854
- eventId: n,
1855
- entry: t,
1856
- author: r,
1857
- turn: i.lastTurn ?? null
1858
- },
1859
- turnId: a ? null : q(e)[i.turnIndex],
1860
- status: a ? i.result === "draw" ? "draw" : "won" : "active",
1861
- winnerId: i.winnerId ?? null,
1862
- result: i.result ?? null
1863
- };
1864
- }
1865
- function lr(e, t, n) {
1866
- if (er(t) !== e.seedCommit) return null;
1867
- let r = Pn({
1868
- gameId: e.gameId,
1869
- players: q(e),
1870
- firstPlayerId: e.firstPlayerId,
1871
- seed: tr(t, e.seedB)
1872
- });
1873
- return {
1874
- ...e,
1875
- seedA: t,
1876
- seedEventId: n,
1877
- logic: r,
1878
- log: [],
1879
- ply: 0,
1880
- lastEventId: n,
1881
- lastAction: null,
1882
- status: "active",
1883
- turnId: q(e)[r.turnIndex],
1884
- error: ""
1885
- };
1886
- }
1887
- function ur(e, t, n) {
1888
- if (![e.hostId, e.guestId].includes(n)) return e;
1889
- let r = t.data;
1890
- if (t.type === "game_end") return ["closed", "declined"].includes(e.status) ? e : {
1891
- ...e,
1892
- status: "closed",
1893
- closedBy: n,
1894
- error: ""
1895
- };
1896
- if (Xn.includes(e.status) || e.status === "conflict") return e;
1897
- if (t.type === "game_accept" || t.type === "game_decline") return n !== e.guestId || e.status !== "invited" || r.invite_event_id !== e.inviteEventId ? e : t.type === "game_decline" ? {
1898
- ...e,
1899
- status: "declined",
1900
- lastEventId: t.event_id
1901
- } : {
1902
- ...e,
1903
- status: "seeding",
1904
- seedB: r.seed_b,
1905
- acceptEventId: t.event_id,
1906
- lastEventId: t.event_id
1907
- };
1908
- if (t.type === "tk_seed") return n !== e.hostId || e.status !== "seeding" ? e : lr(e, r.seed_a, t.event_id) ?? Zn(e, Jn);
1909
- if (![
1910
- "tk_turn",
1911
- "tk_skip",
1912
- "tk_resign"
1913
- ].includes(t.type)) return e;
1914
- if (e.status !== "active") return Zn(e, qn);
1915
- let i = q(e).indexOf(n), a = ar(t.type, r, i);
1916
- if (r.ply <= e.ply) return or(e.log[r.ply - 1] ?? [], a) ? e : Zn(e, Kn);
1917
- if (r.ply > e.ply + 1 || r.prev_event_id !== e.lastEventId) return Zn(e, Kn);
1918
- if (t.type !== "tk_resign" && n !== rr(e)) return e;
1919
- let o = cr(e, a, t.event_id, n);
1920
- return o ? t.type === "tk_turn" && Un(o.logic) !== r.hash ? Zn(e, Yn) : o : e;
1921
- }
1922
- function dr(e, t) {
1923
- if (!ir(e)) return null;
1924
- let n = {
1925
- ply: e.ply + 1,
1926
- prev_event_id: e.lastEventId,
1927
- move: t.move,
1928
- yaw: t.yaw,
1929
- pitch: t.pitch,
1930
- power: t.power,
1931
- ammo: E.indexOf(t.ammo)
1932
- };
1933
- if (n.ammo < 0) return null;
1934
- let r = cr(e, ar("tk_turn", n), "local", e.ownId);
1935
- return r ? {
1936
- ...n,
1937
- hash: Un(r.logic)
1938
- } : null;
1939
- }
1940
- function fr(e) {
1941
- let t = {
1942
- log: e.log ?? [],
1943
- head: e.lastEventId
1944
- };
1945
- return e.acceptEventId && Object.assign(t, {
1946
- accept_event_id: e.acceptEventId,
1947
- seed_b: e.seedB
1948
- }), e.seedA && Object.assign(t, {
1949
- seed_a: e.seedA,
1950
- seed_event_id: e.seedEventId
1951
- }), t;
1952
- }
1953
- function pr(e, t) {
1954
- if (e.accept_event_id && t.accept_event_id && e.accept_event_id !== t.accept_event_id || e.seed_a && t.seed_a && e.seed_a !== t.seed_a) return "diverged";
1955
- let n = Math.min(e.log.length, t.log.length);
1956
- for (let r = 0; r < n; r += 1) if (!or(e.log[r], t.log[r])) return "diverged";
1957
- let r = (e) => (e.seed_a ? 2 : +!!e.accept_event_id) * 1e3 + e.log.length;
1958
- return r(e) === r(t) ? e.log.length === t.log.length && e.head !== t.head && e.log.length > 0 ? "diverged" : "equal" : r(e) < r(t) ? "behind" : "ahead";
1959
- }
1960
- function mr(e, t) {
1961
- let n = {
1962
- ...e,
1963
- status: "invited",
1964
- acceptEventId: null,
1965
- seedB: null,
1966
- seedA: null,
1967
- seedEventId: null,
1968
- logic: null,
1969
- log: [],
1970
- ply: 0,
1971
- lastAction: null,
1972
- winnerId: null,
1973
- result: null,
1974
- turnId: null,
1975
- error: "",
1976
- lastEventId: e.inviteEventId
1977
- };
1978
- if (!t.accept_event_id) return t.log.length ? null : {
1979
- ...n,
1980
- lastEventId: t.head === e.inviteEventId ? t.head : e.inviteEventId
1981
- };
1982
- if (t.accept_event_id === e.inviteEventId) return null;
1983
- if (n = {
1984
- ...n,
1985
- status: "seeding",
1986
- acceptEventId: t.accept_event_id,
1987
- seedB: t.seed_b,
1988
- lastEventId: t.accept_event_id
1989
- }, !t.seed_a) return n;
1990
- if (n = lr(n, t.seed_a, t.seed_event_id), !n) return null;
1991
- for (let e = 0; e < t.log.length; e += 1) {
1992
- let r = t.log[e];
1993
- if (!se(r)) return null;
1994
- let i = e === t.log.length - 1, a = r[0] === 3 ? q(n)[r[1]] : rr(n);
1995
- if (n = cr(n, r, i ? t.head : `${t.seed_event_id}:${e + 1}`, a), !n) return null;
1996
- }
1997
- return n;
1998
- }
1999
- function hr(e, t) {
2000
- if (!t) return !1;
2001
- if (t.type === "tk_seed") return e.seed_a === t.data.seed_a;
2002
- if (t.type === "game_accept") return e.accept_event_id === t.event_id;
2003
- if (![
2004
- "tk_turn",
2005
- "tk_skip",
2006
- "tk_resign"
2007
- ].includes(t.type)) return !1;
2008
- let n = e.log[t.data.ply - 1];
2009
- return !!n && n[0] === ar(t.type, t.data, 0)[0];
2010
- }
2011
- function gr(e, t) {
2012
- let n = { ...e };
2013
- return [
2014
- t.acceptEventId,
2015
- t.seedEventId,
2016
- t.lastEventId
2017
- ].forEach((e) => {
2018
- e && (n[e] = !0);
2019
- }), n;
2020
- }
2021
- function _r(e) {
2022
- return {
2023
- gameId: e.gameId,
2024
- roomId: e.roomId,
2025
- hostId: e.hostId,
2026
- guestId: e.guestId,
2027
- ownId: e.ownId,
2028
- firstPlayerId: e.firstPlayerId,
2029
- seedCommit: e.seedCommit,
2030
- rematchOf: e.rematchOf,
2031
- inviteEventId: e.inviteEventId,
2032
- createdAt: e.createdAt,
2033
- status: e.status,
2034
- ...fr(e)
2035
- };
2036
- }
2037
- // src/games/tanks/net/tankStorage.js
2038
- var vr = "lira:tk:", yr = 6048e5, br = 20, xr = (e, t) => `${vr}${e}:${t}`, Sr = () => {
2039
- try {
2040
- return globalThis.localStorage ?? null;
2041
- } catch {
2042
- return null;
2043
- }
2044
- };
2045
- function Cr(e) {
2046
- let t = [];
2047
- for (let n = 0; n < e.length; n += 1) {
2048
- let r = e.key(n);
2049
- if (r?.startsWith(vr)) try {
2050
- let n = JSON.parse(e.getItem(r));
2051
- t.push({
2052
- key: r,
2053
- value: n
2054
- });
2055
- } catch {
2056
- t.push({
2057
- key: r,
2058
- value: null
2059
- });
2060
- }
2061
- }
2062
- return t;
2063
- }
2064
- function wr(e) {
2065
- let t = Date.now(), n = Cr(e);
2066
- n.filter(({ value: e }) => !e || !(t - e.savedAt < yr)).forEach(({ key: t }) => e.removeItem(t));
2067
- let r = n.filter(({ value: e }) => e && t - e.savedAt < yr).sort((e, t) => e.value.savedAt - t.value.savedAt);
2068
- r.slice(0, Math.max(0, r.length - br)).forEach(({ key: t }) => e.removeItem(t));
2069
- }
2070
- function Tr(e, t, n) {
2071
- try {
2072
- let r = Sr();
2073
- if (!r) return !1;
2074
- let i = Er(e, t) ?? {};
2075
- return r.setItem(xr(e, t), JSON.stringify({
2076
- ...i,
2077
- ...n,
2078
- savedAt: Date.now()
2079
- })), wr(r), !0;
2080
- } catch {
2081
- return !1;
2082
- }
2083
- }
2084
- function Er(e, t) {
2085
- try {
2086
- let n = JSON.parse(Sr()?.getItem(xr(e, t)) ?? "null");
2087
- return !n || typeof n != "object" || !(Date.now() - n.savedAt < yr) || n.seedA !== void 0 && !/^[0-9a-f]{32}$/.test(n.seedA) ? null : n;
2088
- } catch {
2089
- return null;
2090
- }
2091
- }
2092
- function Dr(e) {
2093
- try {
2094
- let t = Sr();
2095
- return t ? Cr(t).filter(({ key: t, value: n }) => t.startsWith(`${vr}${e}:`) && n?.snapshot && Date.now() - n.savedAt < yr).map(({ value: e }) => e).sort((e, t) => t.savedAt - e.savedAt) : [];
2096
- } catch {
2097
- return [];
2098
- }
2099
- }
2100
- // src/games/shared/useChatGames.js
2101
- var Or = Ee, J = (e) => e?.game ?? "connect4", kr = (e) => J(e) === "battleship", Ar = (e) => J(e) === "tanks", jr = 250, Y = (e) => [
2102
- "won",
2103
- "draw",
2104
- "closed",
2105
- "declined"
2106
- ].includes(e.status), Mr = (e, t, n) => JSON.stringify([
2107
- e,
2108
- String(t),
2109
- n
2110
- ]), Nr = (e) => {
2111
- let t = Object.keys(e).filter((t) => Y(e[t]));
2112
- if (t.length <= 80) return e;
2113
- let n = { ...e };
2114
- return t.slice(0, t.length - 80).forEach((e) => {
2115
- delete n[e];
2116
- }), n;
2117
- };
2118
- function Pr(e, t, n) {
2119
- if (![e.hostId, e.guestId].includes(n)) return e;
2120
- if (t.type === "game_end" && t.data.reason === "closed") return ["closed", "declined"].includes(e.status) ? e : {
2121
- ...e,
2122
- status: "closed",
2123
- closedBy: n,
2124
- error: ""
2125
- };
2126
- if (Y(e) || e.status === "conflict") return e;
2127
- if (t.type === "game_accept" || t.type === "game_decline") return n !== e.guestId || e.status !== "invited" || t.data.invite_event_id !== e.inviteEventId ? e : {
2128
- ...e,
2129
- status: t.type === "game_accept" ? "active" : "declined",
2130
- lastEventId: t.event_id,
2131
- acceptEventId: t.type === "game_accept" ? t.event_id : e.acceptEventId
2132
- };
2133
- if (t.type !== "game_move") return e;
2134
- let { ply: r, prev_event_id: i, column: a } = t.data;
2135
- if (n !== (r % 2 == 1 ? e.hostId : e.guestId)) return e;
2136
- if (e.status !== "active") return {
2137
- ...e,
2138
- status: "conflict",
2139
- error: "Falta la aceptación de la partida. Ciérrala y vuelve a invitar."
2140
- };
2141
- if (r <= e.ply || r > e.ply + 1 || i !== e.lastEventId) return {
2142
- ...e,
2143
- status: "conflict",
2144
- error: "La partida perdió sincronización. Ciérrala y envía una nueva invitación."
2145
- };
2146
- if (n !== e.turnId) return e;
2147
- let o = Fe(e.board, a, n);
2148
- return o ? {
2149
- ...e,
2150
- board: o.board,
2151
- ply: r,
2152
- lastEventId: t.event_id,
2153
- moves: [...e.moves ?? [], [a, t.event_id]],
2154
- lastMove: {
2155
- row: o.row,
2156
- column: a,
2157
- eventId: t.event_id
2158
- },
2159
- winnerId: o.winner || null,
2160
- winningCells: o.winningCells,
2161
- status: o.winner ? "won" : o.draw ? "draw" : "active",
2162
- turnId: n === e.hostId ? e.guestId : e.hostId
2163
- } : e;
2164
- }
2165
- var Fr = 8e3, Ir = {
2166
- status: "idle",
2167
- requestId: null,
2168
- requestedAt: 0,
2169
- auto: !1,
2170
- outgoing: [],
2171
- replies: [],
2172
- offer: null,
2173
- message: ""
2174
- }, Lr = (e) => [
2175
- "game_resync_request",
2176
- "game_resync_state",
2177
- "bs_sync_request",
2178
- "bs_sync_state",
2179
- "tk_sync_request",
2180
- "tk_sync_state"
2181
- ].includes(e), Rr = (e) => e.acceptEventId ? {
2182
- accept_event_id: e.acceptEventId,
2183
- moves: e.moves ?? [],
2184
- rev: (e.moves ?? []).length
2185
- } : {
2186
- moves: [],
2187
- rev: 0
2188
- };
2189
- function zr(e, t, n) {
2190
- let r = {
2191
- ...e,
2192
- board: Ae(),
2193
- ply: 0,
2194
- turnId: e.hostId,
2195
- winnerId: null,
2196
- winningCells: [],
2197
- lastMove: null,
2198
- moves: [],
2199
- error: ""
2200
- };
2201
- if (!t) return n.length ? null : {
2202
- ...r,
2203
- status: "invited",
2204
- acceptEventId: null,
2205
- lastEventId: e.inviteEventId
2206
- };
2207
- if (t === e.inviteEventId) return null;
2208
- let i = {
2209
- ...r,
2210
- status: "active",
2211
- acceptEventId: t,
2212
- lastEventId: t
2213
- }, a = /* @__PURE__ */ new Set([e.inviteEventId, t]);
2214
- for (let t = 0; t < n.length; t += 1) {
2215
- let [r, o] = n[t];
2216
- if (a.has(o)) return null;
2217
- a.add(o);
2218
- let s = t % 2 == 0 ? e.hostId : e.guestId, c = Pr(i, {
2219
- type: "game_move",
2220
- event_id: o,
2221
- data: {
2222
- column: r,
2223
- ply: t + 1,
2224
- prev_event_id: i.lastEventId
2225
- }
2226
- }, s);
2227
- if (c.status === "conflict" || c.ply !== t + 1 || c.lastEventId !== o) return null;
2228
- i = c;
2229
- }
2230
- return i;
2231
- }
2232
- function Br(e, t) {
2233
- if (e.acceptEventId && t.acceptEventId && e.acceptEventId !== t.acceptEventId) return "diverged";
2234
- let n = Math.min(e.moves.length, t.moves.length);
2235
- 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";
2236
- 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";
2237
- }
2238
- var Vr = (e) => e.pendingEvent?.type === "game_move" && !e.pending ? e.pendingEvent.event_id : null, Hr = {
2239
- requestType: "game_resync_request",
2240
- stateType: "game_resync_state",
2241
- historyOf: Rr,
2242
- rebuild: (e, t) => zr(e, t.accept_event_id ?? null, t.moves),
2243
- compare: (e, t) => Br({
2244
- acceptEventId: e.acceptEventId ?? null,
2245
- moves: e.moves ?? []
2246
- }, {
2247
- acceptEventId: t.accept_event_id ?? null,
2248
- moves: t.moves
2249
- }),
2250
- offerOf: (e) => ({
2251
- accept_event_id: e.accept_event_id ?? null,
2252
- moves: e.moves
2253
- }),
2254
- covers: (e, t) => {
2255
- let n = Vr(e);
2256
- return !!(n && t.moves?.some((e) => e[1] === n));
2257
- },
2258
- markSeen: (e, t) => {
2259
- let n = { ...e };
2260
- return t.acceptEventId && (n[t.acceptEventId] = !0), (t.moves ?? []).forEach((e) => {
2261
- n[e[1]] = !0;
2262
- }), n;
2263
- },
2264
- merge: () => null
2265
- }, Ur = (e) => ({
2266
- requestType: "bs_sync_request",
2267
- stateType: "bs_sync_state",
2268
- historyOf: Ft,
2269
- rebuild: (t, n) => Rt(t, n, { stored: e(t.scope, t.gameId) }),
2270
- compare: (e, t) => It(Ft(e), t),
2271
- offerOf: (e) => ({
2272
- accept_event_id: e.accept_event_id,
2273
- commits: e.commits,
2274
- log: e.log,
2275
- head: e.head
2276
- }),
2277
- covers: (e, t) => !!(e.pendingEvent && !e.pending && zt(t, e.pendingEvent)),
2278
- markSeen: Bt,
2279
- merge: (e, t) => Lt(Ft(e), t)
2280
- }), Wr = {
2281
- requestType: "tk_sync_request",
2282
- stateType: "tk_sync_state",
2283
- historyOf: fr,
2284
- rebuild: mr,
2285
- compare: (e, t) => pr(fr(e), t),
2286
- offerOf: (e) => ({
2287
- ...e,
2288
- request_event_id: void 0
2289
- }),
2290
- covers: (e, t) => !!(e.pendingEvent && !e.pending && hr(t, e.pendingEvent)),
2291
- markSeen: gr,
2292
- merge: () => null
2293
- }, Gr = (e) => ({
2294
- ...e,
2295
- game: "connect4",
2296
- turnId: e.hostId,
2297
- status: "invited",
2298
- board: Ae(),
2299
- ply: 0,
2300
- winnerId: null,
2301
- lastMove: null,
2302
- pending: !1,
2303
- error: "",
2304
- pendingEvent: null,
2305
- acceptEventId: null,
2306
- moves: []
2307
- }), Kr = (e, t, n) => j(t, {
2308
- game_id: e.gameId,
2309
- data: n,
2310
- game: J(e)
2311
- });
2312
- function qr() {
2313
- let e = null, t = /* @__PURE__ */ new Map(), n = (e, n) => t.get(`${e}:${n}`) ?? Jt(e, n), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Set(), s = Ur(n), l = /* @__PURE__ */ new Map(), u = (e, t) => l.get(`${e}:${t}`) ?? Er(e, t)?.seedA ?? null, d = {
2314
- connect4: {
2315
- create: (e) => Gr(e),
2316
- apply: (e, t, n) => Pr(e, t, n),
2317
- sync: Hr
2318
- },
2319
- battleship: {
2320
- create: (e) => tt(e),
2321
- apply: (e, t, r, i) => jt(e, t, r, { stored: t.type === "bs_commit" && r === i ? n(e.scope, e.gameId) : null }),
2322
- sync: s,
2323
- after: (e, t) => t().bsScheduleEffects(e)
2324
- },
2325
- tanks_live: {
2326
- create: (e, t) => v(e, t.data),
2327
- apply: y
2328
- },
2329
- tanks: {
2330
- create: (e, t) => nr(e, t.data),
2331
- apply: (e, t, n) => ur(e, t, n),
2332
- sync: Wr,
2333
- after: (e, t) => t().tkScheduleEffects(e)
2334
- }
2335
- }, f = (e) => d[J(e)] ?? null, p = (e) => f(e)?.sync ?? Hr;
2336
- return c((s, c) => ({
2337
- games: {},
2338
- configureTransport: (t) => {
2339
- e = t;
2340
- },
2341
- clear: () => {
2342
- r.forEach((e) => clearTimeout(e)), r.clear(), o.forEach((e) => clearTimeout(e)), o.clear(), t.clear(), l.clear(), i.clear(), a.clear(), s({ games: {} });
2343
- },
2344
- markDisconnected: (e) => s((t) => ({ games: Object.fromEntries(Object.entries(t.games).map(([t, n]) => [t, n.scope === e && n.game !== "tanks_live" && !Y(n) ? {
2345
- ...n,
2346
- status: "conflict",
2347
- error: "Conexión interrumpida. Se intentará resincronizar al reconectar.",
2348
- sync: {
2349
- ...Ir,
2350
- ...n.sync,
2351
- status: "idle",
2352
- auto: !1
2353
- }
2354
- } : n])) })),
2355
- ingest: (t, n, r) => {
2356
- let i = typeof n == "object" ? n : {
2357
- scope: n,
2358
- currentUserId: r
2359
- }, o = i?.scope ?? e?.getScope?.(), l = String(i?.currentUserId ?? e?.getUserId?.() ?? ""), u = t.data ?? t.payload, f = u && typeof u == "object" ? {
2360
- ...u,
2361
- ...t
2362
- } : t, p = f.message ?? f.text;
2363
- if (typeof p != "string" || !p.startsWith("LIRA_GAME_V1:")) return !1;
2364
- let m = Oe(p), h = String(f.room_id ?? ""), g = String(f.user_id ?? "");
2365
- if (!m || !o || !l || !g || !h.startsWith("private_")) return !0;
2366
- let _ = h.slice(8).split("_");
2367
- if (_.length !== 2 || !_.includes(l) || !_.includes(g)) return !0;
2368
- let v = Mr(o, h, m.game_id), y = c().games[v];
2369
- if (y && J(y) !== m.game) return !0;
2370
- if (Lr(m.type)) return y && !y.seen[m.event_id] && c().handleResync(v, m, g, l), !0;
2371
- if (!y && m.type !== "game_invite" && m.game === "tanks" && c().restoreTanks(o, m.game_id)) return c().ingest(t, n, r);
2372
- if (!y && m.type !== "game_invite") {
2373
- let e = Date.now();
2374
- for (let [t, n] of a) e - n.at > 3e4 && a.delete(t);
2375
- !a.has(v) && a.size >= 32 && a.delete(a.keys().next().value);
2376
- let t = a.get(v) ?? {
2377
- at: e,
2378
- messages: []
2379
- };
2380
- return t.messages.length < 8 && !t.messages.some((e) => e.eventId === m.event_id) && t.messages.push({
2381
- eventId: m.event_id,
2382
- message: f
2383
- }), a.set(v, t), !0;
2384
- }
2385
- if (y?.seen[m.event_id]) return !0;
2386
- let b = y, x = d[m.game];
2387
- if (!x) return !0;
2388
- if (m.type === "game_invite") {
2389
- let e = m.data.opponent_id;
2390
- if (y || e === g || !_.includes(e)) return !0;
2391
- b = x.create({
2392
- key: v,
2393
- gameId: m.game_id,
2394
- game_id: m.game_id,
2395
- scope: o,
2396
- roomId: h,
2397
- ownId: l,
2398
- hostId: g,
2399
- guestId: e,
2400
- createdAt: f.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
2401
- inviteEventId: m.event_id,
2402
- lastEventId: m.event_id,
2403
- seen: {},
2404
- sync: { ...Ir }
2405
- }, m);
2406
- } else y && (b = x.apply(y, m, g, l));
2407
- if (!b || b === y) return !0;
2408
- if (b = {
2409
- ...b,
2410
- seen: {
2411
- ...b.seen,
2412
- [m.event_id]: !0
2413
- }
2414
- }, s((e) => {
2415
- let t = {
2416
- ...e.games,
2417
- [v]: b
2418
- };
2419
- if (m.type === "game_invite") {
2420
- let e = Object.values(t).filter((e) => e.scope === o && e.roomId === h && !Y(e)), n = e.sort((e, t) => e.gameId < t.gameId ? -1 : +(e.gameId > t.gameId))[0];
2421
- e.forEach((e) => {
2422
- e.key !== n?.key && (t[e.key] = {
2423
- ...e,
2424
- status: "closed",
2425
- error: "Se conserva la otra invitación de esta conversación."
2426
- });
2427
- });
2428
- }
2429
- return { games: Nr(t) };
2430
- }), b.status === "conflict" && y?.status !== "conflict" && queueMicrotask(() => {
2431
- c().requestResync(v, { auto: !0 });
2432
- }), c().afterGameChange(v), m.type === "game_invite") {
2433
- let e = a.get(v);
2434
- a.delete(v), e && Date.now() - e.at <= 3e4 && e.messages.forEach((e) => c().ingest(e.message, o, l));
2435
- }
2436
- return !0;
2437
- },
2438
- invite: async ({ roomId: t, opponentId: n, gameType: r = "connect4", firstPlayerId: i, rematchOf: a }) => {
2439
- if (!e) throw Error("Chat no disponible");
2440
- if (!Or.includes(r)) throw Error("Juego no disponible");
2441
- let o = e.getScope();
2442
- if (!String(e.getUserId() ?? "") || !String(t).startsWith("private_")) throw Error("Abre un chat privado para jugar.");
2443
- if (Object.values(c().games).some((e) => e.scope === o && e.roomId === String(t) && (!Y(e) || e.pendingEvent))) throw Error("Cierra la partida actual antes de invitar.");
2444
- let s = m(), u = {
2445
- opponent_id: String(n),
2446
- rules_version: 1
2447
- };
2448
- if (r === "tanks") {
2449
- let e = $n();
2450
- l.set(`${o}:${s}`, e), Tr(o, s, { seedA: e }), u.seed_commit = er(e), i != null && (u.first_player_id = String(i)), a && (u.rematch_of = a);
2451
- }
2452
- r === "tanks_live" && a && (u.rematch_of = a);
2453
- let d = j("game_invite", {
2454
- game_id: s,
2455
- data: u,
2456
- game: r
2457
- });
2458
- return c().sendEvent(t, d);
2459
- },
2460
- act: async (t, n, r = {}) => {
2461
- let i = c().games[t], a = String(e?.getUserId?.() ?? "");
2462
- if (!i || i.scope !== e?.getScope?.()) throw Error("Partida no disponible");
2463
- if (n !== "game_end" && (i.pending || i.pendingEvent)) throw Error("Reintenta el envío pendiente antes de continuar.");
2464
- let o = r;
2465
- if (n === "game_accept" || n === "game_decline") {
2466
- if (i.status !== "invited" || a !== i.guestId) return;
2467
- o = { invite_event_id: i.inviteEventId }, n === "game_accept" && Ar(i) && (o.seed_b = $n());
2468
- } else if (n === "game_move") {
2469
- if (J(i) !== "connect4" || i.status !== "active" || a !== i.turnId || !Fe(i.board, r.column, a)) return;
2470
- o = {
2471
- column: r.column,
2472
- ply: i.ply + 1,
2473
- prev_event_id: i.lastEventId
2474
- };
2475
- } else if (n === "game_end") o = { reason: "closed" };
2476
- else return;
2477
- return c().sendEvent(i.roomId, j(n, {
2478
- game_id: i.gameId,
2479
- data: o,
2480
- game: J(i)
2481
- }));
2482
- },
2483
- bsUpdateLocal: (e, t) => {
2484
- let n = c().games[e];
2485
- if (!kr(n)) return !1;
2486
- let r = t(n);
2487
- return r !== n && (s((t) => t.games[e] === n ? { games: {
2488
- ...t.games,
2489
- [e]: r
2490
- } } : t), c().games[e] === r);
2491
- },
2492
- bsPlaceShip: (e, t) => c().bsUpdateLocal(e, (e) => ft(e, t)),
2493
- bsRemoveShip: (e, t) => c().bsUpdateLocal(e, (e) => pt(e, t)),
2494
- bsRandomFleet: (e) => c().bsUpdateLocal(e, (e) => gt(e)),
2495
- bsReady: async (n) => {
2496
- let r = c().games[n];
2497
- if (!kr(r) || r.status !== "placement" || r.myReady) return;
2498
- if (r.scope !== e?.getScope?.()) throw Error("Partida no disponible");
2499
- if (r.pending || r.pendingEvent) throw Error("Reintenta el envío pendiente antes de continuar.");
2500
- let i = ct(r.myFleet);
2501
- if (!ut(i)) throw Error("Coloca los cinco barcos antes de continuar.");
2502
- let a = vt(), o = await bt(i, a), s = c().games[n];
2503
- if (!(!s || s.myReady || s.status !== "placement" || s.pending || s.pendingEvent || JSON.stringify(ct(s.myFleet)) !== JSON.stringify(i))) return t.set(`${r.scope}:${r.gameId}`, {
2504
- fleet: i,
2505
- salt: a,
2506
- commitment: o
2507
- }), qt(r.scope, r.gameId, {
2508
- fleet: i,
2509
- salt: a,
2510
- commitment: o
2511
- }), c().sendEvent(r.roomId, j("bs_commit", {
2512
- game_id: r.gameId,
2513
- data: { commitment: o },
2514
- game: "battleship"
2515
- }));
2516
- },
2517
- bsFire: async (t, { row: n, col: r } = {}) => {
2518
- let i = c().games[t];
2519
- if (!kr(i) || i.scope !== e?.getScope?.()) throw Error("Partida no disponible");
2520
- if (i.pending || i.pendingEvent) throw Error("Reintenta el envío pendiente antes de continuar.");
2521
- if (rt(i) && i.targetShots[n]?.[r] === null) return c().sendEvent(i.roomId, j("bs_fire", {
2522
- game_id: i.gameId,
2523
- data: {
2524
- ply: i.ply + 1,
2525
- row: n,
2526
- col: r,
2527
- prev_event_id: i.lastEventId
2528
- },
2529
- game: "battleship"
2530
- }));
2531
- },
2532
- bsScheduleEffects: (e) => {
2533
- r.has(e) || r.set(e, setTimeout(() => {
2534
- r.delete(e), c().bsRunEffects(e);
2535
- }, jr));
2536
- },
2537
- bsRunEffects: (t) => {
2538
- let r = c().games[t];
2539
- if (!kr(r) || !e || r.scope !== e.getScope?.()) return;
2540
- if (r.opponentReveal && r.verification === "pending" && !i.has(t)) {
2541
- let e = r.opponentReveal;
2542
- i.add(t), Nt(r, e).then((n) => s((r) => {
2543
- let i = r.games[t];
2544
- return !i || i.opponentReveal !== e || i.verification === n ? r : { games: {
2545
- ...r.games,
2546
- [t]: {
2547
- ...i,
2548
- verification: n
2549
- }
2550
- } };
2551
- })).catch(() => {}).finally(() => {
2552
- i.delete(t);
2553
- });
2554
- }
2555
- if (r.pending || r.pendingEvent) return;
2556
- let a = (e, t) => {
2557
- c().sendEvent(r.roomId, j(e, {
2558
- game_id: r.gameId,
2559
- data: t,
2560
- game: "battleship"
2561
- })).catch(() => {});
2562
- };
2563
- if (r.status === "active" && r.pendingShot && r.pendingShot.by !== r.ownId) {
2564
- let e = xt(dt(r), r.pendingShot);
2565
- e ? a("bs_result", e) : r.error || s((e) => ({ games: {
2566
- ...e.games,
2567
- [t]: {
2568
- ...e.games[t],
2569
- error: "Tu flota no está disponible en este dispositivo; no se pueden responder disparos."
2570
- }
2571
- } }));
2572
- return;
2573
- }
2574
- let o = String(r.winnerId) !== String(r.ownId) || !!r.opponentReveal;
2575
- if (r.winnerId && ["won", "closed"].includes(r.status) && !r.myRevealSent && o) {
2576
- let e = ct(r.myFleet), t = r.mySalt ?? n(r.scope, r.gameId)?.salt;
2577
- ut(e) && t && a("bs_reveal", {
2578
- fleet: e,
2579
- salt: t
2580
- });
2581
- }
2582
- },
2583
- afterGameChange: (e) => {
2584
- let t = c().games[e];
2585
- f(t)?.after?.(e, c);
2586
- },
2587
- tkTurn: async (t, n) => {
2588
- let r = c().games[t];
2589
- if (!Ar(r) || r.scope !== e?.getScope?.()) throw Error("Partida no disponible");
2590
- if (r.pending || r.pendingEvent) throw Error("Reintenta el envío pendiente antes de continuar.");
2591
- let i = dr(r, n);
2592
- if (i) return c().sendEvent(r.roomId, j("tk_turn", {
2593
- game_id: r.gameId,
2594
- data: i,
2595
- game: "tanks"
2596
- }));
2597
- },
2598
- tkSkip: async (t) => {
2599
- let n = c().games[t];
2600
- if (Ar(n) && ir(n) && n.scope === e?.getScope?.()) return c().sendEvent(n.roomId, j("tk_skip", {
2601
- game_id: n.gameId,
2602
- data: {
2603
- ply: n.ply + 1,
2604
- prev_event_id: n.lastEventId
2605
- },
2606
- game: "tanks"
2607
- }));
2608
- },
2609
- tkResign: async (t) => {
2610
- let n = c().games[t];
2611
- if (!(!Ar(n) || n.status !== "active" || n.pending || n.pendingEvent || n.scope !== e?.getScope?.())) return c().sendEvent(n.roomId, j("tk_resign", {
2612
- game_id: n.gameId,
2613
- data: {
2614
- ply: n.ply + 1,
2615
- prev_event_id: n.lastEventId
2616
- },
2617
- game: "tanks"
2618
- }));
2619
- },
2620
- tkScheduleEffects: (e) => {
2621
- r.has(e) || r.set(e, setTimeout(() => {
2622
- r.delete(e), c().tkRunEffects(e);
2623
- }, jr));
2624
- },
2625
- tkRunEffects: (t) => {
2626
- let n = c().games[t];
2627
- if (!Ar(n) || (Tr(n.scope, n.gameId, { snapshot: _r(n) }), !e || n.scope !== e.getScope?.() || n.pending || n.pendingEvent) || n.status !== "seeding" || n.ownId !== n.hostId) return;
2628
- let r = u(n.scope, n.gameId);
2629
- r ? c().sendEvent(n.roomId, j("tk_seed", {
2630
- game_id: n.gameId,
2631
- data: { seed_a: r },
2632
- game: "tanks"
2633
- })).catch(() => {}) : n.error || s((e) => ({ games: {
2634
- ...e.games,
2635
- [t]: {
2636
- ...e.games[t],
2637
- error: "La semilla de esta partida no está en este dispositivo. Ciérrala e invita de nuevo."
2638
- }
2639
- } }));
2640
- },
2641
- restoreTanks: (e, t) => {
2642
- let n = !1;
2643
- return Dr(e).forEach(({ snapshot: r }) => {
2644
- if (!r || t && r.gameId !== t || [
2645
- "closed",
2646
- "declined",
2647
- "won",
2648
- "draw"
2649
- ].includes(r.status)) return;
2650
- let i = Mr(e, r.roomId, r.gameId);
2651
- if (c().games[i]) return;
2652
- let a = mr(nr({
2653
- key: i,
2654
- gameId: r.gameId,
2655
- game_id: r.gameId,
2656
- scope: e,
2657
- roomId: r.roomId,
2658
- ownId: r.ownId,
2659
- hostId: r.hostId,
2660
- guestId: r.guestId,
2661
- createdAt: r.createdAt,
2662
- inviteEventId: r.inviteEventId,
2663
- lastEventId: r.inviteEventId,
2664
- seen: {},
2665
- sync: { ...Ir }
2666
- }, {
2667
- seed_commit: r.seedCommit,
2668
- first_player_id: r.firstPlayerId,
2669
- rematch_of: r.rematchOf ?? void 0
2670
- }), r);
2671
- if (!a) return;
2672
- n = !0;
2673
- let o = {
2674
- ...a,
2675
- seen: gr({ [r.inviteEventId]: !0 }, a),
2676
- status: "conflict",
2677
- error: "Partida recuperada en este dispositivo. Sincronizando con el rival…"
2678
- };
2679
- s((e) => ({ games: Nr({
2680
- ...e.games,
2681
- [i]: o
2682
- }) })), queueMicrotask(() => {
2683
- c().requestResync(i, { auto: !0 });
2684
- });
2685
- }), n;
2686
- },
2687
- createLiveSignaling: (t) => {
2688
- let n = c().games[t];
2689
- if (n?.game !== "tanks_live" || n.scope !== e?.getScope?.()) throw Error("Partida no disponible");
2690
- let r = e;
2691
- return S({
2692
- roomId: n.roomId,
2693
- send: (n, i) => {
2694
- if (e !== r || c().games[t]?.scope !== r.getScope()) throw Error("La sesión cambió");
2695
- return r.send(n, i);
2696
- }
2697
- });
2698
- },
2699
- liveFinish: (t, n) => {
2700
- let r = c().games[t];
2701
- r?.game === "tanks_live" && r.scope === e?.getScope?.() && r.status === "active" && [r.hostId, r.guestId].includes(String(n)) && s((e) => ({ games: {
2702
- ...e.games,
2703
- [t]: {
2704
- ...r,
2705
- status: "won",
2706
- winnerId: String(n)
2707
- }
2708
- } }));
2709
- },
2710
- liveRematch: (t) => {
2711
- let n = c().games[t];
2712
- if (n?.game === "tanks_live" && n.scope === e?.getScope?.() && Y(n)) return c().invite({
2713
- roomId: n.roomId,
2714
- opponentId: n.ownId === n.hostId ? n.guestId : n.hostId,
2715
- gameType: "tanks_live",
2716
- rematchOf: n.gameId
2717
- });
2718
- },
2719
- sendEvent: async (t, n) => {
2720
- if (!e) throw Error("Chat no disponible");
2721
- let r = e, i = r.getScope(), a = String(r.getUserId() ?? ""), o = Mr(i, t, n.game_id), l = ke(n);
2722
- if (c().ingest({
2723
- room_id: t,
2724
- user_id: a,
2725
- message: l
2726
- }, i, a), !c().games[o]?.seen[n.event_id]) throw Error("Evento de partida inválido");
2727
- let u = (e, t = !0) => s((r) => {
2728
- let i = r.games[o];
2729
- return !i || t && i.pendingEvent?.event_id !== n.event_id ? r : { games: {
2730
- ...r.games,
2731
- [o]: {
2732
- ...i,
2733
- ...e
2734
- }
2735
- } };
2736
- });
2737
- u({
2738
- pending: !0,
2739
- pendingEvent: n,
2740
- error: ""
2741
- }, !1);
2742
- try {
2743
- await r.send(t, l), u({
2744
- pending: !1,
2745
- pendingEvent: null
2746
- }), c().afterGameChange(o);
2747
- } catch (e) {
2748
- throw u({
2749
- pending: !1,
2750
- error: e.message || "No se pudo enviar. Reintenta el mismo evento."
2751
- }), e;
2752
- }
2753
- return o;
2754
- },
2755
- handleResync: (e, t, n, r) => {
2756
- let i = c().games[e], a = p(i), o = {
2757
- ...i.seen,
2758
- [t.event_id]: !0
2759
- }, l = (t) => {
2760
- s((n) => ({ games: {
2761
- ...n.games,
2762
- [e]: t
2763
- } })), c().afterGameChange(e);
2764
- };
2765
- if (n === r || ![i.hostId, i.guestId].includes(n) || ["closed", "declined"].includes(i.status)) {
2766
- l({
2767
- ...i,
2768
- seen: o
2769
- });
2770
- return;
2771
- }
2772
- let u = {
2773
- ...Ir,
2774
- ...i.sync
2775
- };
2776
- if (![a.requestType, a.stateType].includes(t.type)) {
2777
- l({
2778
- ...i,
2779
- seen: o
2780
- });
2781
- return;
2782
- }
2783
- let d = t.type === a.stateType;
2784
- if (d && !u.outgoing.includes(t.data.request_event_id)) {
2785
- l({
2786
- ...i,
2787
- seen: o
2788
- });
2789
- return;
2790
- }
2791
- let f = a.rebuild(i, t.data);
2792
- if (!f) {
2793
- l({
2794
- ...i,
2795
- seen: o,
2796
- sync: d ? {
2797
- ...u,
2798
- status: "failed",
2799
- message: "El rival envió un estado de partida inválido."
2800
- } : u
2801
- });
2802
- return;
2803
- }
2804
- let m = a.compare(i, t.data), h = {
2805
- ...u,
2806
- status: "ok",
2807
- offer: null,
2808
- auto: !1,
2809
- message: ""
2810
- }, g, _ = !d, v = !1, y = m === "mixed" ? a.merge(i, t.data) : null;
2811
- if (m === "equal" || m === "behind") g = {
2812
- ...f,
2813
- sync: h
2814
- }, a.covers(i, t.data) && (g = {
2815
- ...g,
2816
- pendingEvent: null
2817
- });
2818
- else if (y) {
2819
- let e = a.rebuild(i, y);
2820
- g = e ? {
2821
- ...e,
2822
- sync: h
2823
- } : {
2824
- ...i,
2825
- sync: {
2826
- ...u,
2827
- status: "failed",
2828
- message: "No se pudo reconstruir la partida local."
2829
- }
2830
- }, _ = !!e, v = !!e;
2831
- } else if (m === "ahead" || n === i.guestId) {
2832
- let e = a.rebuild(i, a.historyOf(i));
2833
- g = e ? {
2834
- ...e,
2835
- sync: h
2836
- } : {
2837
- ...i,
2838
- sync: {
2839
- ...u,
2840
- status: "failed",
2841
- message: "No se pudo reconstruir la partida local."
2842
- }
2843
- }, _ = !!e, v = !!e;
2844
- } else g = {
2845
- ...i,
2846
- status: "conflict",
2847
- error: "El anfitrión tiene otra versión de la partida. Revísala antes de aceptarla.",
2848
- sync: {
2849
- ...u,
2850
- status: "incompatible",
2851
- offer: a.offerOf(t.data),
2852
- message: ""
2853
- }
2854
- };
2855
- g = {
2856
- ...g,
2857
- seen: a.markSeen(o, g)
2858
- };
2859
- let b = Date.now(), x = g.sync.replies.filter((e) => b - e < 3e4), S = null;
2860
- if (_ && x.length < 6) try {
2861
- S = Kr(i, a.stateType, {
2862
- ...a.historyOf(g),
2863
- request_event_id: t.event_id
2864
- });
2865
- } catch {
2866
- S = null;
2867
- }
2868
- S && (g = {
2869
- ...g,
2870
- seen: {
2871
- ...g.seen,
2872
- [S.event_id]: !0
2873
- },
2874
- sync: {
2875
- ...g.sync,
2876
- replies: [...x, b],
2877
- outgoing: [...g.sync.outgoing, S.event_id].slice(-8)
2878
- }
2879
- }), l(g), S && c().sendResync(e, S).then(() => {
2880
- v && (s((t) => {
2881
- let n = t.games[e];
2882
- return !n || !p(n).covers(n, p(n).historyOf(n)) ? t : { games: {
2883
- ...t.games,
2884
- [e]: {
2885
- ...n,
2886
- pendingEvent: null,
2887
- error: ""
2888
- }
2889
- } };
2890
- }), c().afterGameChange(e));
2891
- }).catch(() => {});
2892
- },
2893
- sendResync: async (t, n) => {
2894
- let r = c().games[t];
2895
- if (!e || !r || r.scope !== e.getScope?.()) throw Error("Chat no disponible");
2896
- await e.send(r.roomId, ke(n));
2897
- },
2898
- requestResync: async (t, { auto: n = !1 } = {}) => {
2899
- let r = c().games[t];
2900
- if (!r || r.game === "tanks_live" || !e || ["closed", "declined"].includes(r.status) || r.scope !== e.getScope?.()) return;
2901
- let i = {
2902
- ...Ir,
2903
- ...r.sync
2904
- };
2905
- if (i.status === "requesting" && Date.now() - i.requestedAt < Fr || n && i.auto) return;
2906
- let a;
2907
- try {
2908
- a = Kr(r, p(r).requestType, p(r).historyOf(r));
2909
- } catch {
2910
- return;
2911
- }
2912
- let l = (e) => s((n) => {
2913
- let r = n.games[t];
2914
- return r?.sync?.requestId !== a.event_id || r.sync.status !== "requesting" ? n : { games: {
2915
- ...n.games,
2916
- [t]: {
2917
- ...r,
2918
- sync: {
2919
- ...r.sync,
2920
- status: "failed",
2921
- message: e
2922
- }
2923
- }
2924
- } };
2925
- });
2926
- s((e) => {
2927
- let r = e.games[t];
2928
- return r ? { games: {
2929
- ...e.games,
2930
- [t]: {
2931
- ...r,
2932
- seen: {
2933
- ...r.seen,
2934
- [a.event_id]: !0
2935
- },
2936
- sync: {
2937
- ...i,
2938
- status: "requesting",
2939
- requestId: a.event_id,
2940
- requestedAt: Date.now(),
2941
- auto: i.auto || n,
2942
- message: "",
2943
- outgoing: [...i.outgoing, a.event_id].slice(-8)
2944
- }
2945
- }
2946
- } } : e;
2947
- });
2948
- let u = setTimeout(() => {
2949
- o.delete(u), l("El rival no respondió a la sincronización. Reintenta cuando esté conectado.");
2950
- }, Fr);
2951
- o.add(u);
2952
- try {
2953
- await c().sendResync(t, a);
2954
- } catch (e) {
2955
- l(e.message || "No se pudo enviar la solicitud de sincronización.");
2956
- }
2957
- },
2958
- adoptResyncOffer: (e) => {
2959
- let t = c().games[e], n = t?.sync?.offer;
2960
- if (!n || t.sync.status !== "incompatible") return !1;
2961
- let r = p(t), i = r.rebuild(t, n);
2962
- return s((n) => ({ games: {
2963
- ...n.games,
2964
- [e]: i ? {
2965
- ...i,
2966
- seen: r.markSeen(t.seen, i),
2967
- pending: !1,
2968
- pendingEvent: null,
2969
- sync: {
2970
- ...t.sync,
2971
- status: "ok",
2972
- offer: null,
2973
- auto: !1,
2974
- message: ""
2975
- }
2976
- } : {
2977
- ...t,
2978
- sync: {
2979
- ...t.sync,
2980
- status: "failed",
2981
- offer: null,
2982
- message: "El estado del anfitrión ya no es válido."
2983
- }
2984
- }
2985
- } })), i && c().afterGameChange(e), !!i;
2986
- },
2987
- resyncConflicts: (e) => {
2988
- c().restoreTanks(e), Object.values(c().games).filter((t) => t.scope === e && t.status === "conflict").forEach((e) => {
2989
- c().requestResync(e.key, { auto: !0 });
2990
- });
2991
- },
2992
- retry: (t) => {
2993
- let n = c().games[t];
2994
- 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."));
2995
- }
2996
- }));
2997
- }
2998
- var X = qr(), Jr = (e) => l(X, e);
2999
- Object.assign(Jr, {
3000
- getState: X.getState,
3001
- setState: X.setState,
3002
- subscribe: X.subscribe
3003
- });
3004
- // src/assets/chatAssets.js
3005
- var Yr = "/sounds", Xr = Yr, Zr = (e) => String(e).replace(/\/+$/, "");
3006
- function Qr(e) {
3007
- Xr = e == null ? Yr : Zr(e);
3008
- }
3009
- function $r() {
3010
- return Xr;
3011
- }
3012
- function ei(e) {
3013
- return `${Xr}/${String(e).replace(/^\/+/, "")}`;
3014
- }
3015
- // src/audio/useSoundSettings.js
3016
- function ti(e) {
3017
- return s(e.subscribe, e.getSettings, e.getSettings);
3018
- }
3019
- // src/games/shared/GameSoundControls.jsx
3020
- function ni({ manager: e }) {
3021
- let { volume: t, muted: n } = ti(e), r = n || t === 0;
3022
- return /* @__PURE__ */ p("div", {
3023
- className: "chat-game-sound",
3024
- children: [/* @__PURE__ */ f("button", {
3025
- type: "button",
3026
- className: "chat-game-sound-toggle",
3027
- onClick: e.toggleMuted,
3028
- "aria-pressed": r,
3029
- "aria-label": r ? "Activar sonido del juego" : "Silenciar sonido del juego",
3030
- title: r ? "Activar sonido" : "Silenciar",
3031
- children: f(r ? d : u, { size: 15 })
3032
- }), /* @__PURE__ */ f("input", {
3033
- type: "range",
3034
- min: "0",
3035
- max: "100",
3036
- step: "5",
3037
- value: Math.round((n ? 0 : t) * 100),
3038
- onChange: (t) => e.setVolume(Number(t.target.value) / 100),
3039
- "aria-label": "Volumen del juego"
3040
- })]
3041
- });
3042
- }
3043
- // src/audio/createSoundManager.js
3044
- var ri = [
3045
- "pointerdown",
3046
- "keydown",
3047
- "touchend"
3048
- ], ii = 300, ai = 800, oi = (e) => Math.min(1, Math.max(0, Number(e) || 0));
3049
- function si(e, t) {
3050
- try {
3051
- let n = JSON.parse(localStorage.getItem(e) ?? "null");
3052
- if (n && typeof n == "object") return {
3053
- volume: oi(n.volume ?? t.volume),
3054
- muted: !!n.muted
3055
- };
3056
- } catch {}
3057
- return {
3058
- volume: oi(t.volume),
3059
- muted: !1
3060
- };
3061
- }
3062
- var ci = 1.5, li = .6;
3063
- function ui({ id: e, baseUrl: t, sounds: n, levels: r = {}, defaultVolume: i = .6, settingsFrom: a = null }) {
3064
- let o = `lira.sound.${e}`, s = typeof window < "u" ? window.AudioContext || window.webkitAudioContext : null, c = a ? a.getSettings() : si(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 = /* @__PURE__ */ new Map(), b = !1, x = !1, S = null, ee = (e) => `${String(typeof t == "function" ? t() : t).replace(/\/$/, "")}/${n[e]}`, te = (e) => (f.has(e) || f.set(e, fetch(ee(e)).then((e) => e.ok ? e.arrayBuffer() : null).catch(() => null)), f.get(e)), C = () => {
3065
- if (!s) return null;
3066
- if (!l) try {
3067
- l = new s(), u = l.createGain(), u.gain.value = c.muted ? 0 : c.volume, u.connect(l.destination);
3068
- } catch {
3069
- return l = null, null;
3070
- }
3071
- return l.state === "suspended" && l.resume().catch(() => {}), l;
3072
- }, ne = (e) => {
3073
- if (m.has(e) || !n[e]) return Promise.resolve(null);
3074
- if (!p.has(e)) {
3075
- let t = C();
3076
- if (!t) return Promise.resolve(null);
3077
- p.set(e, te(e).then((e) => e ? new Promise((n) => {
3078
- t.decodeAudioData(e.slice(0), n, () => n(null))?.catch?.(() => n(null));
3079
- }) : null).then((t) => (t || m.add(e), t)).catch(() => (m.add(e), null)));
3080
- }
3081
- return p.get(e);
3082
- }, re = (e) => oi(r[e] ?? 1), ie = (e) => {
3083
- if (!_.has(e) || v.has(e) || !d) return;
3084
- let t = C();
3085
- if (!t) return;
3086
- let n = {};
3087
- v.set(e, n), ne(e).then((r) => {
3088
- if (v.get(e) === n) {
3089
- if (!r || t.state === "closed") v.delete(e);
3090
- else try {
3091
- let { fadeIn: n = ci, trim: i = 0 } = y.get(e) ?? {}, a = t.createGain();
3092
- a.gain.setValueAtTime(0, t.currentTime), a.gain.linearRampToValueAtTime(re(e), t.currentTime + n), a.connect(u);
3093
- let o = t.createBufferSource();
3094
- o.buffer = r, o.loop = !0, i > 0 && r.duration > i * 4 && (o.loopStart = i, o.loopEnd = r.duration - i), o.connect(a), o.start(0, i > 0 && r.duration > i * 4 ? i : 0), v.set(e, {
3095
- source: o,
3096
- level: a
3097
- });
3098
- } catch {
3099
- v.delete(e);
3100
- }
3101
- }
3102
- });
3103
- }, w = (e) => {
3104
- let t = v.get(e);
3105
- if (v.delete(e), t?.source && l) try {
3106
- let n = y.get(e)?.fadeOut ?? li, r = l.currentTime;
3107
- t.level.gain.cancelScheduledValues(r), t.level.gain.setValueAtTime(t.level.gain.value, r), t.level.gain.linearRampToValueAtTime(0, r + n), t.source.stop(r + n + .05);
3108
- } catch {}
3109
- }, T = () => {
3110
- d || (d = !0, E(), C() && Object.keys(n).forEach((e) => {
3111
- f.has(e) && ne(e);
3112
- }), _.forEach(ie));
3113
- };
3114
- function E() {
3115
- x && (x = !1, ri.forEach((e) => window.removeEventListener(e, T, !0)));
3116
- }
3117
- let ae = (e) => !h.has(e) && (h.add(e), h.size > ii && h.delete(h.values().next().value), !0), oe = () => g.forEach((e) => e()), se = (e) => {
3118
- c = e, u && (u.gain.value = c.muted ? 0 : c.volume), oe();
3119
- }, D = (e) => {
3120
- let t = {
3121
- volume: oi(e.volume ?? c.volume),
3122
- muted: e.muted ?? c.muted
3123
- };
3124
- try {
3125
- localStorage.setItem(o, JSON.stringify(t));
3126
- } catch {}
3127
- se(t);
3128
- }, O = () => {
3129
- b || (b = !0, a && (c = a.getSettings(), S = a.subscribe(() => se(a.getSettings()))), !(typeof window > "u" || d) && (typeof navigator < "u" && navigator.userActivation?.hasBeenActive ? d = !0 : (x = !0, ri.forEach((e) => window.addEventListener(e, T, {
3130
- capture: !0,
3131
- passive: !0
3132
- })))));
3133
- };
3134
- return {
3135
- start: O,
3136
- dispose: () => {
3137
- E(), S && (S(), S = null), b = !1, _.clear(), v.forEach((e) => {
3138
- try {
3139
- e?.source?.stop();
3140
- } catch {}
3141
- }), v.clear(), p.clear();
3142
- let e = l;
3143
- l = null, u = null, e && e.state !== "closed" && e.close().catch(() => {});
3144
- },
3145
- preload(e = Object.keys(n)) {
3146
- O(), e.forEach((e) => {
3147
- n[e] && !m.has(e) && (te(e), l && ne(e));
3148
- });
3149
- },
3150
- play(e, { key: t } = {}) {
3151
- if (O(), t != null && !ae(`${e}:${t}`) || !n[e] || m.has(e) || !d || c.muted || c.volume === 0) return !1;
3152
- let r = C();
3153
- if (!r) return !1;
3154
- let i = Date.now();
3155
- return ne(e).then((t) => {
3156
- if (!(!t || r.state === "closed" || Date.now() - i > ai)) try {
3157
- let n = r.createBufferSource();
3158
- n.buffer = t;
3159
- let i = re(e);
3160
- if (i === 1) n.connect(u);
3161
- else {
3162
- let e = r.createGain();
3163
- e.gain.value = i, n.connect(e), e.connect(u);
3164
- }
3165
- n.start();
3166
- } catch {}
3167
- }), !0;
3168
- },
3169
- markPlayed(e, t) {
3170
- ae(`${e}:${t}`);
3171
- },
3172
- startLoop(e, t) {
3173
- O(), n[e] && !m.has(e) && (t && y.set(e, t), _.add(e), ie(e));
3174
- },
3175
- stopLoop(e) {
3176
- _.delete(e), w(e);
3177
- },
3178
- getSettings: () => a && !b ? a.getSettings() : c,
3179
- setVolume: a ? a.setVolume : (e) => D({
3180
- volume: e,
3181
- muted: oi(e) === 0 && c.muted
3182
- }),
3183
- setMuted: a ? a.setMuted : (e) => D({ muted: !!e }),
3184
- toggleMuted: a ? a.toggleMuted : () => D({ muted: !c.muted }),
3185
- subscribe(e) {
3186
- return O(), g.add(e), () => g.delete(e);
3187
- }
3188
- };
3189
- }
3190
- // src/games/connect4/connect4Sounds.js
3191
- var Z = ui({
3192
- id: "connect4",
3193
- baseUrl: () => ei("connect4"),
3194
- sounds: {
3195
- invite: "invite.ogg",
3196
- start: "start.ogg",
3197
- drop: "drop.ogg",
3198
- turn: "turn.ogg",
3199
- win: "win.ogg",
3200
- lose: "lose.ogg",
3201
- draw: "draw.ogg",
3202
- close: "close.ogg"
3203
- }
3204
- }), di = 140, Q = /* @__PURE__ */ new Map(), fi = /* @__PURE__ */ new Set(), $ = null, pi = (e, t) => e != null && t != null && String(e) === String(t), mi = () => typeof window < "u" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
3205
- function hi(e, t) {
3206
- e.status === "won" ? Z.play(pi(e.winnerId, e.ownId) ? "win" : "lose", { key: t }) : e.status === "draw" ? Z.play("draw", { key: t }) : e.status === "active" && pi(e.turnId, e.ownId) && Z.play("turn", { key: t });
3207
- }
3208
- function gi(e) {
3209
- let t = Q.get(e);
3210
- if (!t) return;
3211
- clearTimeout(t.timer), Q.delete(e), Z.play("drop", { key: e });
3212
- let n = setTimeout(() => {
3213
- fi.delete(n), hi(t.game, e);
3214
- }, di);
3215
- fi.add(n);
3216
- }
3217
- function _i(e) {
3218
- let t = e.lastMove?.eventId;
3219
- if (!t || Q.has(t)) return;
3220
- let n = mi() ? 0 : 440;
3221
- Q.set(t, {
3222
- game: e,
3223
- timer: setTimeout(() => gi(t), n)
3224
- });
3225
- }
3226
- function vi(e, t) {
3227
- t ? t.status === "invited" && e.status === "active" ? Z.play("start", { key: e.lastEventId }) : e.ply > t.ply ? _i(e) : (e.status === "closed" && e.closedBy != null || e.status === "declined") && t.status !== e.status && Z.play("close", { key: e.gameId }) : e.status === "invited" && pi(e.guestId, e.ownId) && Z.play("invite", { key: e.inviteEventId });
3228
- }
3229
- var yi = () => $ != null;
3230
- function bi() {
3231
- if ($) return $;
3232
- Z.start();
3233
- let e = Jr.subscribe((e, t) => {
3234
- e.games !== t.games && Object.entries(e.games).forEach(([e, n]) => {
3235
- let r = t.games[e];
3236
- n.game && n.game !== "connect4" || n !== r && n.ownId != null && vi(n, r);
3237
- });
3238
- }), t = () => {
3239
- $ === t && ($ = null, e(), Q.forEach(({ timer: e }) => clearTimeout(e)), Q.clear(), fi.forEach(clearTimeout), fi.clear());
3240
- };
3241
- return $ = t, t;
3242
- }
3243
- export { x as C, S, L as _, ui as a, ce as b, $r as c, Jr as d, ir as f, R as g, pn as h, bi as i, Qr as l, En as m, yi as n, ni as o, wn as p, gi as r, ei as s, Z as t, X as u, Yt as v, m as w, Ce as x, P as y };
3244
-
3245
- //# sourceMappingURL=connect4Sounds-Cv0q31VW.js.map