@minicode-dev/chat 0.1.11 → 0.1.12

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