@zylem/game-lib 0.6.2 → 0.6.4

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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -16
  3. package/dist/actions.d.ts +30 -21
  4. package/dist/actions.js +793 -146
  5. package/dist/actions.js.map +1 -1
  6. package/dist/behavior/jumper-2d.d.ts +114 -0
  7. package/dist/behavior/jumper-2d.js +711 -0
  8. package/dist/behavior/jumper-2d.js.map +1 -0
  9. package/dist/behavior/platformer-3d.d.ts +296 -0
  10. package/dist/behavior/platformer-3d.js +761 -0
  11. package/dist/behavior/platformer-3d.js.map +1 -0
  12. package/dist/behavior/ricochet-2d.d.ts +275 -0
  13. package/dist/behavior/ricochet-2d.js +425 -0
  14. package/dist/behavior/ricochet-2d.js.map +1 -0
  15. package/dist/behavior/ricochet-3d.d.ts +117 -0
  16. package/dist/behavior/ricochet-3d.js +443 -0
  17. package/dist/behavior/ricochet-3d.js.map +1 -0
  18. package/dist/behavior/screen-visibility.d.ts +79 -0
  19. package/dist/behavior/screen-visibility.js +358 -0
  20. package/dist/behavior/screen-visibility.js.map +1 -0
  21. package/dist/behavior/screen-wrap.d.ts +87 -0
  22. package/dist/behavior/screen-wrap.js +246 -0
  23. package/dist/behavior/screen-wrap.js.map +1 -0
  24. package/dist/behavior/shooter-2d.d.ts +79 -0
  25. package/dist/behavior/shooter-2d.js +180 -0
  26. package/dist/behavior/shooter-2d.js.map +1 -0
  27. package/dist/behavior/thruster.d.ts +11 -0
  28. package/dist/behavior/thruster.js +292 -0
  29. package/dist/behavior/thruster.js.map +1 -0
  30. package/dist/behavior/top-down-movement.d.ts +56 -0
  31. package/dist/behavior/top-down-movement.js +125 -0
  32. package/dist/behavior/top-down-movement.js.map +1 -0
  33. package/dist/behavior/world-boundary-2d.d.ts +142 -0
  34. package/dist/behavior/world-boundary-2d.js +235 -0
  35. package/dist/behavior/world-boundary-2d.js.map +1 -0
  36. package/dist/behavior/world-boundary-3d.d.ts +76 -0
  37. package/dist/behavior/world-boundary-3d.js +274 -0
  38. package/dist/behavior/world-boundary-3d.js.map +1 -0
  39. package/dist/behavior-descriptor-BXnVR8Ki.d.ts +159 -0
  40. package/dist/{blueprints-Cq3Ko6_G.d.ts → blueprints-DmbK2dki.d.ts} +2 -2
  41. package/dist/camera-4XO5gbQH.d.ts +905 -0
  42. package/dist/camera.d.ts +3 -2
  43. package/dist/camera.js +1653 -377
  44. package/dist/camera.js.map +1 -1
  45. package/dist/composition-BASvMKrW.d.ts +218 -0
  46. package/dist/{core-bO8TzV7u.d.ts → core-CARRaS55.d.ts} +110 -69
  47. package/dist/core.d.ts +11 -6
  48. package/dist/core.js +10766 -5626
  49. package/dist/core.js.map +1 -1
  50. package/dist/{entities-DvByhMGU.d.ts → entities-ChFirVL9.d.ts} +133 -29
  51. package/dist/entities.d.ts +5 -3
  52. package/dist/entities.js +4679 -3202
  53. package/dist/entities.js.map +1 -1
  54. package/dist/entity-vj-HTjzU.d.ts +1169 -0
  55. package/dist/global-change-2JvMaz44.d.ts +25 -0
  56. package/dist/main.d.ts +1118 -16
  57. package/dist/main.js +17538 -8499
  58. package/dist/main.js.map +1 -1
  59. package/dist/physics-pose-DCc4oE44.d.ts +25 -0
  60. package/dist/physics-protocol-BDD3P5W2.d.ts +200 -0
  61. package/dist/physics-worker.d.ts +21 -0
  62. package/dist/physics-worker.js +306 -0
  63. package/dist/physics-worker.js.map +1 -0
  64. package/dist/physics.d.ts +205 -0
  65. package/dist/physics.js +577 -0
  66. package/dist/physics.js.map +1 -0
  67. package/dist/stage-types-C19IhuzA.d.ts +731 -0
  68. package/dist/stage.d.ts +11 -7
  69. package/dist/stage.js +8024 -3852
  70. package/dist/stage.js.map +1 -1
  71. package/dist/sync-state-machine-CZyspBpj.d.ts +16 -0
  72. package/dist/thruster-23lzoPZd.d.ts +180 -0
  73. package/dist/world-DfgxoNMt.d.ts +105 -0
  74. package/package.json +53 -13
  75. package/dist/behaviors.d.ts +0 -854
  76. package/dist/behaviors.js +0 -1209
  77. package/dist/behaviors.js.map +0 -1
  78. package/dist/camera-CeJPAgGg.d.ts +0 -116
  79. package/dist/moveable-B_vyA6cw.d.ts +0 -67
  80. package/dist/stage-types-Bd-KtcYT.d.ts +0 -375
  81. package/dist/transformable-CUhvyuYO.d.ts +0 -67
  82. package/dist/world-C8tQ7Plj.d.ts +0 -774
