@minicode-dev/chat 0.1.7 → 0.1.8

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 (37) hide show
  1. package/README.md +25 -0
  2. package/dist/chunks/{BattleshipGameCard-CAWHxqJE.js → BattleshipGameCard-BFqA0cjT.js} +247 -246
  3. package/dist/chunks/{BattleshipGameCard-CAWHxqJE.js.map → BattleshipGameCard-BFqA0cjT.js.map} +1 -1
  4. package/dist/chunks/{ChatContext-CUiEAMKK.js → ChatContext-dty_KPDX.js} +2 -2
  5. package/dist/chunks/{ChatContext-CUiEAMKK.js.map → ChatContext-dty_KPDX.js.map} +1 -1
  6. package/dist/chunks/TanksGameCard-D0n-lzTs.js +1535 -0
  7. package/dist/chunks/TanksGameCard-D0n-lzTs.js.map +1 -0
  8. package/dist/chunks/TanksLiveGameCard-BmNRXP66.js +849 -0
  9. package/dist/chunks/TanksLiveGameCard-BmNRXP66.js.map +1 -0
  10. package/dist/chunks/WebRtcLab-B7xBlJy1.js +510 -0
  11. package/dist/chunks/WebRtcLab-B7xBlJy1.js.map +1 -0
  12. package/dist/chunks/{connect4Sounds-BDXQAvU1.js → connect4Sounds-BN7d_TM2.js} +654 -618
  13. package/dist/chunks/connect4Sounds-BN7d_TM2.js.map +1 -0
  14. package/dist/chunks/createLiveScene-CtYPcOPo.js +364 -0
  15. package/dist/chunks/createLiveScene-CtYPcOPo.js.map +1 -0
  16. package/dist/chunks/createPeerLink-qei05vpV.js +478 -0
  17. package/dist/chunks/createPeerLink-qei05vpV.js.map +1 -0
  18. package/dist/chunks/createTankScene-CV7Brxmt.js +685 -0
  19. package/dist/chunks/createTankScene-CV7Brxmt.js.map +1 -0
  20. package/dist/chunks/fx-BHsl4S_J.js +1470 -0
  21. package/dist/chunks/fx-BHsl4S_J.js.map +1 -0
  22. package/dist/chunks/gameStatus-Cu1Z8un9.js +69 -0
  23. package/dist/chunks/gameStatus-Cu1Z8un9.js.map +1 -0
  24. package/dist/chunks/signalFaults-Dv2YjjKy.js +36 -0
  25. package/dist/chunks/signalFaults-Dv2YjjKy.js.map +1 -0
  26. package/dist/chunks/tanksSounds-C99OD2xD.js +177 -0
  27. package/dist/chunks/tanksSounds-C99OD2xD.js.map +1 -0
  28. package/dist/index.js +1861 -1829
  29. package/dist/index.js.map +1 -1
  30. package/dist/styles.css +1 -1
  31. package/index.d.ts +61 -0
  32. package/package.json +1 -1
  33. package/dist/chunks/TanksGameCard-BEnXTz_J.js +0 -1705
  34. package/dist/chunks/TanksGameCard-BEnXTz_J.js.map +0 -1
  35. package/dist/chunks/connect4Sounds-BDXQAvU1.js.map +0 -1
  36. package/dist/chunks/createTankScene-BuliAxwR.js +0 -2150
  37. package/dist/chunks/createTankScene-BuliAxwR.js.map +0 -1
