@kbve/laser 0.1.0 → 0.1.2

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 (2) hide show
  1. package/laser.es.js +661 -165
  2. package/package.json +2 -2
package/laser.es.js CHANGED
@@ -1,31 +1,32 @@
1
- import { jsxs as m, jsx as b } from "react/jsx-runtime";
2
- import { createContext as D, useContext as P, forwardRef as S, useRef as p, useState as k, useImperativeHandle as E, useEffect as w, useMemo as I } from "react";
3
- import c from "phaser";
4
- import { Canvas as C, useFrame as K } from "@react-three/fiber";
5
- import { addComponent as X, addEntity as Y, createWorld as N, hasComponent as Q, query as tt, removeEntity as et } from "bitecs";
6
- import { RAPIER as it, createRapierPhysics as rt } from "@phaserjs/rapier-connector";
7
- class A {
1
+ import { jsxs as I, jsx as D } from "react/jsx-runtime";
2
+ import { createContext as v, useContext as O, forwardRef as K, useRef as g, useState as j, useImperativeHandle as L, useEffect as R, useMemo as N } from "react";
3
+ import x from "phaser";
4
+ import { Canvas as q, useFrame as F } from "@react-three/fiber";
5
+ import { query as P } from "bitecs";
6
+ export * from "bitecs";
7
+ import { RAPIER as Ht, createRapierPhysics as zt } from "@phaserjs/rapier-connector";
8
+ class S {
8
9
  handlers = /* @__PURE__ */ new Map();
9
10
  on(t, e) {
10
- let s = this.handlers.get(t);
11
- return s || (s = /* @__PURE__ */ new Set(), this.handlers.set(t, s)), s.add(e), () => {
12
- s.delete(e);
11
+ let i = this.handlers.get(t);
12
+ return i || (i = /* @__PURE__ */ new Set(), this.handlers.set(t, i)), i.add(e), () => {
13
+ i.delete(e);
13
14
  };
14
15
  }
15
16
  off(t, e) {
16
17
  this.handlers.get(t)?.delete(e);
17
18
  }
18
19
  emit(t, e) {
19
- this.handlers.get(t)?.forEach((s) => {
20
- s(e);
20
+ this.handlers.get(t)?.forEach((i) => {
21
+ i(e);
21
22
  });
22
23
  }
23
24
  clear() {
24
25
  this.handlers.clear();
25
26
  }
26
27
  }
27
- const f = new A();
28
- class d {
28
+ const E = new S();
29
+ class M {
29
30
  bounds;
30
31
  capacity;
31
32
  points;
@@ -39,18 +40,18 @@ class d {
39
40
  this.bounds = t, this.capacity = e, this.points = [], this.divided = !1, this.cache = /* @__PURE__ */ new Map();
40
41
  }
41
42
  subdivide() {
42
- const { xMin: t, yMin: e, xMax: s, yMax: i } = this.bounds, n = (s - t) / 2, o = (i - e) / 2, a = t, h = e;
43
- this.northeast = new d(
44
- { xMin: a + n, xMax: a + 2 * n, yMin: e, yMax: h + o },
43
+ const { xMin: t, yMin: e, xMax: i, yMax: n } = this.bounds, r = (i - t) / 2, a = (n - e) / 2, o = t, h = e;
44
+ this.northeast = new M(
45
+ { xMin: o + r, xMax: o + 2 * r, yMin: e, yMax: h + a },
45
46
  this.capacity
46
- ), this.northwest = new d(
47
- { xMin: t, xMax: a + n, yMin: e, yMax: h + o },
47
+ ), this.northwest = new M(
48
+ { xMin: t, xMax: o + r, yMin: e, yMax: h + a },
48
49
  this.capacity
49
- ), this.southeast = new d(
50
- { xMin: a + n, xMax: a + 2 * n, yMin: h + o, yMax: h + 2 * o },
50
+ ), this.southeast = new M(
51
+ { xMin: o + r, xMax: o + 2 * r, yMin: h + a, yMax: h + 2 * a },
51
52
  this.capacity
52
- ), this.southwest = new d(
53
- { xMin: t, xMax: a + n, yMin: h + o, yMax: h + 2 * o },
53
+ ), this.southwest = new M(
54
+ { xMin: t, xMax: o + r, yMin: h + a, yMax: h + 2 * a },
54
55
  this.capacity
55
56
  ), this.divided = !0;
56
57
  }
@@ -58,20 +59,20 @@ class d {
58
59
  return this.contains(t.bounds) ? this.points.length < this.capacity ? (this.points.push(t), !0) : (this.divided || this.subdivide(), !!(this.northeast?.insert(t) || this.northwest?.insert(t) || this.southeast?.insert(t) || this.southwest?.insert(t))) : !1;
59
60
  }
60
61
  contains(t) {
61
- const { xMin: e, yMin: s, xMax: i, yMax: n } = this.bounds;
62
- return t.xMin >= e && t.xMax <= i && t.yMin >= s && t.yMax <= n;
62
+ const { xMin: e, yMin: i, xMax: n, yMax: r } = this.bounds;
63
+ return t.xMin >= e && t.xMax <= n && t.yMin >= i && t.yMax <= r;
63
64
  }
64
65
  queryRange(t, e = []) {
65
66
  if (!this.intersects(t))
66
67
  return e;
67
- for (const s of this.points)
68
- this.isWithinBounds(s.bounds, t) && e.push(s);
68
+ for (const i of this.points)
69
+ this.isWithinBounds(i.bounds, t) && e.push(i);
69
70
  return this.divided && (this.northwest?.queryRange(t, e), this.northeast?.queryRange(t, e), this.southwest?.queryRange(t, e), this.southeast?.queryRange(t, e)), e;
70
71
  }
71
72
  query(t, e = []) {
72
- const s = `${t.x},${t.y}`, i = this.cache.get(s);
73
- if (i)
74
- return i;
73
+ const i = `${t.x},${t.y}`, n = this.cache.get(i);
74
+ if (n)
75
+ return n;
75
76
  if (!this.intersects({
76
77
  xMin: t.x,
77
78
  xMax: t.x,
@@ -79,13 +80,13 @@ class d {
79
80
  yMax: t.y
80
81
  }))
81
82
  return e;
82
- for (const n of this.points)
83
- this.isWithinRange(t, n.bounds) && e.push(n);
84
- return this.divided && (this.northwest?.query(t, e), this.northeast?.query(t, e), this.southwest?.query(t, e), this.southeast?.query(t, e)), this.cache.set(s, e), e;
83
+ for (const r of this.points)
84
+ this.isWithinRange(t, r.bounds) && e.push(r);
85
+ return this.divided && (this.northwest?.query(t, e), this.northeast?.query(t, e), this.southwest?.query(t, e), this.southeast?.query(t, e)), this.cache.set(i, e), e;
85
86
  }
86
87
  intersects(t) {
87
- const { xMin: e, yMin: s, xMax: i, yMax: n } = this.bounds;
88
- return !(t.xMin > i || t.xMax < e || t.yMin > n || t.yMax < s);
88
+ const { xMin: e, yMin: i, xMax: n, yMax: r } = this.bounds;
89
+ return !(t.xMin > n || t.xMax < e || t.yMin > r || t.yMax < i);
89
90
  }
90
91
  isWithinBounds(t, e) {
91
92
  return t.xMax >= e.xMin && t.xMin <= e.xMax && t.yMax >= e.yMin && t.yMin <= e.yMax;
@@ -94,74 +95,96 @@ class d {
94
95
  return t.x >= e.xMin && t.x <= e.xMax && t.y >= e.yMin && t.y <= e.yMax;
95
96
  }
96
97
  }
97
- const g = D(null);
98
- function R() {
99
- const r = P(g);
100
- if (!r)
98
+ const T = v(null);
99
+ function U() {
100
+ const s = O(T);
101
+ if (!s)
101
102
  throw new Error(
102
103
  "usePhaserGame must be used within a <PhaserGame> component"
103
104
  );
104
- return r;
105
+ return s;
105
106
  }
106
- const z = S(
107
- function({ config: t, onReady: e, onDestroy: s, className: i, style: n, children: o }, a) {
108
- const h = p(null), l = p(null), [y, x] = k("idle");
109
- E(
110
- a,
107
+ const lt = K(
108
+ function({ config: t, onReady: e, onDestroy: i, className: n, style: r, children: a }, o) {
109
+ const h = g(null), c = g(null), p = g(null), [l, u] = j("idle");
110
+ L(
111
+ o,
111
112
  () => ({
112
- game: l.current,
113
- status: y
113
+ game: c.current,
114
+ status: l
114
115
  }),
115
- [y]
116
- ), w(() => {
116
+ [l]
117
+ ), R(() => {
117
118
  if (!h.current) return;
118
- x("booting");
119
- const u = new c.Game({
120
- type: c.AUTO,
119
+ const m = h.current;
120
+ if (p.current !== null && (window.clearTimeout(p.current), p.current = null), c.current) {
121
+ const f = c.current.canvas;
122
+ return f && f.parentElement !== m && m.appendChild(f), u(c.current.isBooted ? "running" : "booting"), w;
123
+ }
124
+ u("booting");
125
+ const k = {
126
+ type: x.AUTO,
121
127
  width: t.width ?? 800,
122
128
  height: t.height ?? 600,
123
- parent: h.current,
129
+ parent: m,
124
130
  scene: t.scenes,
125
- physics: t.physics,
126
- plugins: t.plugins,
127
- scale: t.scale,
128
131
  backgroundColor: t.backgroundColor,
129
- transparent: t.transparent
130
- });
131
- return l.current = u, u.events.once("ready", () => {
132
- x("running"), f.emit("game:ready", { game: u }), e?.(u);
133
- }), () => {
134
- x("destroyed"), f.emit("game:destroy", void 0), s?.(), u.destroy(!0), l.current = null;
135
- };
136
- }, [t, e, s]);
137
- const v = I(
138
- () => ({ game: l.current, status: y }),
139
- [y]
132
+ transparent: t.transparent,
133
+ ...t.physics && { physics: t.physics },
134
+ ...t.plugins && { plugins: t.plugins },
135
+ ...t.scale && { scale: t.scale },
136
+ ...t.input && { input: t.input },
137
+ ...t.render || t.pixelArt ? {
138
+ render: t.pixelArt ? {
139
+ pixelArt: !0,
140
+ antialias: !1,
141
+ ...t.render
142
+ } : t.render
143
+ } : {},
144
+ ...t.dom && { dom: t.dom },
145
+ ...t.audio && { audio: t.audio },
146
+ ...t.callbacks && { callbacks: t.callbacks },
147
+ ...t.fps && { fps: t.fps }
148
+ }, y = new x.Game(k);
149
+ return c.current = y, y.events.once("ready", () => {
150
+ c.current === y && (u("running"), E.emit("game:ready", { game: y }), e?.(y));
151
+ }), w;
152
+ function w() {
153
+ p.current = window.setTimeout(() => {
154
+ p.current = null;
155
+ const f = c.current;
156
+ f && (u("destroyed"), E.emit("game:destroy", void 0), i?.(), f.destroy(!0), c.current = null);
157
+ }, 0);
158
+ }
159
+ }, [t, e, i]);
160
+ const d = N(
161
+ () => ({ game: c.current, status: l }),
162
+ [l]
140
163
  );
141
- return /* @__PURE__ */ m(g.Provider, { value: v, children: [
142
- /* @__PURE__ */ b("div", { ref: h, className: i, style: n }),
143
- o
164
+ return /* @__PURE__ */ I(T.Provider, { value: d, children: [
165
+ /* @__PURE__ */ D("div", { ref: h, className: n, style: r }),
166
+ a
144
167
  ] });
145
168
  }
146
169
  );
147
- function T(r, t, e) {
148
- const { game: s } = R(), i = p(t);
149
- i.current = t, w(() => {
150
- if (!s) return;
151
- const n = (...o) => i.current(...o);
170
+ function dt(s, t, e) {
171
+ const { game: i } = U(), n = g(t);
172
+ n.current = t, R(() => {
173
+ if (!i) return;
174
+ const r = (...a) => n.current(...a);
152
175
  if (e) {
153
- const o = s.scene.getScene(e);
154
- if (o)
155
- return o.events.on(r, n), () => {
156
- o.events.off(r, n);
176
+ const a = i.scene.getScene(e);
177
+ if (a)
178
+ return a.events.on(s, r), () => {
179
+ a.events.off(s, r);
157
180
  };
158
181
  } else
159
- return s.events.on(r, n), () => {
160
- s.events.off(r, n);
182
+ return i.events.on(s, r), () => {
183
+ i.events.off(s, r);
161
184
  };
162
- }, [s, r, e]);
185
+ }, [i, s, e]);
163
186
  }
164
- class j {
187
+ class W {
165
188
  scene;
166
189
  base;
167
190
  thumb;
@@ -173,16 +196,16 @@ class j {
173
196
  activePointer = null;
174
197
  constructor(t, e) {
175
198
  this.scene = t, this.radius = e?.radius ?? 60, this.deadZone = e?.deadZone ?? 0.25, this.fixed = e?.fixed ?? !0;
176
- const s = e?.x ?? 120, i = e?.y ?? t.scale.height - 120;
199
+ const i = e?.x ?? 120, n = e?.y ?? t.scale.height - 120;
177
200
  this.base = t.add.circle(
178
- s,
179
201
  i,
202
+ n,
180
203
  this.radius,
181
204
  e?.baseColor ?? 8947848,
182
205
  e?.baseAlpha ?? 0.35
183
206
  ).setDepth(100).setScrollFactor(0), this.thumb = t.add.circle(
184
- s,
185
207
  i,
208
+ n,
186
209
  this.radius * 0.4,
187
210
  e?.thumbColor ?? 16777215,
188
211
  e?.thumbAlpha ?? 0.5
@@ -191,8 +214,8 @@ class j {
191
214
  setupInput() {
192
215
  this.scene.input.on("pointerdown", (t) => {
193
216
  if (this.activePointer) return;
194
- const e = t.x - this.base.x, s = t.y - this.base.y, i = Math.sqrt(e * e + s * s);
195
- this.fixed && i > this.radius * 2 || (this.fixed || (this.base.setPosition(t.x, t.y), this.thumb.setPosition(t.x, t.y)), this.activePointer = t, this._isActive = !0);
217
+ const e = t.x - this.base.x, i = t.y - this.base.y, n = Math.sqrt(e * e + i * i);
218
+ this.fixed && n > this.radius * 2 || (this.fixed || (this.base.setPosition(t.x, t.y), this.thumb.setPosition(t.x, t.y)), this.activePointer = t, this._isActive = !0);
196
219
  }), this.scene.input.on("pointermove", (t) => {
197
220
  t === this.activePointer && this.updateThumb(t.x, t.y);
198
221
  }), this.scene.input.on("pointerup", (t) => {
@@ -200,15 +223,15 @@ class j {
200
223
  });
201
224
  }
202
225
  updateThumb(t, e) {
203
- const s = t - this.base.x, i = e - this.base.y, n = Math.sqrt(s * s + i * i), o = Math.min(n, this.radius), a = Math.atan2(i, s);
226
+ const i = t - this.base.x, n = e - this.base.y, r = Math.sqrt(i * i + n * n), a = Math.min(r, this.radius), o = Math.atan2(n, i);
204
227
  if (this.thumb.setPosition(
205
- this.base.x + Math.cos(a) * o,
206
- this.base.y + Math.sin(a) * o
207
- ), o / this.radius < this.deadZone) {
228
+ this.base.x + Math.cos(o) * a,
229
+ this.base.y + Math.sin(o) * a
230
+ ), a / this.radius < this.deadZone) {
208
231
  this._direction = null;
209
232
  return;
210
233
  }
211
- this._direction = this.angleToDirection(a);
234
+ this._direction = this.angleToDirection(o);
212
235
  }
213
236
  angleToDirection(t) {
214
237
  let e = t * 180 / Math.PI;
@@ -230,7 +253,7 @@ class j {
230
253
  this.base.destroy(), this.thumb.destroy();
231
254
  }
232
255
  }
233
- class V {
256
+ class pt {
234
257
  scene;
235
258
  gridEngine;
236
259
  quadtree;
@@ -240,29 +263,29 @@ class V {
240
263
  tileSize;
241
264
  playerId;
242
265
  joystick = null;
243
- constructor(t, e, s, i) {
244
- if (this.scene = t, this.gridEngine = e, this.quadtree = s, this.tileSize = i?.tileSize ?? 48, this.playerId = i?.playerId ?? "player", this.cursor = this.scene.input.keyboard?.createCursorKeys(), this.initializeWASDKeys(), this.tooltip = this.scene.add.text(0, 0, "Press [F]", {
266
+ constructor(t, e, i, n) {
267
+ if (this.scene = t, this.gridEngine = e, this.quadtree = i, this.tileSize = n?.tileSize ?? 48, this.playerId = n?.playerId ?? "player", this.cursor = this.scene.input.keyboard?.createCursorKeys(), this.initializeWASDKeys(), this.tooltip = this.scene.add.text(0, 0, "Press [F]", {
245
268
  font: "16px Arial",
246
269
  backgroundColor: "#000000"
247
- }).setDepth(4).setPadding(3, 2, 2, 3).setVisible(!1), i?.joystick) {
248
- const n = typeof i.joystick == "object" ? i.joystick : void 0;
249
- this.joystick = new j(t, n);
270
+ }).setDepth(4).setPadding(3, 2, 2, 3).setVisible(!1), n?.joystick) {
271
+ const r = typeof n.joystick == "object" ? n.joystick : void 0;
272
+ this.joystick = new W(t, r);
250
273
  }
251
274
  }
252
275
  initializeWASDKeys() {
253
276
  const t = this.scene.input.keyboard;
254
277
  t && (this.wasdKeys = {
255
- W: t.addKey(c.Input.Keyboard.KeyCodes.W),
256
- A: t.addKey(c.Input.Keyboard.KeyCodes.A),
257
- S: t.addKey(c.Input.Keyboard.KeyCodes.S),
258
- D: t.addKey(c.Input.Keyboard.KeyCodes.D)
278
+ W: t.addKey(x.Input.Keyboard.KeyCodes.W),
279
+ A: t.addKey(x.Input.Keyboard.KeyCodes.A),
280
+ S: t.addKey(x.Input.Keyboard.KeyCodes.S),
281
+ D: t.addKey(x.Input.Keyboard.KeyCodes.D)
259
282
  });
260
283
  }
261
284
  checkForNearbyObjects() {
262
- const t = this.gridEngine.getPosition(this.playerId), e = t.x * this.tileSize, s = t.y * this.tileSize, i = this.quadtree.query(t);
263
- i.length > 0 ? (this.tooltip.setPosition(e, s - 60).setVisible(!0), f.emit("player:nearby", {
285
+ const t = this.gridEngine.getPosition(this.playerId), e = t.x * this.tileSize, i = t.y * this.tileSize, n = this.quadtree.query(t);
286
+ n.length > 0 ? (this.tooltip.setPosition(e, i - 60).setVisible(!0), E.emit("player:nearby", {
264
287
  position: t,
265
- ranges: i
288
+ ranges: n
266
289
  })) : this.tooltip.setVisible(!1);
267
290
  }
268
291
  getPlayerPosition() {
@@ -270,16 +293,16 @@ class V {
270
293
  }
271
294
  handleMovement() {
272
295
  if (this.scene.input.keyboard?.addKey("F").isDown) {
273
- const s = this.gridEngine.getPosition(
296
+ const i = this.gridEngine.getPosition(
274
297
  this.playerId
275
- ), i = this.quadtree.query(s);
276
- if (i.length > 0) {
277
- f.emit("player:interact", {
278
- position: s,
279
- ranges: i
298
+ ), n = this.quadtree.query(i);
299
+ if (n.length > 0) {
300
+ E.emit("player:interact", {
301
+ position: i,
302
+ ranges: n
280
303
  });
281
- for (const n of i)
282
- n.action();
304
+ for (const r of n)
305
+ r.action();
283
306
  }
284
307
  }
285
308
  if (this.joystick?.isActive && this.joystick.direction) {
@@ -294,30 +317,99 @@ class V {
294
317
  (t.left.isDown || e.A.isDown) && (t.up.isDown || e.W.isDown) ? this.gridEngine.move(this.playerId, "up-left") : (t.left.isDown || e.A.isDown) && (t.down.isDown || e.S.isDown) ? this.gridEngine.move(this.playerId, "down-left") : (t.right.isDown || e.D.isDown) && (t.up.isDown || e.W.isDown) ? this.gridEngine.move(this.playerId, "up-right") : (t.right.isDown || e.D.isDown) && (t.down.isDown || e.S.isDown) ? this.gridEngine.move(this.playerId, "down-right") : t.left.isDown || e.A.isDown ? this.gridEngine.move(this.playerId, "left") : t.right.isDown || e.D.isDown ? this.gridEngine.move(this.playerId, "right") : t.up.isDown || e.W.isDown ? this.gridEngine.move(this.playerId, "up") : (t.down.isDown || e.S.isDown) && this.gridEngine.move(this.playerId, "down"), this.checkForNearbyObjects();
295
318
  }
296
319
  }
297
- function G(r) {
298
- return +r[r.length - 1];
320
+ function mt(s, t, e = 16739179) {
321
+ t.setTint(16777215).setTintMode(x.TintModes.FILL), s.time.delayedCall(60, () => t.setTint(e)), s.time.delayedCall(180, () => {
322
+ t.clearTint(), t.setTintMode(x.TintModes.MULTIPLY);
323
+ });
324
+ }
325
+ function yt(s, t, e, i, n, r) {
326
+ const a = s.add.text(t, e, i, {
327
+ fontFamily: "monospace",
328
+ fontSize: "14px",
329
+ color: n,
330
+ stroke: "#000000",
331
+ strokeThickness: 3
332
+ }).setOrigin(0.5, 1).setDepth(r);
333
+ return s.tweens.add({
334
+ targets: a,
335
+ y: e - 28,
336
+ alpha: 0,
337
+ duration: 900,
338
+ ease: "Cubic.easeOut",
339
+ onComplete: () => a.destroy()
340
+ }), a;
341
+ }
342
+ function ft(s, t, e, i, n, r = 26) {
343
+ const a = Math.max(0, Math.min(1, i / n));
344
+ s.clear(), s.fillStyle(0, 0.6), s.fillRect(t - r / 2, e, r, 4), s.fillStyle(a > 0.5 ? 4906624 : a > 0.25 ? 16498468 : 16281969, 1), s.fillRect(t - r / 2 + 0.5, e + 0.5, (r - 1) * a, 3);
345
+ }
346
+ function xt(s, { min: t = 0.6, max: e = 2.2, step: i = 0.2 } = {}) {
347
+ const n = (r) => {
348
+ const a = s.cameras.main;
349
+ a.setZoom(x.Math.Clamp(a.zoom + r, t, e));
350
+ };
351
+ s.input.keyboard?.on("keydown-PLUS", () => n(i)), s.input.keyboard?.on("keydown-MINUS", () => n(-i)), s.input.on(
352
+ "wheel",
353
+ (r, a, o, h) => n(h > 0 ? -i * 0.75 : i * 0.75)
354
+ );
355
+ }
356
+ function bt(s, t, e, i = 64) {
357
+ if (s.x === t.x && s.y === t.y || e(t.x, t.y))
358
+ return [];
359
+ const n = (d, m) => `${d},${m}`, r = /* @__PURE__ */ new Map();
360
+ r.set(n(s.x, s.y), null);
361
+ const a = [s], o = [
362
+ [0, -1],
363
+ [0, 1],
364
+ [-1, 0],
365
+ [1, 0]
366
+ ], h = (i * 2 + 1) ** 2;
367
+ let c = 0, p = !1;
368
+ for (; a.length; ) {
369
+ if (++c > h) return [];
370
+ const d = a.shift();
371
+ if (d.x === t.x && d.y === t.y) {
372
+ p = !0;
373
+ break;
374
+ }
375
+ for (const [m, k] of o) {
376
+ const y = d.x + m, w = d.y + k, f = n(y, w);
377
+ r.has(f) || e(y, w) || (r.set(f, n(d.x, d.y)), a.push({ x: y, y: w }));
378
+ }
379
+ }
380
+ if (!p) return [];
381
+ const l = [];
382
+ let u = n(t.x, t.y);
383
+ for (; u && u !== n(s.x, s.y); ) {
384
+ const [d, m] = u.split(",").map(Number);
385
+ if (l.push({ x: d, y: m }), u = r.get(u) ?? null, l.length > i) return [];
386
+ }
387
+ return l.reverse(), l;
388
+ }
389
+ function wt(s) {
390
+ return +s[s.length - 1];
299
391
  }
300
- function O(r) {
301
- return r.startsWith("monster_bird_") && !r.startsWith("monster_bird_shadow");
392
+ function Mt(s) {
393
+ return s.startsWith("monster_bird_") && !s.startsWith("monster_bird_shadow");
302
394
  }
303
- function M(r, t, e, s, i) {
304
- const n = [];
305
- for (let o = 0; o < 10; o++) {
306
- const a = r.add.sprite(0, 0, "monster_bird");
307
- a.setCrop(t, e, s, i), a.scale = 3, n.push(a);
395
+ function C(s, t, e, i, n) {
396
+ const r = [];
397
+ for (let a = 0; a < 10; a++) {
398
+ const o = s.add.sprite(0, 0, "monster_bird");
399
+ o.setCrop(t, e, i, n), o.scale = 3, r.push(o);
308
400
  }
309
- return n;
401
+ return r;
310
402
  }
311
- function Z(r) {
312
- return M(r, 0, 0, 61, 47);
403
+ function gt(s) {
404
+ return C(s, 0, 0, 61, 47);
313
405
  }
314
- function L(r) {
315
- return M(r, 22, 47, 16, 10);
406
+ function Et(s) {
407
+ return C(s, 22, 47, 16, 10);
316
408
  }
317
- function B(r) {
318
- r.anims.create({
409
+ function kt(s) {
410
+ s.anims.create({
319
411
  key: "bird",
320
- frames: r.anims.generateFrameNumbers("monster_bird", {
412
+ frames: s.anims.generateFrameNumbers("monster_bird", {
321
413
  start: 0,
322
414
  end: 2
323
415
  }),
@@ -326,51 +418,455 @@ function B(r) {
326
418
  yoyo: !0
327
419
  });
328
420
  }
329
- const $ = ({
330
- children: r,
421
+ const St = ({
422
+ children: s,
331
423
  className: t,
332
424
  ...e
333
- }) => /* @__PURE__ */ m(
334
- C,
425
+ }) => /* @__PURE__ */ I(
426
+ q,
335
427
  {
336
428
  camera: { position: [0, 0, 5] },
337
429
  ...e,
338
430
  className: t,
339
431
  children: [
340
- /* @__PURE__ */ b("ambientLight", { intensity: 1.5 }),
341
- r
432
+ /* @__PURE__ */ D("ambientLight", { intensity: 1.5 }),
433
+ s
342
434
  ]
343
435
  }
344
436
  );
345
- function H(r) {
346
- const t = p(r);
347
- t.current = r, K((e, s) => {
348
- t.current(s, e.clock.elapsedTime);
437
+ function At(s) {
438
+ const t = g(s);
439
+ t.current = s, F((e, i) => {
440
+ t.current(i, e.clock.elapsedTime);
349
441
  });
350
442
  }
443
+ function* It(s, t, e, i, n, r) {
444
+ const a = r * r;
445
+ for (const o of P(s, t)) {
446
+ const h = e.x[o] - i, c = e.y[o] - n;
447
+ h * h + c * c <= a && (yield o);
448
+ }
449
+ }
450
+ function Dt(s, t, e, i, n, r) {
451
+ const a = r * r;
452
+ let o = -1, h = a;
453
+ for (const c of P(s, t)) {
454
+ const p = e.x[c] - i, l = e.y[c] - n, u = p * p + l * l;
455
+ u <= h && (h = u, o = c);
456
+ }
457
+ return o >= 0 ? o : null;
458
+ }
459
+ class Rt {
460
+ map = /* @__PURE__ */ new Map();
461
+ set(t, e) {
462
+ this.map.set(t, e);
463
+ }
464
+ get(t) {
465
+ return this.map.get(t);
466
+ }
467
+ delete(t) {
468
+ const e = this.map.get(t);
469
+ return this.map.delete(t), e;
470
+ }
471
+ has(t) {
472
+ return this.map.has(t);
473
+ }
474
+ values() {
475
+ return this.map.values();
476
+ }
477
+ entries() {
478
+ return this.map.entries();
479
+ }
480
+ clear() {
481
+ this.map.clear();
482
+ }
483
+ get size() {
484
+ return this.map.size;
485
+ }
486
+ }
487
+ const H = 1e3, z = 15e3;
488
+ function B(s, t, e) {
489
+ const i = t.trim();
490
+ return e ? s === 1e3 ? "disconnected" : i || `server dropped connection (code ${s})` : s === 1006 ? "cannot reach server — down or rejected" : i || `connection refused (code ${s})`;
491
+ }
492
+ class _ {
493
+ ws = null;
494
+ closed = !1;
495
+ attempts = 0;
496
+ everOpened = !1;
497
+ timer = 0;
498
+ state = { status: "connecting", attempts: 0 };
499
+ opts;
500
+ handlers;
501
+ constructor(t, e) {
502
+ this.opts = {
503
+ maxAttempts: 0,
504
+ baseDelayMs: H,
505
+ maxDelayMs: z,
506
+ closeReason: B,
507
+ ...t
508
+ }, this.handlers = e;
509
+ }
510
+ getState() {
511
+ return this.state;
512
+ }
513
+ isOpen() {
514
+ return this.ws?.readyState === WebSocket.OPEN;
515
+ }
516
+ send(t) {
517
+ this.isOpen() && this.ws.send(t);
518
+ }
519
+ connect() {
520
+ if (this.ws || this.closed) return;
521
+ this.everOpened = !1, this.setState({
522
+ status: this.attempts === 0 ? "connecting" : "reconnecting",
523
+ attempts: this.attempts,
524
+ reason: this.state.reason
525
+ });
526
+ const t = typeof this.opts.url == "function" ? this.opts.url() : this.opts.url, e = new WebSocket(t);
527
+ this.ws = e, e.addEventListener("open", () => {
528
+ this.attempts = 0, this.everOpened = !0, this.setState({ status: "connected", attempts: 0 }), this.handlers.onOpen?.(e);
529
+ }), e.addEventListener(
530
+ "message",
531
+ (i) => this.handlers.onMessage?.(i)
532
+ ), e.addEventListener("close", (i) => {
533
+ this.ws = null;
534
+ const n = this.opts.closeReason(
535
+ i.code,
536
+ i.reason,
537
+ this.everOpened
538
+ );
539
+ if (this.closed) {
540
+ this.setState({ status: "closed", attempts: this.attempts });
541
+ return;
542
+ }
543
+ if (this.opts.shouldReconnect && !this.opts.shouldReconnect()) {
544
+ this.setState({
545
+ status: "closed",
546
+ attempts: this.attempts,
547
+ reason: n
548
+ });
549
+ return;
550
+ }
551
+ if (this.attempts += 1, this.opts.maxAttempts > 0 && this.attempts > this.opts.maxAttempts) {
552
+ this.setState({
553
+ status: "closed",
554
+ attempts: this.attempts,
555
+ reason: n
556
+ });
557
+ return;
558
+ }
559
+ const r = Math.min(
560
+ this.opts.baseDelayMs * 2 ** (this.attempts - 1),
561
+ this.opts.maxDelayMs
562
+ );
563
+ this.setState({
564
+ status: "reconnecting",
565
+ attempts: this.attempts,
566
+ reason: n,
567
+ nextRetryMs: r
568
+ }), this.timer = window.setTimeout(() => this.connect(), r);
569
+ });
570
+ }
571
+ close() {
572
+ this.closed = !0, window.clearTimeout(this.timer), this.ws?.close(), this.ws = null, this.setState({ status: "closed", attempts: this.attempts });
573
+ }
574
+ setState(t) {
575
+ this.state = t, this.handlers.onState?.(t);
576
+ }
577
+ }
578
+ const J = 9, Pt = 1, Tt = 2, V = 1, $ = 2, G = 3, Z = 5, Y = 6, X = 7, Ct = 8, _t = 9, Q = 10, tt = 11, vt = 0, Ot = 1, Kt = 2, et = ["spades", "hearts", "diamonds", "clubs"], st = [
579
+ "A",
580
+ "2",
581
+ "3",
582
+ "4",
583
+ "5",
584
+ "6",
585
+ "7",
586
+ "8",
587
+ "9",
588
+ "10",
589
+ "J",
590
+ "Q",
591
+ "K"
592
+ ], it = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10];
593
+ function jt(s) {
594
+ const t = s & 15, e = s >> 4 & 3;
595
+ return {
596
+ suit: et[e],
597
+ rank: st[t],
598
+ points: it[t],
599
+ red: e === 1 || e === 2
600
+ };
601
+ }
602
+ const Lt = 65535;
603
+ function b(s) {
604
+ try {
605
+ return JSON.parse(
606
+ new TextDecoder().decode(Uint8Array.from(s))
607
+ );
608
+ } catch {
609
+ return null;
610
+ }
611
+ }
612
+ function nt(s, t) {
613
+ return {
614
+ JoinMatch: {
615
+ protocol: J,
616
+ jwt: s,
617
+ kbve_username: t
618
+ }
619
+ };
620
+ }
621
+ function rt(s, t) {
622
+ return { Frame: { client_tick: s, inputs: t } };
623
+ }
624
+ class Nt {
625
+ clientTick = 0;
626
+ terminal = !1;
627
+ bus = new S();
628
+ opts;
629
+ socket;
630
+ constructor(t) {
631
+ this.opts = t, this.socket = new _(
632
+ {
633
+ url: t.url,
634
+ maxAttempts: t.maxReconnects ?? 3,
635
+ baseDelayMs: 1500,
636
+ shouldReconnect: () => !this.terminal
637
+ },
638
+ {
639
+ onOpen: () => {
640
+ this.send(nt(this.opts.jwt, this.opts.kbveUsername)), this.bus.emit("open", void 0);
641
+ },
642
+ onMessage: (e) => this.handleMessage(e),
643
+ onState: (e) => {
644
+ this.bus.emit("state", e), e.status === "closed" && this.bus.emit("close", void 0);
645
+ }
646
+ }
647
+ );
648
+ }
649
+ on(t, e) {
650
+ return this.bus.on(t, e);
651
+ }
652
+ getState() {
653
+ return this.socket.getState();
654
+ }
655
+ connect() {
656
+ this.socket.connect();
657
+ }
658
+ /** Stop reconnecting — the server turned us away for good. */
659
+ markTerminal() {
660
+ this.terminal = !0;
661
+ }
662
+ handleMessage(t) {
663
+ let e;
664
+ try {
665
+ e = JSON.parse(
666
+ typeof t.data == "string" ? t.data : String(t.data)
667
+ );
668
+ } catch {
669
+ return;
670
+ }
671
+ "Welcome" in e ? this.bus.emit("welcome", e.Welcome) : "Snapshot" in e ? this.bus.emit("snapshot", e.Snapshot) : "Ephemeral" in e ? this.handleEphemeral(e.Ephemeral) : "Reject" in e && (this.terminal = !0, this.bus.emit("reject", e.Reject.reason));
672
+ }
673
+ handleEphemeral(t) {
674
+ if (this.bus.emit("ephemeral", t), t.kind === V) {
675
+ const e = b(t.payload);
676
+ e && this.bus.emit("inventory", e);
677
+ } else if (t.kind === $) {
678
+ const e = b(t.payload);
679
+ e && this.bus.emit("combat", e);
680
+ } else if (t.kind === G) {
681
+ const e = b(t.payload);
682
+ e && this.bus.emit("pickup", e);
683
+ } else if (t.kind === Z) {
684
+ const e = b(t.payload);
685
+ e && this.bus.emit("itemUsed", e);
686
+ } else if (t.kind === Y) {
687
+ const e = b(t.payload);
688
+ e && this.bus.emit("equipped", e);
689
+ } else if (t.kind === X) {
690
+ const e = b(t.payload);
691
+ e && this.bus.emit("stats", e);
692
+ } else if (t.kind === Q) {
693
+ const e = b(t.payload);
694
+ e && this.bus.emit("shop", e);
695
+ } else if (t.kind === tt) {
696
+ const e = b(
697
+ t.payload
698
+ );
699
+ e && this.bus.emit("blackjackState", e);
700
+ }
701
+ }
702
+ send(t) {
703
+ this.socket.send(JSON.stringify(t));
704
+ }
705
+ sendInputs(t) {
706
+ !this.socket.isOpen() || t.length === 0 || (this.clientTick += 1, this.send(rt(this.clientTick, t)));
707
+ }
708
+ step(t) {
709
+ this.sendInputs([{ Step: { dir: t } }]);
710
+ }
711
+ moveTo(t) {
712
+ this.sendInputs([{ MoveTo: { tile: t } }]);
713
+ }
714
+ action(t, e) {
715
+ this.sendInputs([{ Action: { id: t, target: e } }]);
716
+ }
717
+ heartbeat() {
718
+ this.sendInputs([{ Heartbeat: { client_tick: this.clientTick } }]);
719
+ }
720
+ useItem(t) {
721
+ this.sendInputs([{ UseItem: { item_ref: t } }]);
722
+ }
723
+ equipItem(t) {
724
+ this.sendInputs([{ EquipItem: { item_ref: t } }]);
725
+ }
726
+ buyItem(t, e, i) {
727
+ this.sendInputs([{ BuyItem: { npc: t, item_ref: e, qty: i } }]);
728
+ }
729
+ sellItem(t, e, i) {
730
+ this.sendInputs([{ SellItem: { npc: t, item_ref: e, qty: i } }]);
731
+ }
732
+ joinTable(t) {
733
+ this.sendInputs([{ JoinTable: { table_ref: t } }]);
734
+ }
735
+ leaveTable() {
736
+ this.sendInputs(["LeaveTable"]);
737
+ }
738
+ placeBet(t) {
739
+ this.sendInputs([{ PlaceBet: { amount: t } }]);
740
+ }
741
+ bjAction(t) {
742
+ this.sendInputs([{ BjAction: { kind: t } }]);
743
+ }
744
+ face(t) {
745
+ this.sendInputs([{ Face: { facing: t } }]);
746
+ }
747
+ close() {
748
+ this.sendInputs(["Leave"]), this.socket.close();
749
+ }
750
+ }
751
+ const A = "chat";
752
+ class qt {
753
+ bus = new S();
754
+ opts;
755
+ socket;
756
+ constructor(t) {
757
+ this.opts = t, this.socket = new _(
758
+ {
759
+ url: () => {
760
+ const e = this.opts.url.includes("?") ? "&" : "?";
761
+ return `${this.opts.url}${e}game=${encodeURIComponent(
762
+ this.opts.game
763
+ )}&token=${encodeURIComponent(this.opts.jwt)}`;
764
+ },
765
+ shouldReconnect: () => !!this.opts.jwt
766
+ },
767
+ {
768
+ onOpen: () => this.bus.emit("open", void 0),
769
+ onMessage: (e) => this.handleMessage(e),
770
+ onState: (e) => {
771
+ this.bus.emit("status", e), e.status === "closed" && this.bus.emit("close", void 0);
772
+ }
773
+ }
774
+ );
775
+ }
776
+ on(t, e) {
777
+ return this.bus.on(t, e);
778
+ }
779
+ getState() {
780
+ return this.socket.getState();
781
+ }
782
+ connect() {
783
+ if (!this.opts.jwt) {
784
+ this.bus.emit("status", {
785
+ status: "closed",
786
+ attempts: 0,
787
+ reason: "missing auth token"
788
+ });
789
+ return;
790
+ }
791
+ this.socket.connect();
792
+ }
793
+ handleMessage(t) {
794
+ let e;
795
+ try {
796
+ e = JSON.parse(
797
+ typeof t.data == "string" ? t.data : String(t.data)
798
+ );
799
+ } catch {
800
+ return;
801
+ }
802
+ e.kind === A && (e.channel && e.channel !== this.opts.channel || this.bus.emit("message", { from: e.sender, text: e.content }));
803
+ }
804
+ send(t) {
805
+ const e = t.trim().slice(0, 200);
806
+ if (!e || !this.socket.isOpen()) return;
807
+ const i = {
808
+ kind: A,
809
+ sender: "",
810
+ platform: "",
811
+ channel: this.opts.channel,
812
+ content: e
813
+ };
814
+ this.socket.send(JSON.stringify(i));
815
+ }
816
+ close() {
817
+ this.socket.close();
818
+ }
819
+ }
351
820
  export {
352
- A as LaserEventBus,
353
- g as PhaserContext,
354
- z as PhaserGame,
355
- V as PlayerController,
356
- d as Quadtree,
357
- it as RAPIER,
358
- $ as Stage,
359
- j as VirtualJoystick,
360
- X as addComponent,
361
- Y as addEntity,
362
- B as createBirdAnimation,
363
- Z as createBirdSprites,
364
- rt as createRapierPhysics,
365
- L as createShadowSprites,
366
- N as createWorld,
367
- G as getBirdNum,
368
- Q as hasComponent,
369
- O as isBird,
370
- f as laserEvents,
371
- tt as query,
372
- et as removeEntity,
373
- H as useGameLoop,
374
- T as usePhaserEvent,
375
- R as usePhaserGame
821
+ Pt as ACTION_ATTACK,
822
+ Tt as ACTION_PICKUP,
823
+ tt as EPHEMERAL_BLACKJACK,
824
+ $ as EPHEMERAL_COMBAT,
825
+ Y as EPHEMERAL_EQUIPPED,
826
+ V as EPHEMERAL_INVENTORY,
827
+ Z as EPHEMERAL_ITEM_USED,
828
+ G as EPHEMERAL_PICKUP,
829
+ Q as EPHEMERAL_SHOP,
830
+ X as EPHEMERAL_STATS,
831
+ Ct as EPHEMERAL_STATUS,
832
+ _t as EPHEMERAL_TRADE,
833
+ Nt as GameClient,
834
+ Kt as KIND_CAT_ITEM,
835
+ Ot as KIND_CAT_NPC,
836
+ vt as KIND_CAT_PLAYER,
837
+ S as LaserEventBus,
838
+ Lt as OWNER_NONE,
839
+ J as PROTOCOL_VERSION,
840
+ T as PhaserContext,
841
+ lt as PhaserGame,
842
+ pt as PlayerController,
843
+ M as Quadtree,
844
+ Ht as RAPIER,
845
+ qt as RealmChatClient,
846
+ _ as ReconnectingSocket,
847
+ Rt as SideMap,
848
+ St as Stage,
849
+ W as VirtualJoystick,
850
+ xt as attachCameraZoom,
851
+ kt as createBirdAnimation,
852
+ gt as createBirdSprites,
853
+ zt as createRapierPhysics,
854
+ Et as createShadowSprites,
855
+ jt as decodeCard,
856
+ b as decodeEphemeralPayload,
857
+ B as defaultCloseReason,
858
+ ft as drawHealthBar,
859
+ bt as findTilePath,
860
+ mt as flashEntity,
861
+ yt as floatingText,
862
+ wt as getBirdNum,
863
+ rt as inputFrame,
864
+ Mt as isBird,
865
+ nt as joinFrame,
866
+ E as laserEvents,
867
+ Dt as nearestInRange,
868
+ It as queryInRange,
869
+ At as useGameLoop,
870
+ dt as usePhaserEvent,
871
+ U as usePhaserGame
376
872
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbve/laser",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Phaser + React Three Fiber integration layer for React 19",
5
5
  "keywords": [
6
6
  "phaser",
@@ -39,7 +39,7 @@
39
39
  "peerDependencies": {
40
40
  "react": ">=18.0.0",
41
41
  "react-dom": ">=18.0.0",
42
- "phaser": ">=3.80.0",
42
+ "phaser": ">=4.1.0",
43
43
  "three": ">=0.160.0",
44
44
  "@react-three/fiber": ">=9.0.0",
45
45
  "@react-three/drei": ">=10.0.0",