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