@@ -0,0 +1,849 @@
1
+ import { d as e, o as t } from "./connect4Sounds-BN7d_TM2.js";
2
+ import { a as n, n as r, o as i } from "./createPeerLink-qei05vpV.js";
3
+ import { t as a } from "./ChatContext-dty_KPDX.js";
4
+ import { a as o, i as s, n as c, r as l, t as u } from "./tanksSounds-C99OD2xD.js";
5
+ import { memo as d, useContext as f, useEffect as p, useRef as m, useState as h } from "react";
6
+ import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
7
+ // \0rolldown/runtime.js
8
+ var y = Object.defineProperty, b = (e, t) => {
9
+ let n = {};
10
+ for (var r in e) y(n, r, {
11
+ get: e[r],
12
+ enumerable: !0
13
+ });
14
+ return t || y(n, Symbol.toStringTag, { value: "Module" }), n;
15
+ }, x = Object.freeze({
16
+ speed: 16,
17
+ reverse: 9,
18
+ turn: 1.8,
19
+ acceleration: 28,
20
+ radius: 2,
21
+ reloadMs: 1500,
22
+ shellSpeed: 60,
23
+ damage: 25
24
+ }), S = (e, t, n) => Math.max(t, Math.min(n, e)), C = (e, t) => Math.atan2(Math.sin(t - e), Math.cos(t - e));
25
+ function w() {
26
+ return {
27
+ size: 120,
28
+ bounds: {
29
+ minX: 0,
30
+ maxX: 120,
31
+ minZ: 0,
32
+ maxZ: 120
33
+ },
34
+ obstacles: [
35
+ [
36
+ 42,
37
+ 35,
38
+ 4
39
+ ],
40
+ [
41
+ 78,
42
+ 85,
43
+ 4
44
+ ],
45
+ [
46
+ 60,
47
+ 30,
48
+ 3
49
+ ],
50
+ [
51
+ 60,
52
+ 90,
53
+ 3
54
+ ],
55
+ [
56
+ 35,
57
+ 65,
58
+ 3
59
+ ],
60
+ [
61
+ 85,
62
+ 55,
63
+ 3
64
+ ],
65
+ [
66
+ 60,
67
+ 60,
68
+ 5
69
+ ]
70
+ ].map(([e, t, n], r) => ({
71
+ x: e,
72
+ z: t,
73
+ r: n,
74
+ kind: r % 2 ? "tree" : "rock"
75
+ }))
76
+ };
77
+ }
78
+ function T(e, t) {
79
+ return {
80
+ id: String(e),
81
+ x: t ? 102 : 18,
82
+ z: 60,
83
+ yaw: t ? Math.PI : 0,
84
+ turretYaw: t ? Math.PI : 0,
85
+ speed: 0,
86
+ hp: 100,
87
+ alive: !0,
88
+ color: t ? "#d7463f" : "#54a34a"
89
+ };
90
+ }
91
+ function E(e, t, n, r = x.radius) {
92
+ let i = n.bounds;
93
+ return e >= i.minX + r && e <= i.maxX - r && t >= i.minZ + r && t <= i.maxZ - r && !n.obstacles.some((n) => Math.hypot(e - n.x, t - n.z) < n.r + r);
94
+ }
95
+ function D(e, t, n, r) {
96
+ if (!e.alive) return;
97
+ let i = S(Number(t.throttle) || 0, -1, 1), a = S(Number(t.steer) || 0, -1, 1), o = i * (i < 0 ? x.reverse : x.speed);
98
+ e.speed += S(o - e.speed, -x.acceleration * n, x.acceleration * n), e.yaw += a * x.turn * n, Number.isFinite(t.turretYaw) && (e.turretYaw = t.turretYaw);
99
+ let s = e.x + Math.cos(e.yaw) * e.speed * n, c = e.z + Math.sin(e.yaw) * e.speed * n;
100
+ E(s, e.z, r) ? e.x = s : e.speed = 0, E(e.x, c, r) ? e.z = c : e.speed = 0;
101
+ }
102
+ function O(e, t, n, r, i, a, o) {
103
+ let s = n - e, c = r - t, l = s * s + c * c, u = l ? S(((i - e) * s + (a - t) * c) / l, 0, 1) : 0;
104
+ return Math.hypot(e + s * u - i, t + c * u - a) <= o ? u : null;
105
+ }
106
+ function k(e, t, n, r) {
107
+ let i = e.x + Math.cos(e.yaw) * x.shellSpeed * t, a = e.z + Math.sin(e.yaw) * x.shellSpeed * t, o = null;
108
+ for (let t of n.obstacles) {
109
+ let n = O(e.x, e.z, i, a, t.x, t.z, t.r);
110
+ n !== null && (!o || n < o.t) && (o = {
111
+ t: n,
112
+ kind: "obstacle"
113
+ });
114
+ }
115
+ for (let t of r) {
116
+ if (!t.alive || t.id === e.owner) continue;
117
+ let n = O(e.x, e.z, i, a, t.x, t.z, x.radius);
118
+ n !== null && (!o || n < o.t) && (o = {
119
+ t: n,
120
+ kind: "tank",
121
+ target: t.id
122
+ });
123
+ }
124
+ 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, !E(i, a, {
125
+ ...n,
126
+ obstacles: []
127
+ }, 0) || e.age > 3 ? { kind: "terrain" } : null);
128
+ }
129
+ function ee(e, t, n) {
130
+ let r = S(n, 0, 1);
131
+ return {
132
+ ...t,
133
+ x: e.x + (t.x - e.x) * r,
134
+ z: e.z + (t.z - e.z) * r,
135
+ yaw: e.yaw + C(e.yaw, t.yaw) * r,
136
+ turretYaw: e.turretYaw + C(e.turretYaw, t.turretYaw) * r
137
+ };
138
+ }
139
+ // src/games/tanks-live/net/createLiveMatch.js
140
+ var A = (e) => typeof e == "number" && Number.isFinite(e), j = (e) => typeof e == "string" && e.length > 0 && e.length < 160;
141
+ function M({ game: e, selfId: t, isHost: a = String(t) === String(e.hostId), signaling: o, onChange: s = () => {}, peerFactory: c = r, iceServers: l, iceTransportPolicy: u, RTCPeerConnectionImpl: d } = {}) {
142
+ t = String(t);
143
+ let f = [String(e.hostId), String(e.guestId)];
144
+ if (!f.includes(t) || f[0] === f[1]) throw Error("Invalid live match players");
145
+ let p = f.find((e) => e !== t), m = w(), h = f.map(T), g = [], _ = [], v = {}, y = 0, b = 0, S = 0, C = 0, O = "connecting", M = null, N = !1, P = {
146
+ phase: "idle",
147
+ rtt: null,
148
+ route: null
149
+ }, F = !1, I = !1, L = null, R = [], z = null, B = null, V = /* @__PURE__ */ new Map(), H = /* @__PURE__ */ new Set(), U = /* @__PURE__ */ new Set(), W = () => h.find((e) => e.id === t), G = () => h.find((e) => e.id === p), K = () => {
150
+ N || s({
151
+ status: O,
152
+ winner: M,
153
+ net: P
154
+ });
155
+ }, q = (e) => {
156
+ _.push(e), _.length > 200 && _.shift();
157
+ }, J = (t) => $.sendEvent({
158
+ ...t,
159
+ g: e.gameId,
160
+ r: S
161
+ }), Y = (e) => {
162
+ H.add(e), H.size > 2048 && H.delete(H.values().next().value);
163
+ }, X = () => ({
164
+ k: "snapshot",
165
+ hp: h.map((e) => e.hp),
166
+ status: O,
167
+ winner: M,
168
+ reason: L
169
+ });
170
+ function Z() {
171
+ h = f.map(T), g = [], R = [], z = null, B = null, V.clear(), H.clear(), U.clear(), I = !1, L = null, M = null, O = P.phase === "connected" ? "playing" : "connecting", q({ k: "rematch" }), K();
172
+ }
173
+ function Q(e, t = !1) {
174
+ (O !== "over" || t && M !== e) && (O = "over", M = e, g = [], q({
175
+ k: "over",
176
+ winner: M
177
+ }), K());
178
+ }
179
+ function te(e, t, n) {
180
+ if (O !== "playing" || !j(t.id) || H.has(t.id)) return !1;
181
+ let r = h.find((t) => t.id === e);
182
+ if (!r?.alive || y - (V.get(e) ?? -Infinity) < x.reloadMs - 20 || ![
183
+ t.x,
184
+ t.z,
185
+ t.yaw
186
+ ].every(A) || Math.hypot(t.x - (e === p && B ? B.x : r.x), t.z - (e === p && B ? B.z : r.z)) > 6) return !1;
187
+ Y(t.id), V.set(e, y);
188
+ let i = {
189
+ ...t,
190
+ k: "fire",
191
+ owner: e,
192
+ x: t.x + Math.cos(t.yaw) * 2.8,
193
+ z: t.z + Math.sin(t.yaw) * 2.8,
194
+ y: 1.4,
195
+ age: 0
196
+ };
197
+ return g.push(i), q(i), n && J({
198
+ ...t,
199
+ k: "fire"
200
+ }), !0;
201
+ }
202
+ function ne(t) {
203
+ if (N || O !== "playing" || t?.g !== e.gameId || t.r !== S || !Array.isArray(t.p) || t.p.length !== 5 || !t.p.every(A)) return;
204
+ let [n, r, i, a, o] = t.p;
205
+ if (!E(n, r, m) || Math.abs(o) > x.speed + .1 || Math.abs(i) > 1e6 || Math.abs(a) > 1e6) return;
206
+ let s = z === null ? .1 : Math.max(0, (y - z) / 1e3), c = B || G();
207
+ if (Math.hypot(n - c.x, r - c.z) > x.speed * s + 3) return;
208
+ let l = {
209
+ ...G(),
210
+ x: n,
211
+ z: r,
212
+ yaw: i,
213
+ turretYaw: a,
214
+ speed: o
215
+ };
216
+ B = l, z = y, R.push({
217
+ time: y,
218
+ pose: l
219
+ }), R.length > 30 && R.shift();
220
+ }
221
+ function re(n) {
222
+ if (!N && n && n.g === e.gameId && Number.isInteger(n.r)) {
223
+ if (n.k === "round" && !a && O === "over" && U.has(t) && n.r === S + 1) S = n.r, Z();
224
+ else if (n.r === S) {
225
+ if (n.k === "sync" && a) J(X());
226
+ else if (n.k === "snapshot" && !a && Array.isArray(n.hp) && n.hp.length === 2 && n.hp.every((e) => Number.isInteger(e) && e >= 0 && e <= 100)) {
227
+ let e = n.status === "playing" && n.winner === null && n.hp.every((e) => e > 0), t = n.status === "over" && f.includes(n.winner) && (n.hp[1 - f.indexOf(n.winner)] === 0 || n.reason === "resigned");
228
+ if (!e && !t) return;
229
+ h.forEach((e, t) => {
230
+ e.hp = n.hp[t], e.alive = e.hp > 0;
231
+ }), t && (I = !1, L = n.reason, Q(n.winner, !0));
232
+ } else n.k === "resign" ? (L = "resigned", Q(t, a), a && J(X())) : n.k === "rematch" && O === "over" ? (U.add(p), ie()) : O === "playing" && (n.k === "fire" && te(p, n, !1), !a && n.k === "hit" && j(n.id) && !H.has(`hit:${n.id}`) && f.includes(n.target) && Array.isArray(n.hp) && n.hp.length === 2 && n.hp.every((e, t) => Number.isInteger(e) && e >= 0 && e <= h[t].hp) && [n.x, n.z].every(A) && (Y(`hit:${n.id}`), h.forEach((e, t) => {
233
+ e.hp = n.hp[t], e.alive = e.hp > 0;
234
+ }), g = g.filter((e) => e.id !== n.id), q(n)), !a && n.k === "destroyed" && f.includes(n.target) && !H.has(`destroyed:${n.target}`) && h.find((e) => e.id === n.target).hp === 0 && (Y(`destroyed:${n.target}`), q(n)), !a && n.k === "over" && f.includes(n.winner) && h.find((e) => e.id !== n.winner).hp === 0 && Q(n.winner));
235
+ }
236
+ }
237
+ }
238
+ let $ = c({
239
+ signaling: o && {
240
+ send(t) {
241
+ let r = n(t);
242
+ if (!r) return Promise.reject(/* @__PURE__ */ Error("Invalid live signal"));
243
+ let a = i({
244
+ ...r,
245
+ liveGame: e.gameId
246
+ });
247
+ return a ? o.send(a) : Promise.reject(/* @__PURE__ */ Error("Live signal too large"));
248
+ },
249
+ subscribe(t) {
250
+ return o.subscribe((r) => {
251
+ n(r?.text)?.liveGame === e.gameId && t(r);
252
+ });
253
+ }
254
+ },
255
+ selfId: t,
256
+ peerId: p,
257
+ roomId: e.roomId,
258
+ iceServers: l,
259
+ iceTransportPolicy: u,
260
+ RTCPeerConnectionImpl: d,
261
+ onMove: ne,
262
+ onEvent: re,
263
+ onChange(e) {
264
+ let t = P.phase;
265
+ if (P = e, e.phase === "connected") {
266
+ let e = F;
267
+ F = !0, O !== "over" && (O = "playing"), t !== "connected" && queueMicrotask(() => {
268
+ N || (I && J({ k: "resign" }), a && e ? J(X()) : a || J({ k: "sync" }));
269
+ });
270
+ } else O !== "over" && (O = F ? "disconnected" : "connecting");
271
+ K();
272
+ }
273
+ });
274
+ function ie() {
275
+ a && U.size === 2 && (S++, J({ k: "round" }), Z());
276
+ }
277
+ return a ? $.connect() : $.setListening(!0), {
278
+ setInput(e) {
279
+ v = { ...e };
280
+ },
281
+ step(n) {
282
+ if (N) return;
283
+ let r = Math.max(0, Math.min(Number(n) || 0, 100));
284
+ if (y += r, O !== "playing") return;
285
+ let i = r / 1e3, o = y - 100;
286
+ for (; R.length > 1 && R[1].time <= o;) R.shift();
287
+ if (R.length) {
288
+ let e = R[0], t = R[1] || e, n = ee(e.pose, t.pose, t.time === e.time ? 1 : (o - e.time) / (t.time - e.time));
289
+ for (let e of [
290
+ "x",
291
+ "z",
292
+ "yaw",
293
+ "turretYaw",
294
+ "speed"
295
+ ]) G()[e] = n[e];
296
+ }
297
+ for (let e = i; e > 0; e -= .016) D(W(), v, Math.min(e, .016), m);
298
+ v.fire && te(t, {
299
+ id: `${t}:${S}:${++C}`,
300
+ x: W().x,
301
+ z: W().z,
302
+ yaw: W().turretYaw,
303
+ t: y
304
+ }, !0);
305
+ let s = P.rtt > 250 || P.move?.lossPct > 15 ? 10 : P.rtt > 100 ? 15 : 20;
306
+ if (y >= b) {
307
+ b = y + 1e3 / s;
308
+ let t = W();
309
+ $.sendMove({
310
+ g: e.gameId,
311
+ r: S,
312
+ p: [
313
+ t.x,
314
+ t.z,
315
+ t.yaw,
316
+ t.turretYaw,
317
+ t.speed
318
+ ],
319
+ t: y
320
+ });
321
+ }
322
+ g = g.filter((e) => {
323
+ let t = k(e, i, m, h);
324
+ if (!t) return !0;
325
+ if (a && t.target && O === "playing") {
326
+ let n = h.find((e) => e.id === t.target);
327
+ n.hp = Math.max(0, n.hp - x.damage), n.alive = n.hp > 0;
328
+ let r = {
329
+ k: "hit",
330
+ id: e.id,
331
+ target: n.id,
332
+ dmg: x.damage,
333
+ hp: h.map((e) => e.hp),
334
+ x: e.x,
335
+ z: e.z
336
+ };
337
+ if (J(r), q(r), !n.alive) {
338
+ let t = {
339
+ k: "destroyed",
340
+ target: n.id
341
+ };
342
+ J(t), q(t), J({
343
+ k: "over",
344
+ winner: e.owner
345
+ }), Q(e.owner);
346
+ }
347
+ } else q({
348
+ k: "impact",
349
+ kind: t.kind,
350
+ x: e.x,
351
+ z: e.z
352
+ });
353
+ return !1;
354
+ });
355
+ },
356
+ getRender() {
357
+ let e = {
358
+ arena: m,
359
+ tanks: h.map((e) => ({
360
+ ...e,
361
+ self: e.id === t,
362
+ reload: Math.min(1, (y - (V.get(e.id) ?? -Infinity)) / x.reloadMs)
363
+ })),
364
+ shells: g.map((e) => ({ ...e })),
365
+ events: _,
366
+ status: O,
367
+ winner: M,
368
+ net: P
369
+ };
370
+ return _ = [], e;
371
+ },
372
+ rematch() {
373
+ !N && O === "over" && (U.add(t), J({ k: "rematch" }), ie());
374
+ },
375
+ resign() {
376
+ !N && O !== "over" && (I = !0, L = "resigned", J({ k: "resign" }), Q(p));
377
+ },
378
+ destroy() {
379
+ N || (N = !0, $.destroy(), g = [], R = [], _ = []);
380
+ }
381
+ };
382
+ }
383
+ var N = 180 / Math.PI, P = (e, t) => Number.isFinite(e) ? e : t;
384
+ function F(e) {
385
+ let t = e || {}, n = t.bounds || t;
386
+ if (Number.isFinite(n.minX) && Number.isFinite(n.maxX) && Number.isFinite(n.minZ) && Number.isFinite(n.maxZ)) return I({
387
+ minX: n.minX,
388
+ minZ: n.minZ,
389
+ maxX: n.maxX,
390
+ maxZ: n.maxZ
391
+ });
392
+ let r = P(t.width, P(t.size, 120)), i = P(t.depth, P(t.height, P(t.size, r)));
393
+ return I(t.centered === !0 || t.origin === "center" ? {
394
+ minX: -r / 2,
395
+ minZ: -i / 2,
396
+ maxX: r / 2,
397
+ maxZ: i / 2
398
+ } : {
399
+ minX: 0,
400
+ minZ: 0,
401
+ maxX: r,
402
+ maxZ: i
403
+ });
404
+ }
405
+ function I(e) {
406
+ return {
407
+ ...e,
408
+ width: e.maxX - e.minX,
409
+ depth: e.maxZ - e.minZ,
410
+ cx: (e.minX + e.maxX) / 2,
411
+ cz: (e.minZ + e.maxZ) / 2
412
+ };
413
+ }
414
+ function L(e) {
415
+ return (e?.obstacles || []).filter((e) => Number.isFinite(e?.x) && Number.isFinite(e?.z)).map((e) => ({
416
+ x: e.x,
417
+ z: e.z,
418
+ r: P(e.r, P(e.radius, 1.5)),
419
+ kind: e.kind === "tree" ? "tree" : "rock"
420
+ }));
421
+ }
422
+ var R = (e) => e ? e.k ?? e.type ?? null : null;
423
+ function z(e, t) {
424
+ let n = t || [], r = e?.tank ?? e?.by ?? e?.owner ?? e?.from;
425
+ if (r != null) {
426
+ let e = n.find((e) => String(e.id) === String(r));
427
+ if (e) return e;
428
+ }
429
+ if (!Number.isFinite(e?.x) || !Number.isFinite(e?.z)) return null;
430
+ let i = null, a = Infinity;
431
+ for (let t of n) {
432
+ let n = (t.x - e.x) ** 2 + (t.z - e.z) ** 2;
433
+ n < a && (a = n, i = t);
434
+ }
435
+ return i;
436
+ }
437
+ var B = (e, t) => t == null ? null : (e || []).find((e) => String(e.id) === String(t)) || null, V = (e) => (e || []).find((e) => e.self) || null, H = (e, t = !0) => !t || e <= 25 ? 2 : +(e <= 50), U = (e) => {
438
+ let t = e % (Math.PI * 2);
439
+ return t > Math.PI && (t -= Math.PI * 2), t < -Math.PI && (t += Math.PI * 2), t;
440
+ };
441
+ function W({ moveSpeed: e = .6, turnSpeed: t = .35, holdMs: n = 160 } = {}) {
442
+ let r = null, i = !1, a = !1, o = 0, s = 0;
443
+ return {
444
+ update(c, l) {
445
+ let u = [];
446
+ if (!c || c.alive === !1) return i && u.push({ type: "move_end" }), a && u.push({ type: "turret_end" }), i = a = !1, r = null, u;
447
+ let d = Math.max(1, l) / 1e3;
448
+ if (r) {
449
+ let f = Math.hypot(c.x - r.x, c.z - r.z) / d, p = Math.abs(U((c.yaw ?? 0) - r.yaw)) / d, m = Math.abs(U((c.turretYaw ?? 0) - (c.yaw ?? 0) - r.rel)) / d, h = f > e || p > t;
450
+ o = h ? 0 : o + l, h && !i ? (i = !0, u.push({ type: "move_start" })) : !h && i && o >= n && (i = !1, u.push({ type: "move_end" }));
451
+ let g = m > t;
452
+ s = g ? 0 : s + l, g && !a ? (a = !0, u.push({ type: "turret_start" })) : !g && a && s >= n && (a = !1, u.push({ type: "turret_end" }));
453
+ }
454
+ return r = {
455
+ x: c.x,
456
+ z: c.z,
457
+ yaw: c.yaw ?? 0,
458
+ rel: U((c.turretYaw ?? 0) - (c.yaw ?? 0))
459
+ }, u;
460
+ },
461
+ reset() {
462
+ r = null, i = a = !1, o = s = 0;
463
+ },
464
+ get moving() {
465
+ return i;
466
+ },
467
+ get turning() {
468
+ return a;
469
+ }
470
+ };
471
+ }
472
+ function G(e) {
473
+ switch (R(e)) {
474
+ case "fire": return [{ type: "fire" }, { type: "projectile_start" }];
475
+ case "impact": return [{
476
+ type: "impact",
477
+ kind: e.kind === "obstacle" ? "obstacle" : "terrain"
478
+ }];
479
+ case "hit": return [{ type: "tank_hit" }];
480
+ case "destroyed": return [{ type: "destroyed" }];
481
+ default: return [];
482
+ }
483
+ }
484
+ function K(e) {
485
+ if (!e || e.status !== "over") return null;
486
+ let t = V(e.tanks);
487
+ return !t || e.winner == null ? null : String(e.winner) === String(t.id) ? "victory" : "defeat";
488
+ }
489
+ // src/games/tanks-live/scene/createLiveScene2d.js
490
+ function q(e, { arena: t } = {}) {
491
+ let n = document.createElement("canvas");
492
+ n.style.cssText = "width:100%;height:100%;display:block", e.appendChild(n);
493
+ let r = n.getContext("2d");
494
+ if (!r) throw n.remove(), Error("Canvas 2D unavailable");
495
+ let i = F(t), a = 1, o = 1, s = 1, c = 0, l = 0;
496
+ function u() {
497
+ a = Math.max(1, e.clientWidth), o = Math.max(1, e.clientHeight);
498
+ let t = Math.min(window.devicePixelRatio || 1, 2);
499
+ n.width = a * t, n.height = o * t, r.setTransform(t, 0, 0, t, 0, 0), s = Math.min(a / i.width, o / i.depth), c = (a - i.width * s) / 2, l = (o - i.depth * s) / 2;
500
+ }
501
+ u();
502
+ let d = typeof ResizeObserver == "function" ? new ResizeObserver(u) : null;
503
+ return d?.observe(e), {
504
+ kind: "2d",
505
+ resize: u,
506
+ screenToGround(e, t) {
507
+ return {
508
+ x: ((e + 1) * a / 2 - c) / s + i.minX,
509
+ z: ((1 - t) * o / 2 - l) / s + i.minZ
510
+ };
511
+ },
512
+ render(e) {
513
+ r.fillStyle = "#152519", r.fillRect(0, 0, a, o), r.save(), r.translate(c, l), r.scale(s, s), r.translate(-i.minX, -i.minZ), r.fillStyle = "#526348", r.fillRect(i.minX, i.minZ, i.width, i.depth);
514
+ for (let e of L(t)) r.fillStyle = e.kind === "tree" ? "#24472d" : "#929285", r.beginPath(), r.arc(e.x, e.z, e.r, 0, Math.PI * 2), r.fill();
515
+ for (let t of e.tanks || []) r.save(), r.translate(t.x, t.z), r.rotate(t.yaw), r.fillStyle = t.alive === !1 ? "#333" : t.color || "#73ce68", r.fillRect(-3, -1.8, 6, 3.6), r.restore(), r.save(), r.translate(t.x, t.z), r.rotate(t.turretYaw), r.strokeStyle = "#dce8cf", r.lineWidth = .8, r.beginPath(), r.moveTo(0, 0), r.lineTo(5, 0), r.stroke(), r.restore(), t.self && (r.strokeStyle = "#fff", r.lineWidth = .3, r.beginPath(), r.arc(t.x, t.z, 4, 0, Math.PI * 2), r.stroke());
516
+ r.fillStyle = "#ffe097";
517
+ for (let t of e.shells || []) r.beginPath(), r.arc(t.x, t.z, .7, 0, Math.PI * 2), r.fill();
518
+ r.restore();
519
+ },
520
+ dispose() {
521
+ d?.disconnect(), n.remove();
522
+ }
523
+ };
524
+ }
525
+ // src/games/tanks-live/TanksLiveGameCard.jsx
526
+ var J = /* @__PURE__ */ b({ default: () => Q }), Y = (t, n) => {
527
+ e.getState().act(t, n).catch(() => {});
528
+ }, X = (e) => {
529
+ e.throttle = 0, e.steer = 0, e.fire = !1;
530
+ };
531
+ function Z({ gameKey: n, currentUserId: r, onMinimize: i, onDismiss: d, suspended: y = !1 }) {
532
+ let b = f(a)?.config?.webrtc, x = e((e) => e.games[n]), S = m(y);
533
+ S.current = y;
534
+ let C = m(null), w = m(null), T = m(null), E = m({
535
+ throttle: 0,
536
+ steer: 0,
537
+ fire: !1
538
+ }), [D, O] = h(null), [k, ee] = h(""), [A, j] = h(!1), [N, P] = h("loading");
539
+ p(() => {
540
+ y ? (X(E.current), o()) : T.current?.resize();
541
+ }, [y]);
542
+ let F = ["active", "won"].includes(x?.status), [I, L] = h(null);
543
+ if (p(() => {
544
+ if (!F || !I || !C.current) return;
545
+ let e = !1, t = null, n = {
546
+ arena: I,
547
+ lowPower: matchMedia("(pointer: coarse)").matches,
548
+ reducedMotion: matchMedia("(prefers-reduced-motion: reduce)").matches,
549
+ onEvent: (e) => {
550
+ e.type === "context_lost" && j(!0);
551
+ }
552
+ }, r = () => {
553
+ e || (t = q(C.current, n), T.current = t, P("2d"));
554
+ };
555
+ return A ? r() : import("./createLiveScene-CtYPcOPo.js").then(({ createLiveScene: i }) => {
556
+ if (!e) try {
557
+ t = i(C.current, n), T.current = t, P("3d");
558
+ } catch {
559
+ r();
560
+ }
561
+ }).catch(r), () => {
562
+ e = !0, t?.dispose(), T.current === t && (T.current = null);
563
+ };
564
+ }, [
565
+ F,
566
+ I,
567
+ A
568
+ ]), p(() => {
569
+ if (!F || x.status !== "active" || !C.current) return;
570
+ let t = !1, i = 0, a = performance.now(), u = 0, d = null, f = W(), p = /* @__PURE__ */ new Set();
571
+ s();
572
+ let m;
573
+ try {
574
+ let t = e.getState().createLiveSignaling(n);
575
+ m = M({
576
+ iceServers: b?.iceServers,
577
+ iceTransportPolicy: b?.iceTransportPolicy,
578
+ game: x,
579
+ selfId: String(r),
580
+ isHost: String(x.hostId) === String(r),
581
+ signaling: t
582
+ }), w.current = m;
583
+ } catch (e) {
584
+ ee(e.message || "No se pudo iniciar WebRTC");
585
+ return;
586
+ }
587
+ L(m.getRender().arena);
588
+ function h() {
589
+ p.clear(), X(E.current), o();
590
+ }
591
+ function g(e, t) {
592
+ /^(INPUT|TEXTAREA|SELECT)$/.test(e.target?.tagName) || [
593
+ "KeyW",
594
+ "KeyA",
595
+ "KeyS",
596
+ "KeyD",
597
+ "ArrowUp",
598
+ "ArrowDown",
599
+ "ArrowLeft",
600
+ "ArrowRight",
601
+ "Space"
602
+ ].includes(e.code) && (e.preventDefault(), t ? p.add(e.code) : p.delete(e.code), E.current.throttle = Number(p.has("KeyW") || p.has("ArrowUp")) - Number(p.has("KeyS") || p.has("ArrowDown")), E.current.steer = Number(p.has("KeyD") || p.has("ArrowRight")) - Number(p.has("KeyA") || p.has("ArrowLeft")), E.current.fire = p.has("Space"));
603
+ }
604
+ let _ = (e) => g(e, !0), v = (e) => g(e, !1), y = C.current;
605
+ y.addEventListener("keydown", _), y.addEventListener("keyup", v), y.addEventListener("blur", h);
606
+ let D = () => {
607
+ document.hidden && h();
608
+ };
609
+ document.addEventListener("visibilitychange", D), c({ type: "engine_start" }, n);
610
+ function k(r) {
611
+ if (t) return;
612
+ let s = Math.min(80, r - a);
613
+ a = r;
614
+ let h = S.current || document.hidden;
615
+ m.setInput(h ? {
616
+ throttle: 0,
617
+ steer: 0,
618
+ fire: !1
619
+ } : E.current), m.step(s);
620
+ let g = m.getRender();
621
+ if (h || T.current?.render(g, s), h && (p.clear(), f.reset(), o()), !h) for (let e of g.events || []) for (let t of G(e)) c(t, e.id);
622
+ if (!h) for (let e of f.update(V(g.tanks), s)) c(e);
623
+ let _ = K(g);
624
+ _ && !d && (O(g), d = _, h || l(d, n), e.getState().liveFinish?.(n, g.winner)), r - u > 100 && (u = r, O(g)), i = requestAnimationFrame(k);
625
+ }
626
+ return i = requestAnimationFrame(k), () => {
627
+ t = !0, cancelAnimationFrame(i), h(), m.destroy(), w.current = null, y.removeEventListener("keydown", _), y.removeEventListener("keyup", v), y.removeEventListener("blur", h), document.removeEventListener("visibilitychange", D);
628
+ };
629
+ }, [
630
+ F,
631
+ n,
632
+ r
633
+ ]), !x) return null;
634
+ let R = String(r) === String(x.guestId), z = D?.status === "over" || x.status === "won";
635
+ function B(e) {
636
+ let t = C.current?.getBoundingClientRect(), n = V(D?.tanks);
637
+ if (!t || !n) return;
638
+ let r = T.current?.screenToGround((e.clientX - t.left) / t.width * 2 - 1, 1 - (e.clientY - t.top) / t.height * 2);
639
+ r && (E.current.turretYaw = Math.atan2(r.z - n.z, r.x - n.x));
640
+ }
641
+ let H = (e, t) => ({
642
+ onPointerDown: (n) => {
643
+ n.preventDefault(), n.currentTarget.setPointerCapture(n.pointerId), E.current[e] = t;
644
+ },
645
+ onPointerUp: () => {
646
+ E.current[e] = e !== "fire" && 0;
647
+ },
648
+ onPointerCancel: () => {
649
+ E.current[e] = e !== "fire" && 0;
650
+ },
651
+ onLostPointerCapture: () => {
652
+ E.current[e] = e !== "fire" && 0;
653
+ }
654
+ });
655
+ return /* @__PURE__ */ v("section", {
656
+ className: "chat-game-card tl-card",
657
+ "aria-label": "Tanques LIVE 3D",
658
+ children: [
659
+ /* @__PURE__ */ v("header", {
660
+ className: "tl-header",
661
+ children: [
662
+ /* @__PURE__ */ _("strong", { children: "Tanques LIVE 3D" }),
663
+ /* @__PURE__ */ _(t, { manager: u() }),
664
+ i && /* @__PURE__ */ _("button", {
665
+ onClick: i,
666
+ "aria-label": "Minimizar",
667
+ children: "−"
668
+ }),
669
+ d && /* @__PURE__ */ _("button", {
670
+ onClick: d,
671
+ "aria-label": "Ocultar",
672
+ children: "×"
673
+ })
674
+ ]
675
+ }),
676
+ x.status === "invited" && /* @__PURE__ */ v("div", {
677
+ className: "tl-invite",
678
+ children: [/* @__PURE__ */ _("p", { children: R ? "Te invitaron a un combate en tiempo real." : "Esperando que el rival acepte…" }), R && /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _("button", {
679
+ onClick: () => Y(n, "game_accept"),
680
+ children: "Aceptar"
681
+ }), /* @__PURE__ */ _("button", {
682
+ onClick: () => Y(n, "game_decline"),
683
+ children: "Rechazar"
684
+ })] })]
685
+ }),
686
+ (F || D) && /* @__PURE__ */ v(g, { children: [
687
+ /* @__PURE__ */ v("div", {
688
+ className: "tl-hud",
689
+ children: [(D?.tanks || []).map((e) => /* @__PURE__ */ v("span", { children: [
690
+ e.self ? "Tú" : "Rival",
691
+ " ",
692
+ /* @__PURE__ */ _("meter", {
693
+ min: "0",
694
+ max: "100",
695
+ value: e.hp,
696
+ "aria-label": e.self ? "Tu vida" : "Vida del rival"
697
+ }),
698
+ " ",
699
+ e.hp,
700
+ " HP"
701
+ ] }, e.id)), /* @__PURE__ */ v("span", {
702
+ role: "status",
703
+ children: [
704
+ D?.net?.phase || "Conectando WebRTC…",
705
+ " ",
706
+ D?.net?.route?.label || (typeof D?.net?.route == "string" ? D.net.route : ""),
707
+ " ",
708
+ Number.isFinite(D?.net?.rtt) ? `${Math.round(D.net.rtt)} ms` : ""
709
+ ]
710
+ })]
711
+ }),
712
+ /* @__PURE__ */ _("div", {
713
+ className: "tl-stage",
714
+ ref: C,
715
+ tabIndex: 0,
716
+ "aria-label": "Arena. WASD o flechas para conducir, ratón para apuntar, clic o espacio para disparar",
717
+ onPointerMove: B,
718
+ onPointerDown: (e) => {
719
+ B(e), e.pointerType === "mouse" && (e.currentTarget.focus(), e.currentTarget.setPointerCapture(e.pointerId), B(e), E.current.fire = !0);
720
+ },
721
+ onPointerUp: () => {
722
+ E.current.fire = !1;
723
+ },
724
+ onPointerCancel: () => {
725
+ X(E.current);
726
+ },
727
+ onLostPointerCapture: () => {
728
+ E.current.fire = !1;
729
+ }
730
+ }),
731
+ /* @__PURE__ */ v("div", {
732
+ className: "tl-controls",
733
+ children: [
734
+ /* @__PURE__ */ _("div", {
735
+ className: "tl-joystick",
736
+ role: "group",
737
+ "aria-label": "Joystick de conducción",
738
+ onPointerDown: (e) => {
739
+ e.preventDefault(), e.currentTarget.setPointerCapture(e.pointerId);
740
+ let t = e.currentTarget.getBoundingClientRect();
741
+ E.current.steer = Math.max(-1, Math.min(1, (e.clientX - t.left - t.width / 2) / (t.width / 2))), E.current.throttle = Math.max(-1, Math.min(1, -(e.clientY - t.top - t.height / 2) / (t.height / 2)));
742
+ },
743
+ onPointerMove: (e) => {
744
+ if (!e.currentTarget.hasPointerCapture(e.pointerId)) return;
745
+ let t = e.currentTarget.getBoundingClientRect();
746
+ E.current.steer = Math.max(-1, Math.min(1, (e.clientX - t.left - t.width / 2) / (t.width / 2))), E.current.throttle = Math.max(-1, Math.min(1, -(e.clientY - t.top - t.height / 2) / (t.height / 2)));
747
+ },
748
+ onPointerUp: () => X(E.current),
749
+ onPointerCancel: () => X(E.current),
750
+ onLostPointerCapture: () => X(E.current),
751
+ children: "✥"
752
+ }),
753
+ /* @__PURE__ */ v("div", {
754
+ className: "tl-drive",
755
+ "aria-label": "Controles de conducción",
756
+ children: [
757
+ /* @__PURE__ */ _("button", {
758
+ "aria-label": "Avanzar",
759
+ ...H("throttle", 1),
760
+ children: "▲"
761
+ }),
762
+ /* @__PURE__ */ _("button", {
763
+ "aria-label": "Girar izquierda",
764
+ ...H("steer", -1),
765
+ children: "◀"
766
+ }),
767
+ /* @__PURE__ */ _("button", {
768
+ "aria-label": "Retroceder",
769
+ ...H("throttle", -1),
770
+ children: "▼"
771
+ }),
772
+ /* @__PURE__ */ _("button", {
773
+ "aria-label": "Girar derecha",
774
+ ...H("steer", 1),
775
+ children: "▶"
776
+ })
777
+ ]
778
+ }),
779
+ /* @__PURE__ */ _("button", {
780
+ className: "tl-fire",
781
+ ...H("fire", !0),
782
+ children: "Disparar"
783
+ })
784
+ ]
785
+ }),
786
+ /* @__PURE__ */ _("div", {
787
+ className: "tl-reload",
788
+ children: /* @__PURE__ */ v("label", { children: [
789
+ "Recarga ",
790
+ /* @__PURE__ */ _("progress", {
791
+ max: "1",
792
+ value: V(D?.tanks)?.reload ?? 1
793
+ }),
794
+ " ",
795
+ (V(D?.tanks)?.reload ?? 1) >= 1 ? "Listo" : "Recargando…"
796
+ ] })
797
+ }),
798
+ /* @__PURE__ */ _("small", { children: "WASD / flechas · ratón o toca la arena para apuntar · espacio / clic para disparar" }),
799
+ /* @__PURE__ */ _("button", {
800
+ onClick: () => j((e) => !e),
801
+ children: N === "2d" ? "Probar 3D" : "Vista 2D"
802
+ })
803
+ ] }),
804
+ z && /* @__PURE__ */ v("p", {
805
+ role: "status",
806
+ children: [
807
+ String(D?.winner ?? x.winnerId) === String(r) ? "¡Victoria!" : "Fin del combate",
808
+ " ",
809
+ /* @__PURE__ */ _("button", {
810
+ onClick: () => {
811
+ Promise.resolve(e.getState().liveRematch?.(n)).catch(() => {});
812
+ },
813
+ children: "Revancha"
814
+ })
815
+ ]
816
+ }),
817
+ F && !z && /* @__PURE__ */ _("button", {
818
+ onClick: () => w.current?.resign(),
819
+ children: "Rendirse"
820
+ }),
821
+ x.pending && /* @__PURE__ */ _("p", {
822
+ role: "status",
823
+ children: "Enviando…"
824
+ }),
825
+ x.pendingEvent && x.error && /* @__PURE__ */ _("button", {
826
+ onClick: () => {
827
+ e.getState().retry(n).catch(() => {});
828
+ },
829
+ children: "Reintentar envío"
830
+ }),
831
+ k && /* @__PURE__ */ _("p", {
832
+ role: "alert",
833
+ children: k
834
+ }),
835
+ x.error && /* @__PURE__ */ _("p", {
836
+ role: "alert",
837
+ children: x.error
838
+ }),
839
+ !["closed", "declined"].includes(x.status) && /* @__PURE__ */ _("button", {
840
+ onClick: () => Y(n, "game_end"),
841
+ children: "Cerrar partida"
842
+ })
843
+ ]
844
+ });
845
+ }
846
+ var Q = d(Z);
847
+ export { H as a, B as c, Q as default, L as i, U as l, N as n, R as o, F as r, z as s, J as t };
848
+
849
+ //# sourceMappingURL=TanksLiveGameCard-BmNRXP66.js.map