@myvillage/cli 2.7.0 → 2.8.0

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.
@@ -0,0 +1,634 @@
1
+ // myvillage-realtime client v0.2.0 — generated by myvillage-realtime (npm run build:client).
2
+ // Do not edit: regenerate from https://github.com/myvillageproject/myvillage-realtime
3
+ //#region src/shared/protocol.ts
4
+ /** Server simulation/snapshot rate. */
5
+ var TICK_HZ = 20;
6
+ /** Fixed client input rate; every input advances that player's sim by INPUT_DT. */
7
+ var INPUT_HZ = 30;
8
+ var INPUT_DT = 1 / 30;
9
+ var PROTOCOL_VERSION = 1;
10
+ /** WebSocket close codes the room uses (4000-4999 is app-defined). */
11
+ var CloseCode = {
12
+ Replaced: 4001,
13
+ MatchOver: 4002,
14
+ Full: 4003,
15
+ BadTicket: 4004
16
+ };
17
+ //#endregion
18
+ //#region src/shared/sim.ts
19
+ function clamp(v, min, max) {
20
+ return v < min ? min : v > max ? max : v;
21
+ }
22
+ /** Unit vector a player at `yaw` faces (yaw 0 → -Z, matching three.js cameras). */
23
+ function forwardOf(yaw) {
24
+ return {
25
+ x: -Math.sin(yaw),
26
+ z: -Math.cos(yaw)
27
+ };
28
+ }
29
+ /** Sanitise raw stick input to a vector of length <= 1. */
30
+ function normalizeMove(mx, mz) {
31
+ const x = Number.isFinite(mx) ? clamp(mx, -1, 1) : 0;
32
+ const z = Number.isFinite(mz) ? clamp(mz, -1, 1) : 0;
33
+ const len = Math.hypot(x, z);
34
+ return len > 1 ? {
35
+ x: x / len,
36
+ z: z / len
37
+ } : {
38
+ x,
39
+ z
40
+ };
41
+ }
42
+ /** Push a circle out of the arena bounds and every wall. Mutates `p`. */
43
+ function resolveCollisions(p, radius, map) {
44
+ for (let pass = 0; pass < 2; pass++) {
45
+ for (const b of map.walls) pushOutOfBox(p, radius, b);
46
+ const hx = map.width / 2 - radius;
47
+ const hz = map.depth / 2 - radius;
48
+ p.x = clamp(p.x, -hx, hx);
49
+ p.z = clamp(p.z, -hz, hz);
50
+ }
51
+ }
52
+ function pushOutOfBox(p, r, b) {
53
+ const cx = clamp(p.x, b.minX, b.maxX);
54
+ const cz = clamp(p.z, b.minZ, b.maxZ);
55
+ const dx = p.x - cx;
56
+ const dz = p.z - cz;
57
+ const d2 = dx * dx + dz * dz;
58
+ if (d2 >= r * r) return;
59
+ if (d2 > 1e-12) {
60
+ const d = Math.sqrt(d2);
61
+ p.x = cx + dx / d * r;
62
+ p.z = cz + dz / d * r;
63
+ return;
64
+ }
65
+ const left = p.x - b.minX;
66
+ const right = b.maxX - p.x;
67
+ const back = p.z - b.minZ;
68
+ const front = b.maxZ - p.z;
69
+ const m = Math.min(left, right, back, front);
70
+ if (m === left) p.x = b.minX - r;
71
+ else if (m === right) p.x = b.maxX + r;
72
+ else if (m === back) p.z = b.minZ - r;
73
+ else p.z = b.maxZ + r;
74
+ }
75
+ /** Advance a position by one input step. Mutates `p`. */
76
+ function stepMove(p, input, speed, radius, map, dt) {
77
+ const m = normalizeMove(input.mx, input.mz);
78
+ const f = forwardOf(Number.isFinite(input.yaw) ? input.yaw : 0);
79
+ const rx = -f.z;
80
+ const rz = f.x;
81
+ p.x += (rx * m.x + f.x * m.z) * speed * dt;
82
+ p.z += (rz * m.x + f.z * m.z) * speed * dt;
83
+ resolveCollisions(p, radius, map);
84
+ }
85
+ /** Distance along a ray to an AABB, or null if missed (slab method). */
86
+ function rayBox(o, d, b) {
87
+ let tmin = 0;
88
+ let tmax = Infinity;
89
+ for (const [oa, da, lo, hi] of [[
90
+ o.x,
91
+ d.x,
92
+ b.minX,
93
+ b.maxX
94
+ ], [
95
+ o.z,
96
+ d.z,
97
+ b.minZ,
98
+ b.maxZ
99
+ ]]) {
100
+ if (Math.abs(da) < 1e-12) {
101
+ if (oa < lo || oa > hi) return null;
102
+ continue;
103
+ }
104
+ let t1 = (lo - oa) / da;
105
+ let t2 = (hi - oa) / da;
106
+ if (t1 > t2) [t1, t2] = [t2, t1];
107
+ tmin = Math.max(tmin, t1);
108
+ tmax = Math.min(tmax, t2);
109
+ if (tmin > tmax) return null;
110
+ }
111
+ return tmin;
112
+ }
113
+ /** Distance along a (unit) ray to a circle, or null if missed. */
114
+ function rayCircle(o, d, c, r) {
115
+ const ox = o.x - c.x;
116
+ const oz = o.z - c.z;
117
+ const b = ox * d.x + oz * d.z;
118
+ const cc = ox * ox + oz * oz - r * r;
119
+ const disc = b * b - cc;
120
+ if (disc < 0) return null;
121
+ const s = Math.sqrt(disc);
122
+ const t = -b - s;
123
+ if (t >= 0) return t;
124
+ return -b + s >= 0 ? 0 : null;
125
+ }
126
+ /** Distance to the first wall along the ray, capped at `range`. */
127
+ function wallDistance(o, d, map, range) {
128
+ let best = range;
129
+ for (const b of map.walls) {
130
+ const t = rayBox(o, d, b);
131
+ if (t !== null && t < best) best = t;
132
+ }
133
+ return best;
134
+ }
135
+ /**
136
+ * Hitscan from `origin` along `yaw`. Returns the nearest target hit before any
137
+ * wall and within `range`, plus how far the shot travelled.
138
+ */
139
+ function castShot(origin, yaw, range, map, targets, radius) {
140
+ const d = forwardOf(yaw);
141
+ const wall = wallDistance(origin, d, map, range);
142
+ let hit = null;
143
+ let dist = wall;
144
+ for (const t of targets) {
145
+ const td = rayCircle(origin, d, t, radius);
146
+ if (td !== null && td < dist) {
147
+ dist = td;
148
+ hit = t.id;
149
+ }
150
+ }
151
+ return {
152
+ hit,
153
+ dist
154
+ };
155
+ }
156
+ //#endregion
157
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/typeof.js
158
+ function _typeof(o) {
159
+ "@babel/helpers - typeof";
160
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
161
+ return typeof o;
162
+ } : function(o) {
163
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
164
+ }, _typeof(o);
165
+ }
166
+ //#endregion
167
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPrimitive.js
168
+ function toPrimitive(t, r) {
169
+ if ("object" != _typeof(t) || !t) return t;
170
+ var e = t[Symbol.toPrimitive];
171
+ if (void 0 !== e) {
172
+ var i = e.call(t, r || "default");
173
+ if ("object" != _typeof(i)) return i;
174
+ throw new TypeError("@@toPrimitive must return a primitive value.");
175
+ }
176
+ return ("string" === r ? String : Number)(t);
177
+ }
178
+ //#endregion
179
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPropertyKey.js
180
+ function toPropertyKey(t) {
181
+ var i = toPrimitive(t, "string");
182
+ return "symbol" == _typeof(i) ? i : i + "";
183
+ }
184
+ //#endregion
185
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/defineProperty.js
186
+ function _defineProperty(e, r, t) {
187
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
188
+ value: t,
189
+ enumerable: !0,
190
+ configurable: !0,
191
+ writable: !0
192
+ }) : e[r] = t, e;
193
+ }
194
+ //#endregion
195
+ //#region client/arena-client.ts
196
+ var MAX_STEPS_PER_UPDATE = 4;
197
+ var MAX_PENDING = 120;
198
+ var SNAPSHOT_BUFFER = 20;
199
+ var SNAP_CORRECTION = 2;
200
+ var SMOOTH_HALF_LIFE = .05;
201
+ var PING_EVERY_MS = 2e3;
202
+ function lerpAngle(a, b, t) {
203
+ let d = (b - a) % (Math.PI * 2);
204
+ if (d > Math.PI) d -= Math.PI * 2;
205
+ if (d < -Math.PI) d += Math.PI * 2;
206
+ return a + d * t;
207
+ }
208
+ var ArenaClient = class {
209
+ constructor(opts) {
210
+ _defineProperty(this, "opts", void 0);
211
+ _defineProperty(this, "cfg", null);
212
+ _defineProperty(this, "you", null);
213
+ _defineProperty(this, "phase", "waiting");
214
+ _defineProperty(this, "timeLeft", 0);
215
+ _defineProperty(this, "rttMs", 0);
216
+ _defineProperty(this, "controls", {
217
+ mx: 0,
218
+ mz: 0,
219
+ yaw: 0,
220
+ pitch: 0,
221
+ fire: false
222
+ });
223
+ _defineProperty(this, "self", {
224
+ x: 0,
225
+ z: 0,
226
+ yaw: 0,
227
+ pitch: 0,
228
+ hp: 0,
229
+ alive: true,
230
+ it: false,
231
+ score: 0
232
+ });
233
+ _defineProperty(this, "ws", null);
234
+ _defineProperty(this, "seq", 0);
235
+ _defineProperty(this, "pending", []);
236
+ _defineProperty(this, "acc", 0);
237
+ _defineProperty(this, "snaps", []);
238
+ _defineProperty(this, "clockOffsetMs", null);
239
+ _defineProperty(this, "smooth", {
240
+ x: 0,
241
+ z: 0
242
+ });
243
+ _defineProperty(this, "pingTimer", null);
244
+ _defineProperty(this, "listeners", {
245
+ snapshot: /* @__PURE__ */ new Set(),
246
+ event: /* @__PURE__ */ new Set(),
247
+ end: /* @__PURE__ */ new Set(),
248
+ error: /* @__PURE__ */ new Set(),
249
+ close: /* @__PURE__ */ new Set()
250
+ });
251
+ this.opts = opts;
252
+ }
253
+ on(type, fn) {
254
+ this.listeners[type].add(fn);
255
+ return () => this.listeners[type].delete(fn);
256
+ }
257
+ connect() {
258
+ return new Promise((resolve, reject) => {
259
+ const url = `${this.opts.wsUrl}?ticket=${encodeURIComponent(this.opts.ticket)}`;
260
+ const ws = new WebSocket(url);
261
+ this.ws = ws;
262
+ let welcomed = false;
263
+ ws.onmessage = (e) => {
264
+ const msg = JSON.parse(String(e.data));
265
+ if (msg.t === "welcome") {
266
+ welcomed = true;
267
+ this.onWelcome(msg);
268
+ resolve(msg);
269
+ } else if (msg.t === "error") {
270
+ this.emit("error", msg);
271
+ if (!welcomed) reject(new Error(msg.message));
272
+ } else this.onMessage(msg);
273
+ };
274
+ ws.onclose = (e) => {
275
+ this.stopPing();
276
+ if (!welcomed) reject(new Error(e.reason || `Connection closed (${e.code})`));
277
+ this.emit("close", {
278
+ code: e.code,
279
+ reason: e.reason
280
+ });
281
+ };
282
+ });
283
+ }
284
+ close() {
285
+ this.stopPing();
286
+ this.ws?.close(1e3, "leaving");
287
+ }
288
+ /** Call once per rendered frame. Sends fixed-rate inputs and runs prediction. */
289
+ update(dtSec) {
290
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN || !this.cfg) return;
291
+ this.self.yaw = this.controls.yaw;
292
+ this.self.pitch = this.controls.pitch;
293
+ this.acc += dtSec;
294
+ let steps = 0;
295
+ while (this.acc >= .03333333333333333 && steps < MAX_STEPS_PER_UPDATE) {
296
+ this.acc -= INPUT_DT;
297
+ steps++;
298
+ this.sendInput();
299
+ }
300
+ if (steps === MAX_STEPS_PER_UPDATE) this.acc = 0;
301
+ const decay = Math.pow(.5, dtSec / SMOOTH_HALF_LIFE);
302
+ this.smooth.x *= decay;
303
+ this.smooth.z *= decay;
304
+ }
305
+ /** Where to draw yourself this frame (prediction + smoothed corrections). */
306
+ get view() {
307
+ return {
308
+ ...this.self,
309
+ x: this.self.x + this.smooth.x,
310
+ z: this.self.z + this.smooth.z
311
+ };
312
+ }
313
+ /** Other players, interpolated at the current render time. */
314
+ others(nowMs = performance.now()) {
315
+ const rt = this.renderTick(nowMs);
316
+ if (!this.snaps.length) return [];
317
+ let a = this.snaps[0];
318
+ let b = this.snaps[0];
319
+ for (let i = 0; i < this.snaps.length; i++) {
320
+ if (this.snaps[i].tick <= rt) a = this.snaps[i];
321
+ if (this.snaps[i].tick >= rt) {
322
+ b = this.snaps[i];
323
+ break;
324
+ }
325
+ b = this.snaps[i];
326
+ }
327
+ const t = b.tick === a.tick ? 0 : Math.min(1, Math.max(0, (rt - a.tick) / (b.tick - a.tick)));
328
+ const out = [];
329
+ for (const [id, pb] of b.players) {
330
+ if (id === this.you) continue;
331
+ const pa = a.players.get(id);
332
+ if (!pa || !pa.a || !pb.a || Math.hypot(pb.x - pa.x, pb.z - pa.z) > 4) {
333
+ out.push(pb);
334
+ continue;
335
+ }
336
+ out.push({
337
+ ...pb,
338
+ x: pa.x + (pb.x - pa.x) * t,
339
+ z: pa.z + (pb.z - pa.z) * t,
340
+ y: lerpAngle(pa.y, pb.y, t),
341
+ p: pa.p + (pb.p - pa.p) * t
342
+ });
343
+ }
344
+ return out;
345
+ }
346
+ /** Latest authoritative snapshot of every player (scores, names, hp). */
347
+ get roster() {
348
+ const last = this.snaps[this.snaps.length - 1];
349
+ return last ? [...last.players.values()] : [];
350
+ }
351
+ onWelcome(msg) {
352
+ this.cfg = msg.cfg;
353
+ this.you = msg.you;
354
+ this.syncClock(msg.tick);
355
+ this.stopPing();
356
+ this.pingTimer = setInterval(() => this.ws?.send(JSON.stringify({
357
+ t: "ping",
358
+ c: performance.now()
359
+ })), PING_EVERY_MS);
360
+ }
361
+ onMessage(msg) {
362
+ if (msg.t === "s") this.onSnapshot(msg);
363
+ else if (msg.t === "pong") this.rttMs = performance.now() - msg.c;
364
+ else if (msg.t === "end") {
365
+ this.phase = "ended";
366
+ this.emit("end", msg);
367
+ }
368
+ }
369
+ onSnapshot(msg) {
370
+ this.syncClock(msg.k);
371
+ this.phase = msg.ph;
372
+ this.timeLeft = msg.tl;
373
+ this.snaps.push({
374
+ tick: msg.k,
375
+ players: new Map(msg.p.map((p) => [p.id, p]))
376
+ });
377
+ if (this.snaps.length > SNAPSHOT_BUFFER) this.snaps.shift();
378
+ const me = msg.p.find((p) => p.id === this.you);
379
+ if (me && this.cfg) {
380
+ const before = {
381
+ x: this.self.x + this.smooth.x,
382
+ z: this.self.z + this.smooth.z
383
+ };
384
+ this.self.x = me.x;
385
+ this.self.z = me.z;
386
+ this.self.hp = me.hp;
387
+ this.self.alive = me.a;
388
+ this.self.it = !!me.it;
389
+ this.self.score = me.s;
390
+ this.pending = this.pending.filter((i) => i.seq > msg.ack);
391
+ for (const inp of this.pending) this.predict(inp);
392
+ const ex = before.x - this.self.x;
393
+ const ez = before.z - this.self.z;
394
+ if (Math.hypot(ex, ez) > SNAP_CORRECTION) this.smooth = {
395
+ x: 0,
396
+ z: 0
397
+ };
398
+ else this.smooth = {
399
+ x: ex,
400
+ z: ez
401
+ };
402
+ }
403
+ this.emit("snapshot", msg);
404
+ for (const e of msg.ev ?? []) this.emit("event", e);
405
+ }
406
+ sendInput() {
407
+ const c = this.controls;
408
+ const inp = {
409
+ t: "i",
410
+ seq: ++this.seq,
411
+ mx: c.mx,
412
+ mz: c.mz,
413
+ yaw: c.yaw,
414
+ pitch: c.pitch,
415
+ fire: c.fire,
416
+ vt: Math.round(this.renderTick() * 100) / 100
417
+ };
418
+ this.predict(inp);
419
+ this.pending.push(inp);
420
+ if (this.pending.length > MAX_PENDING) this.pending.shift();
421
+ this.ws.send(JSON.stringify(inp));
422
+ }
423
+ /** Mirror of the server's applyInput movement rules. */
424
+ predict(inp) {
425
+ const cfg = this.cfg;
426
+ if (!this.self.alive || this.phase === "countdown" || this.phase === "ended") return;
427
+ const speed = cfg.moveSpeed * (this.self.it ? cfg.itSpeedMultiplier : 1);
428
+ stepMove(this.self, inp, speed, cfg.playerRadius, cfg.map, INPUT_DT);
429
+ }
430
+ /** Smoothed estimate of the server tick "now", minus the interpolation delay. */
431
+ renderTick(nowMs = performance.now()) {
432
+ if (this.clockOffsetMs === null) return 0;
433
+ return (nowMs + this.clockOffsetMs) * 20 / 1e3 - (this.opts.interpDelayTicks ?? 2);
434
+ }
435
+ syncClock(tick) {
436
+ const sample = tick * 1e3 / 20 - performance.now();
437
+ if (this.clockOffsetMs === null || Math.abs(sample - this.clockOffsetMs) > 1e3) this.clockOffsetMs = sample;
438
+ else this.clockOffsetMs += (sample - this.clockOffsetMs) * .1;
439
+ }
440
+ stopPing() {
441
+ if (this.pingTimer) clearInterval(this.pingTimer);
442
+ this.pingTimer = null;
443
+ }
444
+ emit(type, arg) {
445
+ for (const fn of this.listeners[type]) fn(arg);
446
+ }
447
+ };
448
+ var DEFAULT_ARENA_CONFIG = {
449
+ mode: "elimination",
450
+ minPlayers: 2,
451
+ maxPlayers: 8,
452
+ durationSec: 180,
453
+ countdownSec: 3,
454
+ moveSpeed: 6,
455
+ playerRadius: .4,
456
+ maxHp: 100,
457
+ damage: 25,
458
+ fireCooldownMs: 300,
459
+ weaponRange: 40,
460
+ respawnSec: 3,
461
+ tagRange: 2,
462
+ tagCooldownSec: 2,
463
+ itSpeedMultiplier: 1.1,
464
+ map: {
465
+ width: 40,
466
+ depth: 40,
467
+ walls: [
468
+ {
469
+ minX: -2,
470
+ minZ: -2,
471
+ maxX: 2,
472
+ maxZ: 2,
473
+ height: 3
474
+ },
475
+ {
476
+ minX: -12,
477
+ minZ: -12,
478
+ maxX: -8,
479
+ maxZ: -10,
480
+ height: 2
481
+ },
482
+ {
483
+ minX: 8,
484
+ minZ: 10,
485
+ maxX: 12,
486
+ maxZ: 12,
487
+ height: 2
488
+ },
489
+ {
490
+ minX: -12,
491
+ minZ: 8,
492
+ maxX: -10,
493
+ maxZ: 14,
494
+ height: 2
495
+ },
496
+ {
497
+ minX: 10,
498
+ minZ: -14,
499
+ maxX: 12,
500
+ maxZ: -8,
501
+ height: 2
502
+ },
503
+ {
504
+ minX: -1,
505
+ minZ: -16,
506
+ maxX: 1,
507
+ maxZ: -9,
508
+ height: 2.5
509
+ },
510
+ {
511
+ minX: -1,
512
+ minZ: 9,
513
+ maxX: 1,
514
+ maxZ: 16,
515
+ height: 2.5
516
+ }
517
+ ],
518
+ spawns: [
519
+ {
520
+ x: -16,
521
+ z: -16,
522
+ yaw: -3 * Math.PI / 4
523
+ },
524
+ {
525
+ x: 16,
526
+ z: 16,
527
+ yaw: Math.PI / 4
528
+ },
529
+ {
530
+ x: -16,
531
+ z: 16,
532
+ yaw: -Math.PI / 4
533
+ },
534
+ {
535
+ x: 16,
536
+ z: -16,
537
+ yaw: 3 * Math.PI / 4
538
+ },
539
+ {
540
+ x: 0,
541
+ z: -18,
542
+ yaw: Math.PI
543
+ },
544
+ {
545
+ x: 0,
546
+ z: 18,
547
+ yaw: 0
548
+ },
549
+ {
550
+ x: -18,
551
+ z: 0,
552
+ yaw: -Math.PI / 2
553
+ },
554
+ {
555
+ x: 18,
556
+ z: 0,
557
+ yaw: Math.PI / 2
558
+ }
559
+ ]
560
+ }
561
+ };
562
+ var MAX_WALLS = 200;
563
+ var MAX_SPAWNS = 32;
564
+ function num(v, fallback, min, max) {
565
+ return typeof v === "number" && Number.isFinite(v) ? Math.min(max, Math.max(min, v)) : fallback;
566
+ }
567
+ function resolveMap(input) {
568
+ if (!input || typeof input !== "object") return DEFAULT_ARENA_CONFIG.map;
569
+ const m = input;
570
+ const width = num(m.width, 40, 10, 400);
571
+ const depth = num(m.depth, 40, 10, 400);
572
+ const walls = Array.isArray(m.walls) ? m.walls.slice(0, MAX_WALLS).flatMap((w) => {
573
+ if (!w || typeof w !== "object") return [];
574
+ if (![
575
+ w.minX,
576
+ w.minZ,
577
+ w.maxX,
578
+ w.maxZ
579
+ ].every((v) => typeof v === "number" && Number.isFinite(v))) return [];
580
+ if (w.maxX <= w.minX || w.maxZ <= w.minZ) return [];
581
+ return [{
582
+ minX: w.minX,
583
+ minZ: w.minZ,
584
+ maxX: w.maxX,
585
+ maxZ: w.maxZ,
586
+ height: num(w.height, 2, .1, 50)
587
+ }];
588
+ }) : [];
589
+ const spawns = Array.isArray(m.spawns) ? m.spawns.slice(0, MAX_SPAWNS).flatMap((s) => {
590
+ if (!s || typeof s !== "object") return [];
591
+ if (![s.x, s.z].every((v) => typeof v === "number" && Number.isFinite(v))) return [];
592
+ return [{
593
+ x: num(s.x, 0, -width / 2, width / 2),
594
+ z: num(s.z, 0, -depth / 2, depth / 2),
595
+ yaw: num(s.yaw, 0, -10, 10)
596
+ }];
597
+ }) : [];
598
+ return {
599
+ width,
600
+ depth,
601
+ walls,
602
+ spawns: spawns.length ? spawns : [{
603
+ x: 0,
604
+ z: 0,
605
+ yaw: 0
606
+ }]
607
+ };
608
+ }
609
+ /** Merge untrusted overrides over the defaults, clamping everything. */
610
+ function resolveArenaConfig(overrides) {
611
+ const o = overrides && typeof overrides === "object" ? overrides : {};
612
+ const d = DEFAULT_ARENA_CONFIG;
613
+ const maxPlayers = Math.round(num(o.maxPlayers, d.maxPlayers, 2, 16));
614
+ return {
615
+ mode: o.mode === "tag" || o.mode === "elimination" ? o.mode : d.mode,
616
+ minPlayers: Math.round(num(o.minPlayers, d.minPlayers, 1, maxPlayers)),
617
+ maxPlayers,
618
+ durationSec: num(o.durationSec, d.durationSec, 15, 1800),
619
+ countdownSec: num(o.countdownSec, d.countdownSec, 0, 10),
620
+ moveSpeed: num(o.moveSpeed, d.moveSpeed, 1, 20),
621
+ playerRadius: num(o.playerRadius, d.playerRadius, .2, 2),
622
+ maxHp: num(o.maxHp, d.maxHp, 1, 1e3),
623
+ damage: num(o.damage, d.damage, 1, 1e3),
624
+ fireCooldownMs: num(o.fireCooldownMs, d.fireCooldownMs, 50, 5e3),
625
+ weaponRange: num(o.weaponRange, d.weaponRange, 1, 200),
626
+ respawnSec: num(o.respawnSec, d.respawnSec, 0, 30),
627
+ tagRange: num(o.tagRange, d.tagRange, .5, 10),
628
+ tagCooldownSec: num(o.tagCooldownSec, d.tagCooldownSec, 0, 10),
629
+ itSpeedMultiplier: num(o.itSpeedMultiplier, d.itSpeedMultiplier, .5, 2),
630
+ map: o.map === void 0 ? d.map : resolveMap(o.map)
631
+ };
632
+ }
633
+ //#endregion
634
+ export { ArenaClient, CloseCode, DEFAULT_ARENA_CONFIG, INPUT_DT, INPUT_HZ, PROTOCOL_VERSION, TICK_HZ, castShot, forwardOf, resolveArenaConfig, stepMove };