@@ -0,0 +1,577 @@
1
+ // src/lib/physics/physics-protocol.ts
2
+ var FLOATS_PER_BODY = 13;
3
+ var TransformOffset = {
4
+ POS_X: 0,
5
+ POS_Y: 1,
6
+ POS_Z: 2,
7
+ ROT_X: 3,
8
+ ROT_Y: 4,
9
+ ROT_Z: 5,
10
+ ROT_W: 6,
11
+ LINVEL_X: 7,
12
+ LINVEL_Y: 8,
13
+ LINVEL_Z: 9,
14
+ ANGVEL_X: 10,
15
+ ANGVEL_Y: 11,
16
+ ANGVEL_Z: 12
17
+ };
18
+
19
+ // src/lib/physics/physics-pose.ts
20
+ import { Quaternion } from "three";
21
+ var _previousQuaternion = new Quaternion();
22
+ var _currentQuaternion = new Quaternion();
23
+ var _renderQuaternion = new Quaternion();
24
+ function createPhysicsPose(position = {}, rotation = {}) {
25
+ return {
26
+ position: {
27
+ x: position.x ?? 0,
28
+ y: position.y ?? 0,
29
+ z: position.z ?? 0
30
+ },
31
+ rotation: {
32
+ x: rotation.x ?? 0,
33
+ y: rotation.y ?? 0,
34
+ z: rotation.z ?? 0,
35
+ w: rotation.w ?? 1
36
+ }
37
+ };
38
+ }
39
+ function clampInterpolationAlpha(alpha) {
40
+ if (!Number.isFinite(alpha)) return 0;
41
+ return Math.max(0, Math.min(1, alpha));
42
+ }
43
+ function interpolatePhysicsPose(previous, current, alpha) {
44
+ const t = clampInterpolationAlpha(alpha);
45
+ _previousQuaternion.set(
46
+ previous.rotation.x,
47
+ previous.rotation.y,
48
+ previous.rotation.z,
49
+ previous.rotation.w
50
+ );
51
+ _currentQuaternion.set(
52
+ current.rotation.x,
53
+ current.rotation.y,
54
+ current.rotation.z,
55
+ current.rotation.w
56
+ );
57
+ _renderQuaternion.slerpQuaternions(
58
+ _previousQuaternion,
59
+ _currentQuaternion,
60
+ t
61
+ );
62
+ return {
63
+ position: {
64
+ x: previous.position.x + (current.position.x - previous.position.x) * t,
65
+ y: previous.position.y + (current.position.y - previous.position.y) * t,
66
+ z: previous.position.z + (current.position.z - previous.position.z) * t
67
+ },
68
+ rotation: {
69
+ x: _renderQuaternion.x,
70
+ y: _renderQuaternion.y,
71
+ z: _renderQuaternion.z,
72
+ w: _renderQuaternion.w
73
+ }
74
+ };
75
+ }
76
+
77
+ // src/lib/physics/physics-body-handle.ts
78
+ var PhysicsBodyHandle = class {
79
+ uuid;
80
+ /** Last-known physics state, updated from worker each frame. */
81
+ _snapshot = {
82
+ previous: createPhysicsPose(),
83
+ current: createPhysicsPose(),
84
+ linvel: { x: 0, y: 0, z: 0 },
85
+ angvel: { x: 0, y: 0, z: 0 }
86
+ };
87
+ /** Queued commands to be sent to the worker on next step. */
88
+ _pendingCommands = [];
89
+ /** Optional reference to the proxy's shared command queue. */
90
+ _sharedQueue = null;
91
+ constructor(uuid, sharedQueue) {
92
+ this.uuid = uuid;
93
+ this._sharedQueue = sharedQueue ?? null;
94
+ }
95
+ // ─── Read API (returns cached values) ────────────────────────────────
96
+ /** Cached position from last physics step. */
97
+ translation() {
98
+ return this._snapshot.current.position;
99
+ }
100
+ /** Cached rotation quaternion from last physics step. */
101
+ rotation() {
102
+ return this._snapshot.current.rotation;
103
+ }
104
+ /** Cached linear velocity from last physics step. */
105
+ linvel() {
106
+ return this._snapshot.linvel;
107
+ }
108
+ /** Cached angular velocity from last physics step. */
109
+ angvel() {
110
+ return this._snapshot.angvel;
111
+ }
112
+ getPoseHistory() {
113
+ return this._snapshot;
114
+ }
115
+ getRenderPose(alpha) {
116
+ return interpolatePhysicsPose(
117
+ this._snapshot.previous,
118
+ this._snapshot.current,
119
+ alpha
120
+ );
121
+ }
122
+ // ─── Write API (queues commands) ─────────────────────────────────────
123
+ setLinvel(v, _wakeUp) {
124
+ this.enqueue({ kind: "setLinvel", uuid: this.uuid, x: v.x, y: v.y, z: v.z });
125
+ this._snapshot.linvel = { ...v };
126
+ }
127
+ setAngvel(v, _wakeUp) {
128
+ this.enqueue({ kind: "setAngvel", uuid: this.uuid, x: v.x, y: v.y, z: v.z });
129
+ this._snapshot.angvel = { ...v };
130
+ }
131
+ setTranslation(v, _wakeUp) {
132
+ this.enqueue({ kind: "setTranslation", uuid: this.uuid, x: v.x, y: v.y, z: v.z });
133
+ this.setCollapsedTranslation(v);
134
+ }
135
+ setRotation(q, _wakeUp) {
136
+ this.enqueue({ kind: "setRotation", uuid: this.uuid, x: q.x, y: q.y, z: q.z, w: q.w });
137
+ this.setCollapsedRotation(q);
138
+ }
139
+ applyImpulse(v, _wakeUp) {
140
+ this.enqueue({ kind: "applyImpulse", uuid: this.uuid, x: v.x, y: v.y, z: v.z });
141
+ }
142
+ applyTorqueImpulse(v, _wakeUp) {
143
+ this.enqueue({ kind: "applyTorqueImpulse", uuid: this.uuid, x: v.x, y: v.y, z: v.z });
144
+ }
145
+ lockTranslations(locked, _wakeUp) {
146
+ this.enqueue({ kind: "lockTranslations", uuid: this.uuid, locked });
147
+ }
148
+ lockRotations(locked, _wakeUp) {
149
+ this.enqueue({ kind: "lockRotations", uuid: this.uuid, locked });
150
+ }
151
+ setLinearDamping(damping) {
152
+ this.enqueue({ kind: "setLinearDamping", uuid: this.uuid, damping });
153
+ }
154
+ setGravityScale(scale, _wakeUp) {
155
+ this.enqueue({ kind: "setGravityScale", uuid: this.uuid, scale });
156
+ }
157
+ // ─── Stubbed read-only methods for compatibility ─────────────────────
158
+ /** Returns 'Dynamic' for compatibility; actual type is not synced. */
159
+ bodyType() {
160
+ return 0;
161
+ }
162
+ mass() {
163
+ return 1;
164
+ }
165
+ isEnabled() {
166
+ return true;
167
+ }
168
+ isSleeping() {
169
+ return false;
170
+ }
171
+ /** Collider access is not available through the handle. Returns null. */
172
+ collider(_index) {
173
+ return null;
174
+ }
175
+ // ─── Internal ────────────────────────────────────────────────────────
176
+ /**
177
+ * Update the cached snapshot from worker data.
178
+ * Called by the PhysicsProxy after receiving a stepResult.
179
+ */
180
+ _seedSnapshot(px, py, pz, rx, ry, rz, rw, lvx, lvy, lvz, avx, avy, avz) {
181
+ this.writePose(this._snapshot.previous, px, py, pz, rx, ry, rz, rw);
182
+ this.writePose(this._snapshot.current, px, py, pz, rx, ry, rz, rw);
183
+ this._snapshot.linvel.x = lvx;
184
+ this._snapshot.linvel.y = lvy;
185
+ this._snapshot.linvel.z = lvz;
186
+ this._snapshot.angvel.x = avx;
187
+ this._snapshot.angvel.y = avy;
188
+ this._snapshot.angvel.z = avz;
189
+ }
190
+ _updateSnapshot(px, py, pz, rx, ry, rz, rw, lvx, lvy, lvz, avx, avy, avz) {
191
+ this.copyPose(this._snapshot.current, this._snapshot.previous);
192
+ this.writePose(this._snapshot.current, px, py, pz, rx, ry, rz, rw);
193
+ this._snapshot.linvel.x = lvx;
194
+ this._snapshot.linvel.y = lvy;
195
+ this._snapshot.linvel.z = lvz;
196
+ this._snapshot.angvel.x = avx;
197
+ this._snapshot.angvel.y = avy;
198
+ this._snapshot.angvel.z = avz;
199
+ }
200
+ /** Drain pending commands. */
201
+ _drainCommands() {
202
+ const cmds = this._pendingCommands;
203
+ this._pendingCommands = [];
204
+ return cmds;
205
+ }
206
+ enqueue(cmd) {
207
+ if (this._sharedQueue) {
208
+ this._sharedQueue.push(cmd);
209
+ } else {
210
+ this._pendingCommands.push(cmd);
211
+ }
212
+ }
213
+ copyPose(source, target) {
214
+ target.position.x = source.position.x;
215
+ target.position.y = source.position.y;
216
+ target.position.z = source.position.z;
217
+ target.rotation.x = source.rotation.x;
218
+ target.rotation.y = source.rotation.y;
219
+ target.rotation.z = source.rotation.z;
220
+ target.rotation.w = source.rotation.w;
221
+ }
222
+ writePose(target, px, py, pz, rx, ry, rz, rw) {
223
+ target.position.x = px;
224
+ target.position.y = py;
225
+ target.position.z = pz;
226
+ target.rotation.x = rx;
227
+ target.rotation.y = ry;
228
+ target.rotation.z = rz;
229
+ target.rotation.w = rw;
230
+ }
231
+ setCollapsedTranslation(translation) {
232
+ this._snapshot.previous.position.x = translation.x;
233
+ this._snapshot.previous.position.y = translation.y;
234
+ this._snapshot.previous.position.z = translation.z;
235
+ this._snapshot.current.position.x = translation.x;
236
+ this._snapshot.current.position.y = translation.y;
237
+ this._snapshot.current.position.z = translation.z;
238
+ }
239
+ setCollapsedRotation(rotation) {
240
+ this._snapshot.previous.rotation.x = rotation.x;
241
+ this._snapshot.previous.rotation.y = rotation.y;
242
+ this._snapshot.previous.rotation.z = rotation.z;
243
+ this._snapshot.previous.rotation.w = rotation.w;
244
+ this._snapshot.current.rotation.x = rotation.x;
245
+ this._snapshot.current.rotation.y = rotation.y;
246
+ this._snapshot.current.rotation.z = rotation.z;
247
+ this._snapshot.current.rotation.w = rotation.w;
248
+ }
249
+ };
250
+
251
+ // src/lib/physics/physics-proxy.ts
252
+ var PhysicsProxy = class {
253
+ worker = null;
254
+ handles = /* @__PURE__ */ new Map();
255
+ commandQueue = [];
256
+ collisionListeners = [];
257
+ pendingStep = null;
258
+ /** Latest interpolation alpha from the worker (0..1). */
259
+ interpolationAlpha = 0;
260
+ /**
261
+ * Spawn the worker and initialize the Rapier world inside it.
262
+ * Resolves when the worker reports `ready`.
263
+ *
264
+ * @param gravity World gravity as [x, y, z].
265
+ * @param physicsRate Physics tick rate in Hz (default 60).
266
+ * @param workerUrl URL to the physics worker script. The consuming
267
+ * application must provide this because bundlers (Vite, Webpack)
268
+ * can only resolve worker URLs from application source code.
269
+ * Example for Vite:
270
+ * ```ts
271
+ * new URL('@zylem/game-lib/dist/physics-worker.js', import.meta.url)
272
+ * ```
273
+ */
274
+ async init(gravity, physicsRate = 60, workerUrl) {
275
+ if (!workerUrl) {
276
+ throw new Error(
277
+ '[PhysicsProxy] workerUrl is required. Provide physicsWorkerUrl in your stage config.\nFor Vite: physicsWorkerUrl: new URL("@zylem/game-lib/dist/physics-worker.js", import.meta.url)'
278
+ );
279
+ }
280
+ this.worker = new Worker(workerUrl, { type: "module" });
281
+ return new Promise((resolve, reject) => {
282
+ const onMessage = (e) => {
283
+ if (e.data.type === "ready") {
284
+ this.worker.removeEventListener("message", onMessage);
285
+ this.worker.addEventListener("message", this.onWorkerMessage.bind(this));
286
+ resolve();
287
+ } else if (e.data.type === "error") {
288
+ reject(new Error(e.data.message));
289
+ }
290
+ };
291
+ this.worker.addEventListener("message", onMessage);
292
+ this.send({ type: "init", gravity, physicsRate });
293
+ });
294
+ }
295
+ /**
296
+ * Register a body in the worker and return a main-thread handle.
297
+ *
298
+ * @returns A {@link PhysicsBodyHandle} for reading cached transforms
299
+ * and queuing write commands.
300
+ */
301
+ addBody(uuid, body, colliders, characterController) {
302
+ const cmd = {
303
+ type: "addBody",
304
+ uuid,
305
+ body,
306
+ colliders,
307
+ characterController
308
+ };
309
+ this.send(cmd);
310
+ const handle = new PhysicsBodyHandle(uuid, this.commandQueue);
311
+ handle._seedSnapshot(
312
+ body.translation[0],
313
+ body.translation[1],
314
+ body.translation[2],
315
+ 0,
316
+ 0,
317
+ 0,
318
+ 1,
319
+ 0,
320
+ 0,
321
+ 0,
322
+ 0,
323
+ 0,
324
+ 0
325
+ );
326
+ this.handles.set(uuid, handle);
327
+ return handle;
328
+ }
329
+ /** Remove a body from the worker and discard its handle. */
330
+ removeBody(uuid) {
331
+ this.send({ type: "removeBody", uuid });
332
+ this.handles.delete(uuid);
333
+ }
334
+ /** Get a body handle by entity UUID. */
335
+ getHandle(uuid) {
336
+ return this.handles.get(uuid);
337
+ }
338
+ /**
339
+ * Send a step command to the worker with the current frame delta
340
+ * and all queued body commands.
341
+ *
342
+ * Returns a promise that resolves after the worker replies with
343
+ * the step result. Handles are updated and collision callbacks
344
+ * are fired before the promise resolves.
345
+ */
346
+ step(delta) {
347
+ return new Promise((resolve, reject) => {
348
+ this.pendingStep = { resolve, reject };
349
+ const commands = this.commandQueue.splice(0);
350
+ for (const handle of this.handles.values()) {
351
+ commands.push(...handle._drainCommands());
352
+ }
353
+ this.send({ type: "step", delta, commands });
354
+ });
355
+ }
356
+ /**
357
+ * Subscribe to collision events.
358
+ * @returns Unsubscribe function.
359
+ */
360
+ onCollision(callback) {
361
+ this.collisionListeners.push(callback);
362
+ return () => {
363
+ this.collisionListeners = this.collisionListeners.filter((cb) => cb !== callback);
364
+ };
365
+ }
366
+ /** Terminate the worker and release all handles. */
367
+ dispose() {
368
+ if (this.worker) {
369
+ this.send({ type: "dispose" });
370
+ this.worker.terminate();
371
+ this.worker = null;
372
+ }
373
+ this.handles.clear();
374
+ this.commandQueue.length = 0;
375
+ this.collisionListeners.length = 0;
376
+ this.pendingStep = null;
377
+ }
378
+ // ─── Internal ────────────────────────────────────────────────────────
379
+ send(cmd) {
380
+ this.worker?.postMessage(cmd);
381
+ }
382
+ onWorkerMessage(e) {
383
+ const event = e.data;
384
+ switch (event.type) {
385
+ case "stepResult":
386
+ this.applyStepResult(event);
387
+ break;
388
+ case "error":
389
+ if (this.pendingStep) {
390
+ this.pendingStep.reject(new Error(event.message));
391
+ this.pendingStep = null;
392
+ } else {
393
+ console.error("[PhysicsProxy] Worker error:", event.message);
394
+ }
395
+ break;
396
+ }
397
+ }
398
+ applyStepResult(result) {
399
+ const { transforms, bodyOrder, collisions, interpolationAlpha } = result;
400
+ this.interpolationAlpha = interpolationAlpha;
401
+ for (let i = 0; i < bodyOrder.length; i++) {
402
+ const handle = this.handles.get(bodyOrder[i]);
403
+ if (!handle) continue;
404
+ const o = i * FLOATS_PER_BODY;
405
+ handle._updateSnapshot(
406
+ transforms[o + TransformOffset.POS_X],
407
+ transforms[o + TransformOffset.POS_Y],
408
+ transforms[o + TransformOffset.POS_Z],
409
+ transforms[o + TransformOffset.ROT_X],
410
+ transforms[o + TransformOffset.ROT_Y],
411
+ transforms[o + TransformOffset.ROT_Z],
412
+ transforms[o + TransformOffset.ROT_W],
413
+ transforms[o + TransformOffset.LINVEL_X],
414
+ transforms[o + TransformOffset.LINVEL_Y],
415
+ transforms[o + TransformOffset.LINVEL_Z],
416
+ transforms[o + TransformOffset.ANGVEL_X],
417
+ transforms[o + TransformOffset.ANGVEL_Y],
418
+ transforms[o + TransformOffset.ANGVEL_Z]
419
+ );
420
+ }
421
+ for (const pair of collisions) {
422
+ for (const listener of this.collisionListeners) {
423
+ try {
424
+ listener(pair);
425
+ } catch (err) {
426
+ console.error("[PhysicsProxy] Collision listener error:", err);
427
+ }
428
+ }
429
+ }
430
+ if (this.pendingStep) {
431
+ this.pendingStep.resolve(result);
432
+ this.pendingStep = null;
433
+ }
434
+ }
435
+ };
436
+
437
+ // src/lib/physics/serialize-descriptors.ts
438
+ import { RigidBodyType } from "@dimforge/rapier3d-compat";
439
+ function serializeBodyDesc(desc) {
440
+ const status = desc.status;
441
+ let type = "dynamic";
442
+ if (status === RigidBodyType.Fixed) type = "fixed";
443
+ else if (status === RigidBodyType.KinematicPositionBased) type = "kinematicPositionBased";
444
+ else if (status === RigidBodyType.KinematicVelocityBased) type = "kinematicVelocityBased";
445
+ const t = desc.translation ?? { x: 0, y: 0, z: 0 };
446
+ return {
447
+ type,
448
+ translation: [t.x ?? 0, t.y ?? 0, t.z ?? 0],
449
+ gravityScale: desc.gravityScale ?? 1,
450
+ canSleep: desc.canSleep ?? false,
451
+ ccdEnabled: desc.ccdEnabled ?? true
452
+ };
453
+ }
454
+ function serializeColliderDesc(desc) {
455
+ const internal = desc;
456
+ const customShapeData = internal.__zylemShapeData;
457
+ if (customShapeData?.shape === "trimesh") {
458
+ const result2 = {
459
+ shape: "trimesh",
460
+ dimensions: [],
461
+ vertices: [...customShapeData.vertices],
462
+ indices: [...customShapeData.indices]
463
+ };
464
+ const translation = internal.translation;
465
+ if (translation && (translation.x !== 0 || translation.y !== 0 || translation.z !== 0)) {
466
+ result2.translation = [translation.x, translation.y, translation.z];
467
+ }
468
+ if (internal.isSensor) {
469
+ result2.sensor = true;
470
+ }
471
+ if (internal.collisionGroups !== void 0 && internal.collisionGroups !== 4294967295) {
472
+ result2.collisionGroups = internal.collisionGroups;
473
+ }
474
+ if (internal.activeCollisionTypes !== void 0) {
475
+ result2.activeCollisionTypes = internal.activeCollisionTypes;
476
+ }
477
+ return result2;
478
+ }
479
+ const shapeType = internal.shape?.type ?? internal.shapeType ?? 0;
480
+ const { shape, dimensions, heightfieldMeta } = extractShapeData(shapeType, internal);
481
+ const result = {
482
+ shape,
483
+ dimensions
484
+ };
485
+ const t = internal.translation;
486
+ if (t && (t.x !== 0 || t.y !== 0 || t.z !== 0)) {
487
+ result.translation = [t.x, t.y, t.z];
488
+ }
489
+ if (internal.isSensor) {
490
+ result.sensor = true;
491
+ }
492
+ if (internal.collisionGroups !== void 0 && internal.collisionGroups !== 4294967295) {
493
+ result.collisionGroups = internal.collisionGroups;
494
+ }
495
+ if (internal.activeCollisionTypes !== void 0) {
496
+ result.activeCollisionTypes = internal.activeCollisionTypes;
497
+ }
498
+ if (heightfieldMeta) {
499
+ result.heightfieldMeta = heightfieldMeta;
500
+ }
501
+ return result;
502
+ }
503
+ function serializeCharacterController() {
504
+ return {
505
+ offset: 0.01,
506
+ maxSlopeClimbAngle: 45 * Math.PI / 180,
507
+ minSlopeSlideAngle: 30 * Math.PI / 180,
508
+ snapToGroundDistance: 0.01,
509
+ slideEnabled: true,
510
+ applyImpulsesToDynamic: true,
511
+ characterMass: 1
512
+ };
513
+ }
514
+ function extractShapeData(shapeType, internal) {
515
+ switch (shapeType) {
516
+ case 0:
517
+ return {
518
+ shape: "ball",
519
+ dimensions: [internal.shape?.radius ?? internal.halfExtents?.x ?? 1]
520
+ };
521
+ case 1:
522
+ return {
523
+ shape: "cuboid",
524
+ dimensions: [
525
+ internal.shape?.halfExtents?.x ?? internal.halfExtents?.x ?? 0.5,
526
+ internal.shape?.halfExtents?.y ?? internal.halfExtents?.y ?? 0.5,
527
+ internal.shape?.halfExtents?.z ?? internal.halfExtents?.z ?? 0.5
528
+ ]
529
+ };
530
+ case 2:
531
+ return {
532
+ shape: "capsule",
533
+ dimensions: [
534
+ internal.shape?.halfHeight ?? 0.5,
535
+ internal.shape?.radius ?? 0.5
536
+ ]
537
+ };
538
+ case 6:
539
+ return {
540
+ shape: "cone",
541
+ dimensions: [
542
+ internal.shape?.halfHeight ?? 1,
543
+ internal.shape?.radius ?? 1
544
+ ]
545
+ };
546
+ case 7:
547
+ return {
548
+ shape: "cylinder",
549
+ dimensions: [
550
+ internal.shape?.halfHeight ?? 1,
551
+ internal.shape?.radius ?? 1
552
+ ]
553
+ };
554
+ case 11: {
555
+ const nrows = internal.shape?.nrows ?? 10;
556
+ const ncols = internal.shape?.ncols ?? 10;
557
+ const heights = internal.shape?.heights;
558
+ return {
559
+ shape: "heightfield",
560
+ dimensions: heights ? Array.from(heights) : [],
561
+ heightfieldMeta: { nrows, ncols }
562
+ };
563
+ }
564
+ default:
565
+ return { shape: "cuboid", dimensions: [0.5, 0.5, 0.5] };
566
+ }
567
+ }
568
+ export {
569
+ FLOATS_PER_BODY,
570
+ PhysicsBodyHandle,
571
+ PhysicsProxy,
572
+ TransformOffset,
573
+ serializeBodyDesc,
574
+ serializeCharacterController,
575
+ serializeColliderDesc
576
+ };
577
+ //# sourceMappingURL=physics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/physics/physics-protocol.ts","../src/lib/physics/physics-pose.ts","../src/lib/physics/physics-body-handle.ts","../src/lib/physics/physics-proxy.ts","../src/lib/physics/serialize-descriptors.ts"],"sourcesContent":["/**\n * Message protocol for communication between the main thread and the\n * physics Web Worker.\n *\n * Data flows in two directions:\n * Main → Worker: {@link PhysicsCommand} (init, entity CRUD, per-frame step)\n * Worker → Main: {@link PhysicsEvent} (ready, step results, errors)\n *\n * All types are plain JSON-serializable objects so they can cross the\n * postMessage boundary without structured-clone issues.\n */\n\n// ─── Serializable Descriptor Types ─────────────────────────────────────────\n\n/** Rigid body type mirroring Rapier's RigidBodyType enum values. */\nexport type SerializableBodyType = 'dynamic' | 'fixed' | 'kinematicPositionBased' | 'kinematicVelocityBased';\n\n/**\n * Plain-object representation of a Rapier RigidBodyDesc.\n * Created on the main thread and reconstructed in the worker.\n */\nexport interface SerializableBodyDesc {\n\ttype: SerializableBodyType;\n\ttranslation: [number, number, number];\n\tgravityScale: number;\n\tcanSleep: boolean;\n\tccdEnabled: boolean;\n\tlockTranslations?: boolean;\n\tlockRotations?: boolean;\n}\n\n/** Collider shape kind. Matches the factory functions in collision-factories. */\nexport type ColliderShapeKind =\n\t| 'cuboid'\n\t| 'ball'\n\t| 'capsule'\n\t| 'cone'\n\t| 'cylinder'\n\t| 'trimesh'\n\t| 'heightfield';\n\n/**\n * Plain-object representation of a Rapier ColliderDesc.\n * Shape-specific dimensions are stored in {@link dimensions}.\n */\nexport interface SerializableColliderDesc {\n\tshape: ColliderShapeKind;\n\t/** Shape-specific numeric dimensions (e.g. halfExtents, radius, halfHeight). */\n\tdimensions: number[];\n\t/** For trimesh: flattened xyz vertex array. */\n\tvertices?: number[];\n\t/** For trimesh: triangle indices referencing {@link vertices}. */\n\tindices?: number[];\n\t/** Collider offset translation relative to the body. */\n\ttranslation?: [number, number, number];\n\tsensor?: boolean;\n\tcollisionGroups?: number;\n\tactiveCollisionTypes?: number;\n\t/** For heightfield: number of rows and columns. */\n\theightfieldMeta?: { nrows: number; ncols: number };\n}\n\n/** Describes a character controller to be created alongside the body. */\nexport interface SerializableCharacterController {\n\toffset: number;\n\tmaxSlopeClimbAngle: number;\n\tminSlopeSlideAngle: number;\n\tsnapToGroundDistance: number;\n\tslideEnabled: boolean;\n\tapplyImpulsesToDynamic: boolean;\n\tcharacterMass: number;\n}\n\n// ─── Per-Body Commands (batched inside a step) ─────────────────────────────\n\nexport type BodyCommand =\n\t| { kind: 'setLinvel'; uuid: string; x: number; y: number; z: number }\n\t| { kind: 'setAngvel'; uuid: string; x: number; y: number; z: number }\n\t| { kind: 'setTranslation'; uuid: string; x: number; y: number; z: number }\n\t| { kind: 'setRotation'; uuid: string; x: number; y: number; z: number; w: number }\n\t| { kind: 'applyImpulse'; uuid: string; x: number; y: number; z: number }\n\t| { kind: 'applyTorqueImpulse'; uuid: string; x: number; y: number; z: number }\n\t| { kind: 'lockTranslations'; uuid: string; locked: boolean }\n\t| { kind: 'lockRotations'; uuid: string; locked: boolean }\n\t| { kind: 'addTranslation'; uuid: string; dx: number; dy: number; dz: number }\n\t| { kind: 'setLinearDamping'; uuid: string; damping: number }\n\t| { kind: 'setGravityScale'; uuid: string; scale: number };\n\n// ─── Main → Worker Commands ────────────────────────────────────────────────\n\nexport type PhysicsCommand =\n\t| PhysicsInitCommand\n\t| PhysicsAddBodyCommand\n\t| PhysicsRemoveBodyCommand\n\t| PhysicsStepCommand\n\t| PhysicsDisposeCommand;\n\nexport interface PhysicsInitCommand {\n\ttype: 'init';\n\tgravity: [number, number, number];\n\tphysicsRate: number;\n}\n\nexport interface PhysicsAddBodyCommand {\n\ttype: 'addBody';\n\tuuid: string;\n\tbody: SerializableBodyDesc;\n\tcolliders: SerializableColliderDesc[];\n\tcharacterController?: SerializableCharacterController;\n}\n\nexport interface PhysicsRemoveBodyCommand {\n\ttype: 'removeBody';\n\tuuid: string;\n}\n\nexport interface PhysicsStepCommand {\n\ttype: 'step';\n\tdelta: number;\n\tcommands: BodyCommand[];\n}\n\nexport interface PhysicsDisposeCommand {\n\ttype: 'dispose';\n}\n\n// ─── Worker → Main Events ──────────────────────────────────────────────────\n\nexport type PhysicsEvent =\n\t| PhysicsReadyEvent\n\t| PhysicsStepResultEvent\n\t| PhysicsErrorEvent;\n\nexport interface PhysicsReadyEvent {\n\ttype: 'ready';\n}\n\n/**\n * Result of a physics step sent from the worker each frame.\n *\n * `transforms` is a flat Float32Array with 13 floats per body:\n * [posX, posY, posZ, rotX, rotY, rotZ, rotW, linvelX, linvelY, linvelZ, angvelX, angvelY, angvelZ]\n *\n * The order matches {@link bodyOrder} — an array of UUIDs in the same\n * index order as the transform buffer.\n */\nexport interface PhysicsStepResultEvent {\n\ttype: 'stepResult';\n\t/** Flat buffer: 13 floats per body (pos3, rot4, linvel3, angvel3). */\n\ttransforms: Float32Array;\n\t/** UUID order matching the transforms buffer. */\n\tbodyOrder: string[];\n\t/** Collision pairs detected this frame. */\n\tcollisions: CollisionPair[];\n\t/** Interpolation alpha for rendering (0..1). */\n\tinterpolationAlpha: number;\n}\n\nexport interface PhysicsErrorEvent {\n\ttype: 'error';\n\tmessage: string;\n}\n\n/** A collision pair detected during the physics step. */\nexport interface CollisionPair {\n\tuuidA: string;\n\tuuidB: string;\n\tcontactType: 'contact' | 'intersection';\n}\n\n// ─── Transform Buffer Layout ───────────────────────────────────────────────\n\n/** Number of floats per body in the transforms buffer. */\nexport const FLOATS_PER_BODY = 13;\n\n/** Offsets into the per-body segment of the transforms buffer. */\nexport const TransformOffset = {\n\tPOS_X: 0,\n\tPOS_Y: 1,\n\tPOS_Z: 2,\n\tROT_X: 3,\n\tROT_Y: 4,\n\tROT_Z: 5,\n\tROT_W: 6,\n\tLINVEL_X: 7,\n\tLINVEL_Y: 8,\n\tLINVEL_Z: 9,\n\tANGVEL_X: 10,\n\tANGVEL_Y: 11,\n\tANGVEL_Z: 12,\n} as const;\n","import { Quaternion } from 'three';\n\nexport interface PhysicsVector3 {\n\tx: number;\n\ty: number;\n\tz: number;\n}\n\nexport interface PhysicsQuaternion {\n\tx: number;\n\ty: number;\n\tz: number;\n\tw: number;\n}\n\nexport interface PhysicsPose {\n\tposition: PhysicsVector3;\n\trotation: PhysicsQuaternion;\n}\n\nexport interface PhysicsPoseHistory {\n\tprevious: PhysicsPose;\n\tcurrent: PhysicsPose;\n}\n\nexport interface PhysicsPoseReadable {\n\ttranslation(): PhysicsVector3;\n\trotation(): PhysicsQuaternion;\n}\n\nexport interface PhysicsRenderPoseProvider {\n\tgetPoseHistory(): PhysicsPoseHistory;\n\tgetRenderPose(alpha: number): PhysicsPose;\n}\n\nconst directBodyPoseHistory = new WeakMap<object, PhysicsPoseHistory>();\nconst _previousQuaternion = new Quaternion();\nconst _currentQuaternion = new Quaternion();\nconst _renderQuaternion = new Quaternion();\n\nexport function createPhysicsPose(\n\tposition: Partial<PhysicsVector3> = {},\n\trotation: Partial<PhysicsQuaternion> = {},\n): PhysicsPose {\n\treturn {\n\t\tposition: {\n\t\t\tx: position.x ?? 0,\n\t\t\ty: position.y ?? 0,\n\t\t\tz: position.z ?? 0,\n\t\t},\n\t\trotation: {\n\t\t\tx: rotation.x ?? 0,\n\t\t\ty: rotation.y ?? 0,\n\t\t\tz: rotation.z ?? 0,\n\t\t\tw: rotation.w ?? 1,\n\t\t},\n\t};\n}\n\nexport function clonePhysicsVector3(vector: PhysicsVector3): PhysicsVector3 {\n\treturn { x: vector.x, y: vector.y, z: vector.z };\n}\n\nexport function clonePhysicsQuaternion(\n\trotation: PhysicsQuaternion,\n): PhysicsQuaternion {\n\treturn { x: rotation.x, y: rotation.y, z: rotation.z, w: rotation.w };\n}\n\nexport function clonePhysicsPose(pose: PhysicsPose): PhysicsPose {\n\treturn {\n\t\tposition: clonePhysicsVector3(pose.position),\n\t\trotation: clonePhysicsQuaternion(pose.rotation),\n\t};\n}\n\nexport function clampInterpolationAlpha(alpha: number): number {\n\tif (!Number.isFinite(alpha)) return 0;\n\treturn Math.max(0, Math.min(1, alpha));\n}\n\nexport function capturePhysicsPose(body: PhysicsPoseReadable): PhysicsPose {\n\treturn {\n\t\tposition: clonePhysicsVector3(body.translation()),\n\t\trotation: clonePhysicsQuaternion(body.rotation()),\n\t};\n}\n\nexport function createCollapsedPhysicsPoseHistory(\n\tpose: PhysicsPose,\n): PhysicsPoseHistory {\n\tconst current = clonePhysicsPose(pose);\n\treturn {\n\t\tprevious: clonePhysicsPose(current),\n\t\tcurrent,\n\t};\n}\n\nexport function registerDirectBodyPoseHistory(\n\tbody: object & PhysicsPoseReadable,\n): PhysicsPoseHistory {\n\tconst history = createCollapsedPhysicsPoseHistory(capturePhysicsPose(body));\n\tdirectBodyPoseHistory.set(body, history);\n\treturn history;\n}\n\nexport function getDirectBodyPoseHistory(\n\tbody: object,\n): PhysicsPoseHistory | null {\n\treturn directBodyPoseHistory.get(body) ?? null;\n}\n\nexport function collapseDirectBodyPoseHistory(\n\tbody: object & PhysicsPoseReadable,\n): PhysicsPoseHistory {\n\tconst pose = capturePhysicsPose(body);\n\tconst history =\n\t\tdirectBodyPoseHistory.get(body) ?? createCollapsedPhysicsPoseHistory(pose);\n\n\thistory.previous = clonePhysicsPose(pose);\n\thistory.current = clonePhysicsPose(pose);\n\tdirectBodyPoseHistory.set(body, history);\n\n\treturn history;\n}\n\nexport function prepareDirectBodyPoseHistoryStep(\n\tbody: object & PhysicsPoseReadable,\n): PhysicsPoseHistory {\n\treturn collapseDirectBodyPoseHistory(body);\n}\n\nexport function commitDirectBodyPoseHistoryStep(\n\tbody: object & PhysicsPoseReadable,\n): PhysicsPoseHistory {\n\tconst pose = capturePhysicsPose(body);\n\tconst history =\n\t\tdirectBodyPoseHistory.get(body) ?? createCollapsedPhysicsPoseHistory(pose);\n\n\thistory.current = clonePhysicsPose(pose);\n\tdirectBodyPoseHistory.set(body, history);\n\n\treturn history;\n}\n\nexport function interpolatePhysicsPose(\n\tprevious: PhysicsPose,\n\tcurrent: PhysicsPose,\n\talpha: number,\n): PhysicsPose {\n\tconst t = clampInterpolationAlpha(alpha);\n\n\t_previousQuaternion.set(\n\t\tprevious.rotation.x,\n\t\tprevious.rotation.y,\n\t\tprevious.rotation.z,\n\t\tprevious.rotation.w,\n\t);\n\t_currentQuaternion.set(\n\t\tcurrent.rotation.x,\n\t\tcurrent.rotation.y,\n\t\tcurrent.rotation.z,\n\t\tcurrent.rotation.w,\n\t);\n\t_renderQuaternion.slerpQuaternions(\n\t\t_previousQuaternion,\n\t\t_currentQuaternion,\n\t\tt,\n\t);\n\n\treturn {\n\t\tposition: {\n\t\t\tx: previous.position.x + (current.position.x - previous.position.x) * t,\n\t\t\ty: previous.position.y + (current.position.y - previous.position.y) * t,\n\t\t\tz: previous.position.z + (current.position.z - previous.position.z) * t,\n\t\t},\n\t\trotation: {\n\t\t\tx: _renderQuaternion.x,\n\t\t\ty: _renderQuaternion.y,\n\t\t\tz: _renderQuaternion.z,\n\t\t\tw: _renderQuaternion.w,\n\t\t},\n\t};\n}\n\nexport function getBodyPoseHistory(body: unknown): PhysicsPoseHistory | null {\n\tif (isRenderPoseProvider(body)) {\n\t\treturn body.getPoseHistory();\n\t}\n\tif (isPhysicsPoseReadable(body)) {\n\t\treturn directBodyPoseHistory.get(body as object) ?? null;\n\t}\n\treturn null;\n}\n\nexport function getBodyRenderPose(\n\tbody: PhysicsPoseReadable | PhysicsRenderPoseProvider,\n\talpha: number,\n): PhysicsPose {\n\tif (isRenderPoseProvider(body)) {\n\t\treturn body.getRenderPose(alpha);\n\t}\n\n\tconst history = directBodyPoseHistory.get(body as object);\n\tif (!history) {\n\t\treturn capturePhysicsPose(body);\n\t}\n\n\tconst latestPose = capturePhysicsPose(body);\n\tif (!posesEqual(latestPose, history.current)) {\n\t\tconst collapsed = collapseDirectBodyPoseHistory(body as object & PhysicsPoseReadable);\n\t\treturn clonePhysicsPose(collapsed.current);\n\t}\n\n\treturn interpolatePhysicsPose(history.previous, history.current, alpha);\n}\n\nfunction isPhysicsPoseReadable(value: unknown): value is PhysicsPoseReadable {\n\treturn (\n\t\tvalue != null &&\n\t\ttypeof value === 'object' &&\n\t\ttypeof (value as PhysicsPoseReadable).translation === 'function' &&\n\t\ttypeof (value as PhysicsPoseReadable).rotation === 'function'\n\t);\n}\n\nfunction isRenderPoseProvider(value: unknown): value is PhysicsRenderPoseProvider {\n\treturn (\n\t\tvalue != null &&\n\t\ttypeof value === 'object' &&\n\t\ttypeof (value as PhysicsRenderPoseProvider).getPoseHistory === 'function' &&\n\t\ttypeof (value as PhysicsRenderPoseProvider).getRenderPose === 'function'\n\t);\n}\n\nfunction posesEqual(a: PhysicsPose, b: PhysicsPose): boolean {\n\treturn (\n\t\ta.position.x === b.position.x &&\n\t\ta.position.y === b.position.y &&\n\t\ta.position.z === b.position.z &&\n\t\ta.rotation.x === b.rotation.x &&\n\t\ta.rotation.y === b.rotation.y &&\n\t\ta.rotation.z === b.rotation.z &&\n\t\ta.rotation.w === b.rotation.w\n\t);\n}\n","import type { BodyCommand } from './physics-protocol';\nimport {\n\tcreatePhysicsPose,\n\tinterpolatePhysicsPose,\n\ttype PhysicsPose,\n\ttype PhysicsPoseHistory,\n\ttype PhysicsQuaternion,\n\ttype PhysicsVector3,\n} from './physics-pose';\n\n/**\n * Lightweight read-only view of a physics body's state.\n *\n * These values are synced from the worker each frame and represent\n * the body's state after the latest physics step.\n */\nexport interface PhysicsSnapshot {\n\tprevious: PhysicsPose;\n\tcurrent: PhysicsPose;\n\tlinvel: { x: number; y: number; z: number };\n\tangvel: { x: number; y: number; z: number };\n}\n\n/**\n * Main-thread handle for a physics body that lives in a Web Worker.\n *\n * Provides the same read interface as a Rapier RigidBody (translation,\n * rotation, linvel, angvel) by returning cached values that are synced\n * from the worker each frame.\n *\n * Write operations (setLinvel, setTranslation, etc.) are queued as\n * {@link BodyCommand}s and sent to the worker on the next step.\n */\nexport class PhysicsBodyHandle {\n\treadonly uuid: string;\n\n\t/** Last-known physics state, updated from worker each frame. */\n\tprivate _snapshot: PhysicsSnapshot = {\n\t\tprevious: createPhysicsPose(),\n\t\tcurrent: createPhysicsPose(),\n\t\tlinvel: { x: 0, y: 0, z: 0 },\n\t\tangvel: { x: 0, y: 0, z: 0 },\n\t};\n\n\t/** Queued commands to be sent to the worker on next step. */\n\tprivate _pendingCommands: BodyCommand[] = [];\n\n\t/** Optional reference to the proxy's shared command queue. */\n\tprivate _sharedQueue: BodyCommand[] | null = null;\n\n\tconstructor(uuid: string, sharedQueue?: BodyCommand[]) {\n\t\tthis.uuid = uuid;\n\t\tthis._sharedQueue = sharedQueue ?? null;\n\t}\n\n\t// ─── Read API (returns cached values) ────────────────────────────────\n\n\t/** Cached position from last physics step. */\n\ttranslation(): { x: number; y: number; z: number } {\n\t\treturn this._snapshot.current.position;\n\t}\n\n\t/** Cached rotation quaternion from last physics step. */\n\trotation(): { x: number; y: number; z: number; w: number } {\n\t\treturn this._snapshot.current.rotation;\n\t}\n\n\t/** Cached linear velocity from last physics step. */\n\tlinvel(): { x: number; y: number; z: number } {\n\t\treturn this._snapshot.linvel;\n\t}\n\n\t/** Cached angular velocity from last physics step. */\n\tangvel(): { x: number; y: number; z: number } {\n\t\treturn this._snapshot.angvel;\n\t}\n\n\tgetPoseHistory(): PhysicsPoseHistory {\n\t\treturn this._snapshot;\n\t}\n\n\tgetRenderPose(alpha: number): PhysicsPose {\n\t\treturn interpolatePhysicsPose(\n\t\t\tthis._snapshot.previous,\n\t\t\tthis._snapshot.current,\n\t\t\talpha,\n\t\t);\n\t}\n\n\t// ─── Write API (queues commands) ─────────────────────────────────────\n\n\tsetLinvel(v: { x: number; y: number; z: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'setLinvel', uuid: this.uuid, x: v.x, y: v.y, z: v.z });\n\t\tthis._snapshot.linvel = { ...v };\n\t}\n\n\tsetAngvel(v: { x: number; y: number; z: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'setAngvel', uuid: this.uuid, x: v.x, y: v.y, z: v.z });\n\t\tthis._snapshot.angvel = { ...v };\n\t}\n\n\tsetTranslation(v: { x: number; y: number; z: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'setTranslation', uuid: this.uuid, x: v.x, y: v.y, z: v.z });\n\t\tthis.setCollapsedTranslation(v);\n\t}\n\n\tsetRotation(q: { x: number; y: number; z: number; w: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'setRotation', uuid: this.uuid, x: q.x, y: q.y, z: q.z, w: q.w });\n\t\tthis.setCollapsedRotation(q);\n\t}\n\n\tapplyImpulse(v: { x: number; y: number; z: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'applyImpulse', uuid: this.uuid, x: v.x, y: v.y, z: v.z });\n\t}\n\n\tapplyTorqueImpulse(v: { x: number; y: number; z: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'applyTorqueImpulse', uuid: this.uuid, x: v.x, y: v.y, z: v.z });\n\t}\n\n\tlockTranslations(locked: boolean, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'lockTranslations', uuid: this.uuid, locked });\n\t}\n\n\tlockRotations(locked: boolean, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'lockRotations', uuid: this.uuid, locked });\n\t}\n\n\tsetLinearDamping(damping: number): void {\n\t\tthis.enqueue({ kind: 'setLinearDamping', uuid: this.uuid, damping });\n\t}\n\n\tsetGravityScale(scale: number, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'setGravityScale', uuid: this.uuid, scale });\n\t}\n\n\t// ─── Stubbed read-only methods for compatibility ─────────────────────\n\n\t/** Returns 'Dynamic' for compatibility; actual type is not synced. */\n\tbodyType(): number {\n\t\treturn 0;\n\t}\n\n\tmass(): number {\n\t\treturn 1;\n\t}\n\n\tisEnabled(): boolean {\n\t\treturn true;\n\t}\n\n\tisSleeping(): boolean {\n\t\treturn false;\n\t}\n\n\t/** Collider access is not available through the handle. Returns null. */\n\tcollider(_index: number): null {\n\t\treturn null;\n\t}\n\n\t// ─── Internal ────────────────────────────────────────────────────────\n\n\t/**\n\t * Update the cached snapshot from worker data.\n\t * Called by the PhysicsProxy after receiving a stepResult.\n\t */\n\t_seedSnapshot(\n\t\tpx: number,\n\t\tpy: number,\n\t\tpz: number,\n\t\trx: number,\n\t\try: number,\n\t\trz: number,\n\t\trw: number,\n\t\tlvx: number,\n\t\tlvy: number,\n\t\tlvz: number,\n\t\tavx: number,\n\t\tavy: number,\n\t\tavz: number,\n\t): void {\n\t\tthis.writePose(this._snapshot.previous, px, py, pz, rx, ry, rz, rw);\n\t\tthis.writePose(this._snapshot.current, px, py, pz, rx, ry, rz, rw);\n\t\tthis._snapshot.linvel.x = lvx;\n\t\tthis._snapshot.linvel.y = lvy;\n\t\tthis._snapshot.linvel.z = lvz;\n\t\tthis._snapshot.angvel.x = avx;\n\t\tthis._snapshot.angvel.y = avy;\n\t\tthis._snapshot.angvel.z = avz;\n\t}\n\n\t_updateSnapshot(\n\t\tpx: number, py: number, pz: number,\n\t\trx: number, ry: number, rz: number, rw: number,\n\t\tlvx: number, lvy: number, lvz: number,\n\t\tavx: number, avy: number, avz: number,\n\t): void {\n\t\tthis.copyPose(this._snapshot.current, this._snapshot.previous);\n\t\tthis.writePose(this._snapshot.current, px, py, pz, rx, ry, rz, rw);\n\t\tthis._snapshot.linvel.x = lvx;\n\t\tthis._snapshot.linvel.y = lvy;\n\t\tthis._snapshot.linvel.z = lvz;\n\t\tthis._snapshot.angvel.x = avx;\n\t\tthis._snapshot.angvel.y = avy;\n\t\tthis._snapshot.angvel.z = avz;\n\t}\n\n\t/** Drain pending commands. */\n\t_drainCommands(): BodyCommand[] {\n\t\tconst cmds = this._pendingCommands;\n\t\tthis._pendingCommands = [];\n\t\treturn cmds;\n\t}\n\n\tprivate enqueue(cmd: BodyCommand): void {\n\t\tif (this._sharedQueue) {\n\t\t\tthis._sharedQueue.push(cmd);\n\t\t} else {\n\t\t\tthis._pendingCommands.push(cmd);\n\t\t}\n\t}\n\n\tprivate copyPose(source: PhysicsPose, target: PhysicsPose): void {\n\t\ttarget.position.x = source.position.x;\n\t\ttarget.position.y = source.position.y;\n\t\ttarget.position.z = source.position.z;\n\t\ttarget.rotation.x = source.rotation.x;\n\t\ttarget.rotation.y = source.rotation.y;\n\t\ttarget.rotation.z = source.rotation.z;\n\t\ttarget.rotation.w = source.rotation.w;\n\t}\n\n\tprivate writePose(\n\t\ttarget: PhysicsPose,\n\t\tpx: number,\n\t\tpy: number,\n\t\tpz: number,\n\t\trx: number,\n\t\try: number,\n\t\trz: number,\n\t\trw: number,\n\t): void {\n\t\ttarget.position.x = px;\n\t\ttarget.position.y = py;\n\t\ttarget.position.z = pz;\n\t\ttarget.rotation.x = rx;\n\t\ttarget.rotation.y = ry;\n\t\ttarget.rotation.z = rz;\n\t\ttarget.rotation.w = rw;\n\t}\n\n\tprivate setCollapsedTranslation(translation: PhysicsVector3): void {\n\t\tthis._snapshot.previous.position.x = translation.x;\n\t\tthis._snapshot.previous.position.y = translation.y;\n\t\tthis._snapshot.previous.position.z = translation.z;\n\t\tthis._snapshot.current.position.x = translation.x;\n\t\tthis._snapshot.current.position.y = translation.y;\n\t\tthis._snapshot.current.position.z = translation.z;\n\t}\n\n\tprivate setCollapsedRotation(rotation: PhysicsQuaternion): void {\n\t\tthis._snapshot.previous.rotation.x = rotation.x;\n\t\tthis._snapshot.previous.rotation.y = rotation.y;\n\t\tthis._snapshot.previous.rotation.z = rotation.z;\n\t\tthis._snapshot.previous.rotation.w = rotation.w;\n\t\tthis._snapshot.current.rotation.x = rotation.x;\n\t\tthis._snapshot.current.rotation.y = rotation.y;\n\t\tthis._snapshot.current.rotation.z = rotation.z;\n\t\tthis._snapshot.current.rotation.w = rotation.w;\n\t}\n}\n","import type {\n\tPhysicsCommand,\n\tPhysicsEvent,\n\tPhysicsStepResultEvent,\n\tPhysicsAddBodyCommand,\n\tBodyCommand,\n\tCollisionPair,\n\tSerializableBodyDesc,\n\tSerializableColliderDesc,\n\tSerializableCharacterController,\n} from './physics-protocol';\nimport { FLOATS_PER_BODY, TransformOffset } from './physics-protocol';\nimport { PhysicsBodyHandle } from './physics-body-handle';\n\n/**\n * Callback signature for collision events dispatched by the proxy.\n */\nexport type CollisionCallback = (pair: CollisionPair) => void;\n\n/**\n * Main-thread proxy that communicates with the physics Web Worker.\n *\n * Usage:\n * ```ts\n * const proxy = new PhysicsProxy();\n * await proxy.init([0, -9.81, 0], 60);\n * const handle = proxy.addBody(uuid, bodyDesc, colliderDescs);\n * // each frame:\n * await proxy.step(delta);\n * ```\n *\n * The proxy owns the worker lifecycle and manages body handles.\n * After each step, all handles are updated with fresh transform data\n * and collision callbacks are fired.\n */\nexport class PhysicsProxy {\n\tprivate worker: Worker | null = null;\n\tprivate handles = new Map<string, PhysicsBodyHandle>();\n\tprivate commandQueue: BodyCommand[] = [];\n\tprivate collisionListeners: CollisionCallback[] = [];\n\tprivate pendingStep: {\n\t\tresolve: (result: PhysicsStepResultEvent) => void;\n\t\treject: (err: Error) => void;\n\t} | null = null;\n\n\t/** Latest interpolation alpha from the worker (0..1). */\n\tinterpolationAlpha = 0;\n\n\t/**\n\t * Spawn the worker and initialize the Rapier world inside it.\n\t * Resolves when the worker reports `ready`.\n\t *\n\t * @param gravity World gravity as [x, y, z].\n\t * @param physicsRate Physics tick rate in Hz (default 60).\n\t * @param workerUrl URL to the physics worker script. The consuming\n\t * application must provide this because bundlers (Vite, Webpack)\n\t * can only resolve worker URLs from application source code.\n\t * Example for Vite:\n\t * ```ts\n\t * new URL('@zylem/game-lib/dist/physics-worker.js', import.meta.url)\n\t * ```\n\t */\n\tasync init(\n\t\tgravity: [number, number, number],\n\t\tphysicsRate = 60,\n\t\tworkerUrl?: URL,\n\t): Promise<void> {\n\t\tif (!workerUrl) {\n\t\t\tthrow new Error(\n\t\t\t\t'[PhysicsProxy] workerUrl is required. Provide physicsWorkerUrl in your stage config.\\n' +\n\t\t\t\t'For Vite: physicsWorkerUrl: new URL(\"@zylem/game-lib/dist/physics-worker.js\", import.meta.url)'\n\t\t\t);\n\t\t}\n\t\tthis.worker = new Worker(workerUrl, { type: 'module' });\n\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tconst onMessage = (e: MessageEvent<PhysicsEvent>) => {\n\t\t\t\tif (e.data.type === 'ready') {\n\t\t\t\t\tthis.worker!.removeEventListener('message', onMessage);\n\t\t\t\t\tthis.worker!.addEventListener('message', this.onWorkerMessage.bind(this));\n\t\t\t\t\tresolve();\n\t\t\t\t} else if (e.data.type === 'error') {\n\t\t\t\t\treject(new Error(e.data.message));\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.worker!.addEventListener('message', onMessage);\n\n\t\t\tthis.send({ type: 'init', gravity, physicsRate });\n\t\t});\n\t}\n\n\t/**\n\t * Register a body in the worker and return a main-thread handle.\n\t *\n\t * @returns A {@link PhysicsBodyHandle} for reading cached transforms\n\t * and queuing write commands.\n\t */\n\taddBody(\n\t\tuuid: string,\n\t\tbody: SerializableBodyDesc,\n\t\tcolliders: SerializableColliderDesc[],\n\t\tcharacterController?: SerializableCharacterController,\n\t): PhysicsBodyHandle {\n\t\tconst cmd: PhysicsAddBodyCommand = {\n\t\t\ttype: 'addBody',\n\t\t\tuuid,\n\t\t\tbody,\n\t\t\tcolliders,\n\t\t\tcharacterController,\n\t\t};\n\t\tthis.send(cmd);\n\n\t\tconst handle = new PhysicsBodyHandle(uuid, this.commandQueue);\n\t\thandle._seedSnapshot(\n\t\t\tbody.translation[0], body.translation[1], body.translation[2],\n\t\t\t0, 0, 0, 1,\n\t\t\t0, 0, 0,\n\t\t\t0, 0, 0,\n\t\t);\n\t\tthis.handles.set(uuid, handle);\n\t\treturn handle;\n\t}\n\n\t/** Remove a body from the worker and discard its handle. */\n\tremoveBody(uuid: string): void {\n\t\tthis.send({ type: 'removeBody', uuid });\n\t\tthis.handles.delete(uuid);\n\t}\n\n\t/** Get a body handle by entity UUID. */\n\tgetHandle(uuid: string): PhysicsBodyHandle | undefined {\n\t\treturn this.handles.get(uuid);\n\t}\n\n\t/**\n\t * Send a step command to the worker with the current frame delta\n\t * and all queued body commands.\n\t *\n\t * Returns a promise that resolves after the worker replies with\n\t * the step result. Handles are updated and collision callbacks\n\t * are fired before the promise resolves.\n\t */\n\tstep(delta: number): Promise<PhysicsStepResultEvent> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.pendingStep = { resolve, reject };\n\n\t\t\tconst commands = this.commandQueue.splice(0);\n\n\t\t\tfor (const handle of this.handles.values()) {\n\t\t\t\tcommands.push(...handle._drainCommands());\n\t\t\t}\n\n\t\t\tthis.send({ type: 'step', delta, commands });\n\t\t});\n\t}\n\n\t/**\n\t * Subscribe to collision events.\n\t * @returns Unsubscribe function.\n\t */\n\tonCollision(callback: CollisionCallback): () => void {\n\t\tthis.collisionListeners.push(callback);\n\t\treturn () => {\n\t\t\tthis.collisionListeners = this.collisionListeners.filter((cb) => cb !== callback);\n\t\t};\n\t}\n\n\t/** Terminate the worker and release all handles. */\n\tdispose(): void {\n\t\tif (this.worker) {\n\t\t\tthis.send({ type: 'dispose' });\n\t\t\tthis.worker.terminate();\n\t\t\tthis.worker = null;\n\t\t}\n\t\tthis.handles.clear();\n\t\tthis.commandQueue.length = 0;\n\t\tthis.collisionListeners.length = 0;\n\t\tthis.pendingStep = null;\n\t}\n\n\t// ─── Internal ────────────────────────────────────────────────────────\n\n\tprivate send(cmd: PhysicsCommand): void {\n\t\tthis.worker?.postMessage(cmd);\n\t}\n\n\tprivate onWorkerMessage(e: MessageEvent<PhysicsEvent>): void {\n\t\tconst event = e.data;\n\n\t\tswitch (event.type) {\n\t\t\tcase 'stepResult':\n\t\t\t\tthis.applyStepResult(event);\n\t\t\t\tbreak;\n\t\t\tcase 'error':\n\t\t\t\tif (this.pendingStep) {\n\t\t\t\t\tthis.pendingStep.reject(new Error(event.message));\n\t\t\t\t\tthis.pendingStep = null;\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('[PhysicsProxy] Worker error:', event.message);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate applyStepResult(result: PhysicsStepResultEvent): void {\n\t\tconst { transforms, bodyOrder, collisions, interpolationAlpha } = result;\n\t\tthis.interpolationAlpha = interpolationAlpha;\n\n\t\tfor (let i = 0; i < bodyOrder.length; i++) {\n\t\t\tconst handle = this.handles.get(bodyOrder[i]);\n\t\t\tif (!handle) continue;\n\n\t\t\tconst o = i * FLOATS_PER_BODY;\n\t\t\thandle._updateSnapshot(\n\t\t\t\ttransforms[o + TransformOffset.POS_X],\n\t\t\t\ttransforms[o + TransformOffset.POS_Y],\n\t\t\t\ttransforms[o + TransformOffset.POS_Z],\n\t\t\t\ttransforms[o + TransformOffset.ROT_X],\n\t\t\t\ttransforms[o + TransformOffset.ROT_Y],\n\t\t\t\ttransforms[o + TransformOffset.ROT_Z],\n\t\t\t\ttransforms[o + TransformOffset.ROT_W],\n\t\t\t\ttransforms[o + TransformOffset.LINVEL_X],\n\t\t\t\ttransforms[o + TransformOffset.LINVEL_Y],\n\t\t\t\ttransforms[o + TransformOffset.LINVEL_Z],\n\t\t\t\ttransforms[o + TransformOffset.ANGVEL_X],\n\t\t\t\ttransforms[o + TransformOffset.ANGVEL_Y],\n\t\t\t\ttransforms[o + TransformOffset.ANGVEL_Z],\n\t\t\t);\n\t\t}\n\n\t\tfor (const pair of collisions) {\n\t\t\tfor (const listener of this.collisionListeners) {\n\t\t\t\ttry {\n\t\t\t\t\tlistener(pair);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error('[PhysicsProxy] Collision listener error:', err);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.pendingStep) {\n\t\t\tthis.pendingStep.resolve(result);\n\t\t\tthis.pendingStep = null;\n\t\t}\n\t}\n}\n","import type { RigidBodyDesc, ColliderDesc } from '@dimforge/rapier3d-compat';\nimport { RigidBodyType } from '@dimforge/rapier3d-compat';\nimport type {\n\tSerializableBodyDesc,\n\tSerializableBodyType,\n\tSerializableColliderDesc,\n\tColliderShapeKind,\n\tSerializableCharacterController,\n} from './physics-protocol';\n\n/**\n * Convert a Rapier RigidBodyDesc to a plain serializable object.\n *\n * Rapier descriptors are WASM-backed class instances that cannot cross\n * the postMessage boundary. This extracts the relevant data into a\n * JSON-safe format that the worker can reconstruct.\n */\nexport function serializeBodyDesc(desc: RigidBodyDesc): SerializableBodyDesc {\n\tconst status = (desc as any).status as number;\n\tlet type: SerializableBodyType = 'dynamic';\n\tif (status === RigidBodyType.Fixed) type = 'fixed';\n\telse if (status === RigidBodyType.KinematicPositionBased) type = 'kinematicPositionBased';\n\telse if (status === RigidBodyType.KinematicVelocityBased) type = 'kinematicVelocityBased';\n\n\tconst t = (desc as any).translation ?? { x: 0, y: 0, z: 0 };\n\n\treturn {\n\t\ttype,\n\t\ttranslation: [t.x ?? 0, t.y ?? 0, t.z ?? 0],\n\t\tgravityScale: (desc as any).gravityScale ?? 1,\n\t\tcanSleep: (desc as any).canSleep ?? false,\n\t\tccdEnabled: (desc as any).ccdEnabled ?? true,\n\t};\n}\n\n/**\n * Convert a Rapier ColliderDesc to a plain serializable object.\n *\n * Because Rapier's ColliderDesc uses opaque shape enums and internal\n * buffers, we infer the shape from the descriptor's internal type tag\n * and extract the numeric dimensions.\n */\nexport function serializeColliderDesc(desc: ColliderDesc): SerializableColliderDesc {\n\tconst internal = desc as any;\n\tconst customShapeData = internal.__zylemShapeData as\n\t\t| { shape: 'trimesh'; vertices: number[]; indices: number[] }\n\t\t| undefined;\n\tif (customShapeData?.shape === 'trimesh') {\n\t\tconst result: SerializableColliderDesc = {\n\t\t\tshape: 'trimesh',\n\t\t\tdimensions: [],\n\t\t\tvertices: [...customShapeData.vertices],\n\t\t\tindices: [...customShapeData.indices],\n\t\t};\n\n\t\tconst translation = internal.translation;\n\t\tif (\n\t\t\ttranslation\n\t\t\t&& (translation.x !== 0 || translation.y !== 0 || translation.z !== 0)\n\t\t) {\n\t\t\tresult.translation = [translation.x, translation.y, translation.z];\n\t\t}\n\n\t\tif (internal.isSensor) {\n\t\t\tresult.sensor = true;\n\t\t}\n\n\t\tif (internal.collisionGroups !== undefined && internal.collisionGroups !== 0xFFFFFFFF) {\n\t\t\tresult.collisionGroups = internal.collisionGroups;\n\t\t}\n\n\t\tif (internal.activeCollisionTypes !== undefined) {\n\t\t\tresult.activeCollisionTypes = internal.activeCollisionTypes;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tconst shapeType = internal.shape?.type ?? internal.shapeType ?? 0;\n\n\tconst { shape, dimensions, heightfieldMeta } = extractShapeData(shapeType, internal);\n\n\tconst result: SerializableColliderDesc = {\n\t\tshape,\n\t\tdimensions,\n\t};\n\n\tconst t = internal.translation;\n\tif (t && (t.x !== 0 || t.y !== 0 || t.z !== 0)) {\n\t\tresult.translation = [t.x, t.y, t.z];\n\t}\n\n\tif (internal.isSensor) {\n\t\tresult.sensor = true;\n\t}\n\n\tif (internal.collisionGroups !== undefined && internal.collisionGroups !== 0xFFFFFFFF) {\n\t\tresult.collisionGroups = internal.collisionGroups;\n\t}\n\n\tif (internal.activeCollisionTypes !== undefined) {\n\t\tresult.activeCollisionTypes = internal.activeCollisionTypes;\n\t}\n\n\tif (heightfieldMeta) {\n\t\tresult.heightfieldMeta = heightfieldMeta;\n\t}\n\n\treturn result;\n}\n\n/**\n * Create a serializable character controller descriptor.\n */\nexport function serializeCharacterController(): SerializableCharacterController {\n\treturn {\n\t\toffset: 0.01,\n\t\tmaxSlopeClimbAngle: 45 * Math.PI / 180,\n\t\tminSlopeSlideAngle: 30 * Math.PI / 180,\n\t\tsnapToGroundDistance: 0.01,\n\t\tslideEnabled: true,\n\t\tapplyImpulsesToDynamic: true,\n\t\tcharacterMass: 1,\n\t};\n}\n\n// ─── Shape Extraction ──────────────────────────────────────────────────────\n\n/**\n * Rapier shape type enum values (from rapier internals):\n * 0 = Ball, 1 = Cuboid, 2 = Capsule, 6 = Cone, 7 = Cylinder,\n * 11 = HeightField\n */\nfunction extractShapeData(\n\tshapeType: number,\n\tinternal: any,\n): { shape: ColliderShapeKind; dimensions: number[]; heightfieldMeta?: { nrows: number; ncols: number } } {\n\tswitch (shapeType) {\n\t\tcase 0: // Ball\n\t\t\treturn {\n\t\t\t\tshape: 'ball',\n\t\t\t\tdimensions: [internal.shape?.radius ?? internal.halfExtents?.x ?? 1],\n\t\t\t};\n\t\tcase 1: // Cuboid\n\t\t\treturn {\n\t\t\t\tshape: 'cuboid',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfExtents?.x ?? internal.halfExtents?.x ?? 0.5,\n\t\t\t\t\tinternal.shape?.halfExtents?.y ?? internal.halfExtents?.y ?? 0.5,\n\t\t\t\t\tinternal.shape?.halfExtents?.z ?? internal.halfExtents?.z ?? 0.5,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 2: // Capsule\n\t\t\treturn {\n\t\t\t\tshape: 'capsule',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 0.5,\n\t\t\t\t\tinternal.shape?.radius ?? 0.5,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 6: // Cone\n\t\t\treturn {\n\t\t\t\tshape: 'cone',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 1,\n\t\t\t\t\tinternal.shape?.radius ?? 1,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 7: // Cylinder\n\t\t\treturn {\n\t\t\t\tshape: 'cylinder',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 1,\n\t\t\t\t\tinternal.shape?.radius ?? 1,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 11: { // HeightField\n\t\t\tconst nrows = internal.shape?.nrows ?? 10;\n\t\t\tconst ncols = internal.shape?.ncols ?? 10;\n\t\t\tconst heights = internal.shape?.heights;\n\t\t\treturn {\n\t\t\t\tshape: 'heightfield',\n\t\t\t\tdimensions: heights ? Array.from(heights) : [],\n\t\t\t\theightfieldMeta: { nrows, ncols },\n\t\t\t};\n\t\t}\n\t\tdefault:\n\t\t\treturn { shape: 'cuboid', dimensions: [0.5, 0.5, 0.5] };\n\t}\n}\n"],"mappings":"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","names":["result"]}