@zylem/behaviors 0.4.0 → 0.5.1

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 (146) hide show
  1. package/README.md +13 -1
  2. package/dist/behavior-system-CeJXzNvr.d.ts +868 -0
  3. package/dist/{chunk-GFARAJV2.js → chunk-2PAHQZZD.js} +44 -73
  4. package/dist/chunk-2PAHQZZD.js.map +1 -0
  5. package/dist/chunk-52FJIDGL.js +30 -0
  6. package/dist/chunk-52FJIDGL.js.map +1 -0
  7. package/dist/{chunk-UYFOLI2X.js → chunk-5A5AYP2C.js} +1 -1
  8. package/dist/{chunk-UYFOLI2X.js.map → chunk-5A5AYP2C.js.map} +1 -1
  9. package/dist/{chunk-64HKCSXD.js → chunk-5EBIIYZD.js} +25 -45
  10. package/dist/chunk-5EBIIYZD.js.map +1 -0
  11. package/dist/{chunk-WXXXJ22R.js → chunk-5NJGASUJ.js} +87 -129
  12. package/dist/chunk-5NJGASUJ.js.map +1 -0
  13. package/dist/{chunk-XLUJDKCT.js → chunk-5UMCWV5A.js} +24 -15
  14. package/dist/chunk-5UMCWV5A.js.map +1 -0
  15. package/dist/chunk-5WRI5ZAA.js +31 -0
  16. package/dist/chunk-5WRI5ZAA.js.map +1 -0
  17. package/dist/{chunk-5SM5SH5O.js → chunk-7JLWZXPA.js} +2 -2
  18. package/dist/{chunk-HNESASBB.js → chunk-AEBDZWCP.js} +19 -28
  19. package/dist/chunk-AEBDZWCP.js.map +1 -0
  20. package/dist/chunk-AS3HR7AS.js +188 -0
  21. package/dist/chunk-AS3HR7AS.js.map +1 -0
  22. package/dist/chunk-E4X4YJZB.js +841 -0
  23. package/dist/chunk-E4X4YJZB.js.map +1 -0
  24. package/dist/{chunk-PWF757B6.js → chunk-F6ESSHQK.js} +19 -25
  25. package/dist/chunk-F6ESSHQK.js.map +1 -0
  26. package/dist/chunk-GQAPBNGT.js +210 -0
  27. package/dist/chunk-GQAPBNGT.js.map +1 -0
  28. package/dist/chunk-JGXRQUTC.js +191 -0
  29. package/dist/chunk-JGXRQUTC.js.map +1 -0
  30. package/dist/{chunk-BXP4K7RF.js → chunk-JVADRLWX.js} +57 -186
  31. package/dist/chunk-JVADRLWX.js.map +1 -0
  32. package/dist/{chunk-ZA43LPRM.js → chunk-KIYUUSPK.js} +2 -2
  33. package/dist/{chunk-V74N7D6Q.js → chunk-KOWGILCN.js} +24 -15
  34. package/dist/chunk-KOWGILCN.js.map +1 -0
  35. package/dist/{chunk-WWVD5DR5.js → chunk-M3QDKKDF.js} +2 -8
  36. package/dist/chunk-M3QDKKDF.js.map +1 -0
  37. package/dist/{chunk-FTDZAKZW.js → chunk-NQPYMUDF.js} +7 -5
  38. package/dist/{chunk-FTDZAKZW.js.map → chunk-NQPYMUDF.js.map} +1 -1
  39. package/dist/{chunk-XP3ASVGJ.js → chunk-NW4SE5XW.js} +2 -2
  40. package/dist/{chunk-KDY5N6J4.js → chunk-OPZ2LVS2.js} +1 -22
  41. package/dist/{chunk-KDY5N6J4.js.map → chunk-OPZ2LVS2.js.map} +1 -1
  42. package/dist/{chunk-5XZWTFGF.js → chunk-PLIXVF7B.js} +3 -3
  43. package/dist/chunk-PLIXVF7B.js.map +1 -0
  44. package/dist/{chunk-Y7YIAWPW.js → chunk-SGHIGTVZ.js} +1 -11
  45. package/dist/{chunk-Y7YIAWPW.js.map → chunk-SGHIGTVZ.js.map} +1 -1
  46. package/dist/{chunk-UL6Q5HDP.js → chunk-TBUKJKY6.js} +3 -25
  47. package/dist/chunk-TBUKJKY6.js.map +1 -0
  48. package/dist/chunk-VFDUKGRZ.js +155 -0
  49. package/dist/chunk-VFDUKGRZ.js.map +1 -0
  50. package/dist/chunk-VT3H43QA.js +288 -0
  51. package/dist/chunk-VT3H43QA.js.map +1 -0
  52. package/dist/chunk-W26PHBME.js +309 -0
  53. package/dist/chunk-W26PHBME.js.map +1 -0
  54. package/dist/components-BANNjAZP.d.ts +30 -0
  55. package/dist/cooldown.d.ts +2 -2
  56. package/dist/cooldown.js +1 -0
  57. package/dist/coordinators/boundary-ricochet-3d.d.ts +4 -4
  58. package/dist/coordinators/boundary-ricochet-3d.js +1 -0
  59. package/dist/coordinators/boundary-ricochet.d.ts +4 -4
  60. package/dist/coordinators/boundary-ricochet.js +3 -2
  61. package/dist/coordinators/first-person-shooter.js +1 -0
  62. package/dist/coordinators/multidirectional-space-shooter.d.ts +3 -3
  63. package/dist/coordinators/multidirectional-space-shooter.js +5 -3
  64. package/dist/coordinators/top-down-shooter.d.ts +3 -3
  65. package/dist/coordinators/top-down-shooter.js +5 -3
  66. package/dist/core.d.ts +288 -8
  67. package/dist/core.js +492 -19
  68. package/dist/core.js.map +1 -1
  69. package/dist/destructible-3d.d.ts +32 -4
  70. package/dist/destructible-3d.js +2 -1
  71. package/dist/destructible-prebake.js +1 -0
  72. package/dist/{entity-types-CmtQ-IBp.d.ts → entity-types-DhfsZbSK.d.ts} +5 -3
  73. package/dist/first-person.d.ts +27 -38
  74. package/dist/first-person.js +8 -7
  75. package/dist/index.d.ts +14 -15
  76. package/dist/index.js +37 -52
  77. package/dist/jumper-2d.d.ts +3 -17
  78. package/dist/jumper-2d.js +4 -8
  79. package/dist/jumper-3d.d.ts +5 -39
  80. package/dist/jumper-3d.js +5 -9
  81. package/dist/{moveable-BLTHO7Jq.d.ts → moveable-XhzWPAw5.d.ts} +21 -4
  82. package/dist/particle-emitter/presets.js +1 -0
  83. package/dist/particle-emitter.d.ts +3 -3
  84. package/dist/particle-emitter.js +3 -2
  85. package/dist/platformer-2d.d.ts +13 -82
  86. package/dist/platformer-2d.js +4 -4
  87. package/dist/platformer-3d.d.ts +13 -78
  88. package/dist/platformer-3d.js +4 -4
  89. package/dist/ricochet-2d.d.ts +3 -3
  90. package/dist/ricochet-2d.js +4 -3
  91. package/dist/ricochet-3d.d.ts +3 -3
  92. package/dist/ricochet-3d.js +4 -3
  93. package/dist/runtime-2d.d.ts +2 -2
  94. package/dist/runtime-2d.js +1 -0
  95. package/dist/runtime-2d.js.map +1 -1
  96. package/dist/screen-visibility.d.ts +2 -2
  97. package/dist/screen-visibility.js +1 -0
  98. package/dist/screen-wrap.d.ts +2 -2
  99. package/dist/screen-wrap.js +4 -3
  100. package/dist/shooter-2d.d.ts +3 -3
  101. package/dist/shooter-2d.js +4 -3
  102. package/dist/thruster.d.ts +5 -34
  103. package/dist/thruster.js +4 -6
  104. package/dist/top-down-movement.d.ts +9 -27
  105. package/dist/top-down-movement.js +6 -6
  106. package/dist/{vector-Bm65-FOG.d.ts → vector-DjhLUrak.d.ts} +2 -4
  107. package/dist/world-boundary-2d.d.ts +2 -2
  108. package/dist/world-boundary-2d.js +5 -4
  109. package/dist/world-boundary-3d.d.ts +2 -2
  110. package/dist/world-boundary-3d.js +4 -3
  111. package/package.json +4 -3
  112. package/dist/behavior-system-DSNek0W9.d.ts +0 -483
  113. package/dist/chunk-4URF65BR.js +0 -44
  114. package/dist/chunk-4URF65BR.js.map +0 -1
  115. package/dist/chunk-4V7TIRO2.js +0 -44
  116. package/dist/chunk-4V7TIRO2.js.map +0 -1
  117. package/dist/chunk-5XZWTFGF.js.map +0 -1
  118. package/dist/chunk-64HKCSXD.js.map +0 -1
  119. package/dist/chunk-BXP4K7RF.js.map +0 -1
  120. package/dist/chunk-FRJDQM23.js +0 -506
  121. package/dist/chunk-FRJDQM23.js.map +0 -1
  122. package/dist/chunk-GFARAJV2.js.map +0 -1
  123. package/dist/chunk-GTLA6LOJ.js +0 -400
  124. package/dist/chunk-GTLA6LOJ.js.map +0 -1
  125. package/dist/chunk-HNESASBB.js.map +0 -1
  126. package/dist/chunk-JXMF4NUI.js +0 -309
  127. package/dist/chunk-JXMF4NUI.js.map +0 -1
  128. package/dist/chunk-MJFMNRMZ.js +0 -240
  129. package/dist/chunk-MJFMNRMZ.js.map +0 -1
  130. package/dist/chunk-OTLSUYQQ.js +0 -29
  131. package/dist/chunk-OTLSUYQQ.js.map +0 -1
  132. package/dist/chunk-PWF757B6.js.map +0 -1
  133. package/dist/chunk-RONH2KDI.js +0 -455
  134. package/dist/chunk-RONH2KDI.js.map +0 -1
  135. package/dist/chunk-RTRFJVCZ.js +0 -454
  136. package/dist/chunk-RTRFJVCZ.js.map +0 -1
  137. package/dist/chunk-UL6Q5HDP.js.map +0 -1
  138. package/dist/chunk-V74N7D6Q.js.map +0 -1
  139. package/dist/chunk-WWVD5DR5.js.map +0 -1
  140. package/dist/chunk-WXXXJ22R.js.map +0 -1
  141. package/dist/chunk-XLUJDKCT.js.map +0 -1
  142. package/dist/components-BWG1GkZA.d.ts +0 -20
  143. package/dist/use-behavior-h9-T5FSv.d.ts +0 -13
  144. /package/dist/{chunk-5SM5SH5O.js.map → chunk-7JLWZXPA.js.map} +0 -0
  145. /package/dist/{chunk-ZA43LPRM.js.map → chunk-KIYUUSPK.js.map} +0 -0
  146. /package/dist/{chunk-XP3ASVGJ.js.map → chunk-NW4SE5XW.js.map} +0 -0
@@ -0,0 +1,841 @@
1
+ // src/lib/runtime/wasm-stage-runtime.ts
2
+ import {
3
+ loadStageFfi,
4
+ STAGE_RENDER_STRIDE,
5
+ STAGE_INPUT_STRIDE,
6
+ STAGE_SNAPSHOT_STRIDE,
7
+ STAGE_EVENT_STRIDE
8
+ } from "@zylem/runtime";
9
+ var STAGE_INVALID_SLOT = 4294967295;
10
+ var StageBodyKind = {
11
+ Dynamic: 0,
12
+ Static: 1,
13
+ KinematicPosition: 2,
14
+ KinematicVelocity: 3
15
+ };
16
+ var StageBoundaryDim = {
17
+ Two: 2,
18
+ Three: 3
19
+ };
20
+ var StageRicochetDim = {
21
+ Two: 2,
22
+ Three: 3
23
+ };
24
+ var StageRicochetReflection = {
25
+ Mirror: 0,
26
+ Angled: 1
27
+ };
28
+ var StageTopDownPlane = {
29
+ Xy: 0,
30
+ Xz: 1
31
+ };
32
+ var StageEventType = {
33
+ CollisionStarted: 1,
34
+ CollisionStopped: 2,
35
+ BoundaryHit: 3,
36
+ Ricochet: 4,
37
+ RegionEntered: 5,
38
+ JumpStarted: 6,
39
+ Landed: 7,
40
+ Wrapped: 8,
41
+ CooldownFired: 9
42
+ };
43
+ var STAGE_INPUT_BUTTON_JUMP = 1;
44
+ var STAGE_INPUT_BUTTON_RUN = 2;
45
+ function readBehaviorSnapshot(ref) {
46
+ const backref = ref;
47
+ const wasmStage = backref.__wasmStage;
48
+ const handle = backref.__entity?.runtimeHandle ?? -1;
49
+ if (!wasmStage || handle < 0) return null;
50
+ return wasmStage.readSnapshot(handle);
51
+ }
52
+ function readStageRenderSlot(view, slot, out) {
53
+ const base = slot * STAGE_RENDER_STRIDE;
54
+ if (slot < 0 || base + STAGE_RENDER_STRIDE > view.length) {
55
+ return null;
56
+ }
57
+ const result = out ?? {
58
+ position: [0, 0, 0],
59
+ rotation: [0, 0, 0, 1],
60
+ scale: 1,
61
+ custom: [0, 0, 0, 0]
62
+ };
63
+ result.position[0] = view[base];
64
+ result.position[1] = view[base + 1];
65
+ result.position[2] = view[base + 2];
66
+ result.rotation[0] = view[base + 3];
67
+ result.rotation[1] = view[base + 4];
68
+ result.rotation[2] = view[base + 5];
69
+ result.rotation[3] = view[base + 6];
70
+ const scale = view[base + 7];
71
+ result.scale = scale === 0 ? 1 : scale;
72
+ result.custom[0] = view[base + 8];
73
+ result.custom[1] = view[base + 9];
74
+ result.custom[2] = view[base + 10];
75
+ result.custom[3] = view[base + 11];
76
+ return result;
77
+ }
78
+ var WasmStageRuntime = class {
79
+ exports;
80
+ memory;
81
+ renderView = new Float32Array(0);
82
+ inputView = new Float32Array(0);
83
+ snapshotView = new Float32Array(0);
84
+ eventView = new Float32Array(0);
85
+ poseView = new Float32Array(0);
86
+ vec3View = new Float32Array(0);
87
+ queryView = new Float32Array(0);
88
+ scratchView = new Float32Array(0);
89
+ constructor(exports, options = {}) {
90
+ this.exports = exports;
91
+ this.memory = exports.memory;
92
+ const capacity = Math.max(options.initialCapacity ?? 64, 8);
93
+ exports.zylem_stage_create(capacity);
94
+ if (options.gravity) {
95
+ exports.zylem_stage_set_gravity(
96
+ options.gravity[0],
97
+ options.gravity[1],
98
+ options.gravity[2]
99
+ );
100
+ }
101
+ this.refreshViews();
102
+ }
103
+ /** Recreate typed views over wasm memory. Call after step() or whenever memory may have grown. */
104
+ refreshViews() {
105
+ const buffer = this.memory.buffer;
106
+ const renderPtr = this.exports.zylem_stage_render_ptr();
107
+ const renderLen = this.exports.zylem_stage_render_len();
108
+ const inputPtr = this.exports.zylem_stage_input_ptr();
109
+ const inputLen = this.exports.zylem_stage_input_len();
110
+ const snapshotPtr = this.exports.zylem_stage_snapshot_ptr();
111
+ const snapshotLen = this.exports.zylem_stage_snapshot_len();
112
+ const eventPtr = this.exports.zylem_stage_event_ptr();
113
+ const eventLen = this.exports.zylem_stage_event_len();
114
+ const posePtr = this.exports.zylem_stage_pose_ptr();
115
+ const poseLen = this.exports.zylem_stage_pose_len();
116
+ const vec3Ptr = this.exports.zylem_stage_vec3_ptr();
117
+ const queryPtr = this.exports.zylem_stage_query_ptr();
118
+ const queryLen = this.exports.zylem_stage_query_len();
119
+ const scratchPtr = this.exports.zylem_stage_scratch_ptr();
120
+ const scratchCap = this.exports.zylem_stage_scratch_capacity();
121
+ this.renderView = renderLen > 0 ? new Float32Array(buffer, renderPtr, renderLen) : new Float32Array(0);
122
+ this.inputView = inputLen > 0 ? new Float32Array(buffer, inputPtr, inputLen) : new Float32Array(0);
123
+ this.snapshotView = snapshotLen > 0 ? new Float32Array(buffer, snapshotPtr, snapshotLen) : new Float32Array(0);
124
+ this.eventView = eventLen > 0 ? new Float32Array(buffer, eventPtr, eventLen) : new Float32Array(0);
125
+ this.poseView = poseLen > 0 ? new Float32Array(buffer, posePtr, poseLen) : new Float32Array(0);
126
+ this.vec3View = vec3Ptr !== 0 ? new Float32Array(buffer, vec3Ptr, 3) : new Float32Array(0);
127
+ this.queryView = queryLen > 0 ? new Float32Array(buffer, queryPtr, queryLen) : new Float32Array(0);
128
+ this.scratchView = scratchCap > 0 ? new Float32Array(buffer, scratchPtr, scratchCap) : new Float32Array(0);
129
+ }
130
+ /** Step the simulation by `dt` seconds. Refreshes views afterwards. */
131
+ step(dt) {
132
+ const active = this.exports.zylem_stage_step(dt);
133
+ this.refreshViews();
134
+ return active;
135
+ }
136
+ dispose() {
137
+ this.exports.zylem_stage_destroy();
138
+ }
139
+ get tickCount() {
140
+ return this.exports.zylem_stage_tick_count() >>> 0;
141
+ }
142
+ get activeCount() {
143
+ return this.exports.zylem_stage_active_count() >>> 0;
144
+ }
145
+ setGravity(x, y, z) {
146
+ this.exports.zylem_stage_set_gravity(x, y, z);
147
+ }
148
+ // ─── Entity lifecycle ───────────────────────────────────────────────
149
+ createEntity() {
150
+ const slot = this.exports.zylem_stage_create_entity() >>> 0;
151
+ this.refreshViews();
152
+ return slot;
153
+ }
154
+ destroyEntity(slot) {
155
+ return this.exports.zylem_stage_destroy_entity(slot) !== 0;
156
+ }
157
+ // ─── Body / collider attach ────────────────────────────────────────
158
+ attachBody(slot, config) {
159
+ const ok = this.exports.zylem_stage_attach_body(
160
+ slot,
161
+ config.kind,
162
+ config.position[0],
163
+ config.position[1],
164
+ config.position[2],
165
+ config.rotation[0],
166
+ config.rotation[1],
167
+ config.rotation[2],
168
+ config.rotation[3],
169
+ config.linearDamping,
170
+ config.angularDamping,
171
+ config.gravityScale,
172
+ config.canSleep ? 1 : 0,
173
+ config.ccdEnabled ? 1 : 0,
174
+ config.lockRotation[0] ? 1 : 0,
175
+ config.lockRotation[1] ? 1 : 0,
176
+ config.lockRotation[2] ? 1 : 0,
177
+ config.lockTranslation[0] ? 1 : 0,
178
+ config.lockTranslation[1] ? 1 : 0,
179
+ config.lockTranslation[2] ? 1 : 0
180
+ );
181
+ return ok !== 0;
182
+ }
183
+ addCollider(slot, config) {
184
+ const offset = config.offset;
185
+ const sensor = config.sensor ? 1 : 0;
186
+ const groups = config.collisionGroups >>> 0;
187
+ const friction = config.friction;
188
+ const restitution = config.restitution;
189
+ switch (config.shape.type) {
190
+ case "box": {
191
+ const [hx, hy, hz] = config.shape.halfExtents;
192
+ return this.exports.zylem_stage_add_collider_box(
193
+ slot,
194
+ hx,
195
+ hy,
196
+ hz,
197
+ offset[0],
198
+ offset[1],
199
+ offset[2],
200
+ friction,
201
+ restitution,
202
+ sensor,
203
+ groups
204
+ ) !== 0;
205
+ }
206
+ case "sphere": {
207
+ return this.exports.zylem_stage_add_collider_sphere(
208
+ slot,
209
+ config.shape.radius,
210
+ offset[0],
211
+ offset[1],
212
+ offset[2],
213
+ friction,
214
+ restitution,
215
+ sensor,
216
+ groups
217
+ ) !== 0;
218
+ }
219
+ case "capsule": {
220
+ return this.exports.zylem_stage_add_collider_capsule(
221
+ slot,
222
+ config.shape.halfHeight,
223
+ config.shape.radius,
224
+ offset[0],
225
+ offset[1],
226
+ offset[2],
227
+ friction,
228
+ restitution,
229
+ sensor,
230
+ groups
231
+ ) !== 0;
232
+ }
233
+ case "cylinder": {
234
+ return this.exports.zylem_stage_add_collider_cylinder(
235
+ slot,
236
+ config.shape.halfHeight,
237
+ config.shape.radius,
238
+ offset[0],
239
+ offset[1],
240
+ offset[2],
241
+ friction,
242
+ restitution,
243
+ sensor,
244
+ groups
245
+ ) !== 0;
246
+ }
247
+ case "cone": {
248
+ return this.exports.zylem_stage_add_collider_cone(
249
+ slot,
250
+ config.shape.halfHeight,
251
+ config.shape.radius,
252
+ offset[0],
253
+ offset[1],
254
+ offset[2],
255
+ friction,
256
+ restitution,
257
+ sensor,
258
+ groups
259
+ ) !== 0;
260
+ }
261
+ case "convexHull": {
262
+ const verts = config.shape.vertices;
263
+ if (verts.length % 3 !== 0) return false;
264
+ const offsetFloats = this.stageScratch(verts);
265
+ return this.exports.zylem_stage_add_collider_convex_hull(
266
+ slot,
267
+ offsetFloats,
268
+ verts.length / 3,
269
+ offset[0],
270
+ offset[1],
271
+ offset[2],
272
+ friction,
273
+ restitution,
274
+ sensor,
275
+ groups
276
+ ) !== 0;
277
+ }
278
+ case "trimesh": {
279
+ const verts = config.shape.vertices;
280
+ const indices = config.shape.indices;
281
+ if (verts.length % 3 !== 0 || indices.length % 3 !== 0) return false;
282
+ const vertOffset = this.stageScratch(verts);
283
+ const indexOffset = this.stageScratchIndices(indices, vertOffset + verts.length);
284
+ return this.exports.zylem_stage_add_collider_trimesh(
285
+ slot,
286
+ vertOffset,
287
+ verts.length / 3,
288
+ indexOffset,
289
+ indices.length,
290
+ offset[0],
291
+ offset[1],
292
+ offset[2],
293
+ friction,
294
+ restitution,
295
+ sensor,
296
+ groups
297
+ ) !== 0;
298
+ }
299
+ case "heightfield": {
300
+ const heights = config.shape.heights;
301
+ const heightOffset = this.stageScratch(heights);
302
+ return this.exports.zylem_stage_add_collider_heightfield(
303
+ slot,
304
+ config.shape.rows,
305
+ config.shape.cols,
306
+ config.shape.scale[0],
307
+ config.shape.scale[1],
308
+ config.shape.scale[2],
309
+ heightOffset,
310
+ offset[0],
311
+ offset[1],
312
+ offset[2],
313
+ friction,
314
+ restitution,
315
+ sensor,
316
+ groups
317
+ ) !== 0;
318
+ }
319
+ default: {
320
+ const _exhaustive = config.shape;
321
+ void _exhaustive;
322
+ return false;
323
+ }
324
+ }
325
+ }
326
+ stageScratch(values, baseOffset = 0) {
327
+ this.scratchView.set(values, baseOffset);
328
+ return baseOffset;
329
+ }
330
+ stageScratchIndices(indices, baseOffset) {
331
+ for (let i = 0; i < indices.length; i++) {
332
+ this.scratchView[baseOffset + i] = indices[i];
333
+ }
334
+ return baseOffset;
335
+ }
336
+ // ─── Pose / velocity ───────────────────────────────────────────────
337
+ getPose(slot, out) {
338
+ const ok = this.exports.zylem_stage_get_pose(slot) !== 0;
339
+ if (!ok) return null;
340
+ const v = this.poseView;
341
+ const result = out ?? {
342
+ position: [0, 0, 0],
343
+ rotation: [0, 0, 0, 1]
344
+ };
345
+ result.position[0] = v[0];
346
+ result.position[1] = v[1];
347
+ result.position[2] = v[2];
348
+ result.rotation[0] = v[3];
349
+ result.rotation[1] = v[4];
350
+ result.rotation[2] = v[5];
351
+ result.rotation[3] = v[6];
352
+ return result;
353
+ }
354
+ setPosition(slot, x, y, z) {
355
+ return this.exports.zylem_stage_set_position(slot, x, y, z) !== 0;
356
+ }
357
+ setRotation(slot, x, y, z, w) {
358
+ return this.exports.zylem_stage_set_rotation(slot, x, y, z, w) !== 0;
359
+ }
360
+ setLinearVelocity(slot, x, y, z) {
361
+ return this.exports.zylem_stage_set_linvel(slot, x, y, z) !== 0;
362
+ }
363
+ getLinearVelocity(slot, out) {
364
+ if (this.exports.zylem_stage_get_linvel(slot) === 0) return null;
365
+ const v = this.vec3View;
366
+ const result = out ?? [0, 0, 0];
367
+ result[0] = v[0];
368
+ result[1] = v[1];
369
+ result[2] = v[2];
370
+ return result;
371
+ }
372
+ setAngularVelocity(slot, x, y, z) {
373
+ return this.exports.zylem_stage_set_angvel(slot, x, y, z) !== 0;
374
+ }
375
+ getAngularVelocity(slot, out) {
376
+ if (this.exports.zylem_stage_get_angvel(slot) === 0) return null;
377
+ const v = this.vec3View;
378
+ const result = out ?? [0, 0, 0];
379
+ result[0] = v[0];
380
+ result[1] = v[1];
381
+ result[2] = v[2];
382
+ return result;
383
+ }
384
+ applyImpulse(slot, x, y, z) {
385
+ return this.exports.zylem_stage_apply_impulse(slot, x, y, z) !== 0;
386
+ }
387
+ // ─── Queries / diagnostics ─────────────────────────────────────────
388
+ /** Cast a ray against the physics world. Returns the closest hit or `null`. */
389
+ castRay(origin, dir, maxDistance, solidOnly = true) {
390
+ const hit = this.exports.zylem_stage_cast_ray(
391
+ origin[0],
392
+ origin[1],
393
+ origin[2],
394
+ dir[0],
395
+ dir[1],
396
+ dir[2],
397
+ maxDistance,
398
+ solidOnly ? 1 : 0
399
+ );
400
+ if (hit === 0) return null;
401
+ const v = this.queryView;
402
+ return {
403
+ slot: v[0] >>> 0,
404
+ distance: v[1],
405
+ normal: [v[2], v[3], v[4]]
406
+ };
407
+ }
408
+ /** Body introspection for debug tooling. */
409
+ getBodyInfo(slot) {
410
+ if (this.exports.zylem_stage_body_info(slot) === 0) return null;
411
+ const v = this.queryView;
412
+ return {
413
+ bodyType: v[0] | 0,
414
+ mass: v[1],
415
+ isSleeping: v[2] > 0.5,
416
+ isEnabled: v[3] > 0.5,
417
+ linearVelocity: [v[4], v[5], v[6]]
418
+ };
419
+ }
420
+ /** Wireframe debug render of every collider (all shapes). */
421
+ getDebugRender() {
422
+ const vertexCount = this.exports.zylem_stage_debug_render() >>> 0;
423
+ if (vertexCount === 0) return null;
424
+ const buffer = this.memory.buffer;
425
+ const vertices = new Float32Array(
426
+ buffer,
427
+ this.exports.zylem_stage_debug_vertices_ptr(),
428
+ this.exports.zylem_stage_debug_vertices_len()
429
+ );
430
+ const colors = new Float32Array(
431
+ buffer,
432
+ this.exports.zylem_stage_debug_colors_ptr(),
433
+ this.exports.zylem_stage_debug_colors_len()
434
+ );
435
+ return { vertices, colors };
436
+ }
437
+ // ─── Render / event reads ──────────────────────────────────────────
438
+ /** Read-only view over the render buffer; one slot occupies {@link STAGE_RENDER_STRIDE} floats. */
439
+ get render() {
440
+ return this.renderView;
441
+ }
442
+ get renderStride() {
443
+ return STAGE_RENDER_STRIDE;
444
+ }
445
+ /**
446
+ * Decode a single entity slot from the live render buffer. Convenience
447
+ * wrapper over {@link readStageRenderSlot} bound to this runtime's view.
448
+ */
449
+ readRenderSlot(slot, out) {
450
+ return readStageRenderSlot(this.renderView, slot, out);
451
+ }
452
+ /** Drain the wasm event buffer into a fresh array of typed events. */
453
+ drainEvents() {
454
+ const count = this.exports.zylem_stage_event_count() >>> 0;
455
+ if (count === 0) return [];
456
+ const view = this.eventView;
457
+ const events = new Array(count);
458
+ for (let i = 0; i < count; i++) {
459
+ const base = i * STAGE_EVENT_STRIDE;
460
+ const primaryRaw = view[base + 1];
461
+ const secondaryRaw = view[base + 2];
462
+ events[i] = {
463
+ type: view[base] | 0,
464
+ primarySlot: Number.isNaN(primaryRaw) ? null : primaryRaw >>> 0,
465
+ secondarySlot: Number.isNaN(secondaryRaw) ? null : secondaryRaw >>> 0,
466
+ payload: [view[base + 3], view[base + 4], view[base + 5]]
467
+ };
468
+ }
469
+ return events;
470
+ }
471
+ // ─── Batched input / snapshot buffers ─────────────────────────────
472
+ /** Writable view over the slot-indexed input buffer ({@link STAGE_INPUT_STRIDE} floats/slot). */
473
+ get input() {
474
+ return this.inputView;
475
+ }
476
+ get inputStride() {
477
+ return STAGE_INPUT_STRIDE;
478
+ }
479
+ /** Read-only view over the per-slot behavior snapshot buffer ({@link STAGE_SNAPSHOT_STRIDE} floats/slot). */
480
+ get snapshot() {
481
+ return this.snapshotView;
482
+ }
483
+ get snapshotStride() {
484
+ return STAGE_SNAPSHOT_STRIDE;
485
+ }
486
+ /**
487
+ * Write the primary movement axes for a slot into the batched input
488
+ * buffer and mark the slot dirty. Field-scoped (doesn't touch look
489
+ * deltas or buttons) so multiple behaviors composed on one entity can
490
+ * each write their part.
491
+ */
492
+ writeInputAxes(slot, axisA, axisB) {
493
+ const base = slot * STAGE_INPUT_STRIDE;
494
+ const view = this.inputView;
495
+ if (slot < 0 || base + STAGE_INPUT_STRIDE > view.length) return false;
496
+ view[base] = axisA;
497
+ view[base + 1] = axisB;
498
+ view[base + 7] = 1;
499
+ return true;
500
+ }
501
+ /** Write the look deltas (first-person yaw/pitch) for a slot. */
502
+ writeInputLook(slot, yawDelta, pitchDelta) {
503
+ const base = slot * STAGE_INPUT_STRIDE;
504
+ const view = this.inputView;
505
+ if (slot < 0 || base + STAGE_INPUT_STRIDE > view.length) return false;
506
+ view[base + 2] = yawDelta;
507
+ view[base + 3] = pitchDelta;
508
+ view[base + 7] = 1;
509
+ return true;
510
+ }
511
+ /** Write reserved input slots (thruster world-space vector X/Y). */
512
+ writeInputReserved(slot, reservedA, reservedB) {
513
+ const base = slot * STAGE_INPUT_STRIDE;
514
+ const view = this.inputView;
515
+ if (slot < 0 || base + STAGE_INPUT_STRIDE > view.length) return false;
516
+ view[base + 5] = reservedA;
517
+ view[base + 6] = reservedB;
518
+ view[base + 7] = 1;
519
+ return true;
520
+ }
521
+ /**
522
+ * Set or clear one button bit ({@link STAGE_INPUT_BUTTON_JUMP} /
523
+ * {@link STAGE_INPUT_BUTTON_RUN}) in a slot's input bitmask.
524
+ */
525
+ writeInputButton(slot, buttonMask, pressed) {
526
+ const base = slot * STAGE_INPUT_STRIDE;
527
+ const view = this.inputView;
528
+ if (slot < 0 || base + STAGE_INPUT_STRIDE > view.length) return false;
529
+ const current = view[base + 4] | 0;
530
+ view[base + 4] = pressed ? current | buttonMask : current & ~buttonMask;
531
+ view[base + 7] = 1;
532
+ return true;
533
+ }
534
+ /**
535
+ * Decode a slot's behavior snapshot from the buffer written at the end of
536
+ * the previous step. Returns `null` when the slot has no behavior data.
537
+ */
538
+ readSnapshot(slot, out) {
539
+ const base = slot * STAGE_SNAPSHOT_STRIDE;
540
+ const view = this.snapshotView;
541
+ if (slot < 0 || base + STAGE_SNAPSHOT_STRIDE > view.length) return null;
542
+ if (view[base + 7] === 0) return null;
543
+ const result = out ?? {
544
+ grounded: false,
545
+ fsmState: 0,
546
+ jumpCount: 0,
547
+ verticalVelocity: 0,
548
+ speed: 0,
549
+ yaw: 0,
550
+ pitch: 0
551
+ };
552
+ result.grounded = view[base] > 0.5;
553
+ result.fsmState = view[base + 1] | 0;
554
+ result.jumpCount = view[base + 2] | 0;
555
+ result.verticalVelocity = view[base + 3];
556
+ result.speed = view[base + 4];
557
+ result.yaw = view[base + 5];
558
+ result.pitch = view[base + 6];
559
+ return result;
560
+ }
561
+ // ─── Behavior helpers ─────────────────────────────────────────────
562
+ get queryScratch() {
563
+ return this.queryView;
564
+ }
565
+ attachCooldown(slot) {
566
+ return this.exports.zylem_stage_attach_cooldown(slot) !== 0;
567
+ }
568
+ registerCooldown(slot, id, durationSeconds, immediate = false) {
569
+ return this.exports.zylem_stage_cooldown_register(slot, id >>> 0, durationSeconds, immediate ? 1 : 0) !== 0;
570
+ }
571
+ fireCooldown(slot, id) {
572
+ return this.exports.zylem_stage_cooldown_fire(slot, id >>> 0) !== 0;
573
+ }
574
+ resetCooldown(slot, id) {
575
+ return this.exports.zylem_stage_cooldown_reset(slot, id >>> 0) !== 0;
576
+ }
577
+ cooldownRemaining(slot, id) {
578
+ return this.exports.zylem_stage_cooldown_remaining(slot, id >>> 0);
579
+ }
580
+ attachWorldBoundary(slot, dim, bounds) {
581
+ return this.exports.zylem_stage_attach_world_boundary(
582
+ slot,
583
+ dim,
584
+ bounds.top,
585
+ bounds.bottom,
586
+ bounds.left,
587
+ bounds.right,
588
+ bounds.front ?? 0,
589
+ bounds.back ?? 0,
590
+ bounds.padding ?? 0
591
+ ) !== 0;
592
+ }
593
+ queryWorldBoundary(slot) {
594
+ if (this.exports.zylem_stage_query_world_boundary(slot) === 0) return null;
595
+ const v = this.queryView;
596
+ return {
597
+ hits: v[0] | 0,
598
+ clamped: [v[1], v[2], v[3]]
599
+ };
600
+ }
601
+ attachScreenWrap(slot, opts) {
602
+ return this.exports.zylem_stage_attach_screen_wrap(
603
+ slot,
604
+ opts.width,
605
+ opts.height,
606
+ opts.centerX ?? 0,
607
+ opts.centerY ?? 0,
608
+ opts.edgeThreshold ?? 0
609
+ ) !== 0;
610
+ }
611
+ queryScreenWrap(slot) {
612
+ if (this.exports.zylem_stage_query_screen_wrap(slot) === 0) return null;
613
+ const v = this.queryView;
614
+ return { fsm: v[0] | 0, lastWrappedAxes: v[1] | 0 };
615
+ }
616
+ attachRicochet(slot, dim, opts) {
617
+ return this.exports.zylem_stage_attach_ricochet(
618
+ slot,
619
+ dim,
620
+ opts.minSpeed,
621
+ opts.maxSpeed,
622
+ opts.speedMultiplier,
623
+ opts.maxAngleDeg,
624
+ opts.reflectionMode
625
+ ) !== 0;
626
+ }
627
+ queryRicochet(slot) {
628
+ if (this.exports.zylem_stage_query_ricochet(slot) === 0) return null;
629
+ const v = this.queryView;
630
+ return { bounces: v[0] | 0, lastKind: v[1] | 0 };
631
+ }
632
+ attachThruster(slot, opts) {
633
+ return this.exports.zylem_stage_attach_thruster(
634
+ slot,
635
+ opts.maxSpeed,
636
+ opts.acceleration,
637
+ opts.turnRateRadPerSec,
638
+ opts.linearDamping
639
+ ) !== 0;
640
+ }
641
+ setThrusterInput(slot, thrust, turn, vectorX = 0, vectorY = 0) {
642
+ this.exports.zylem_stage_set_thruster_input(slot, thrust, turn, vectorX, vectorY);
643
+ }
644
+ queryThruster(slot) {
645
+ if (this.exports.zylem_stage_query_thruster(slot) === 0) return null;
646
+ const v = this.queryView;
647
+ return { headingRad: v[0], speed: v[1] };
648
+ }
649
+ attachTopDown(slot, opts) {
650
+ return this.exports.zylem_stage_attach_top_down(slot, opts.plane, opts.speed, opts.faceMovement ? 1 : 0) !== 0;
651
+ }
652
+ setTopDownInput(slot, axisA, axisB) {
653
+ this.exports.zylem_stage_set_top_down_input(slot, axisA, axisB);
654
+ }
655
+ attachJumper2D(slot, opts) {
656
+ return this.exports.zylem_stage_attach_jumper_2d(
657
+ slot,
658
+ opts.jumpForce,
659
+ opts.maxJumps >>> 0,
660
+ opts.jumpBufferTime,
661
+ opts.coyoteTime,
662
+ opts.gravity
663
+ ) !== 0;
664
+ }
665
+ setJumper2DInput(slot, jumpPressed) {
666
+ this.exports.zylem_stage_set_jumper_2d_input(slot, jumpPressed ? 1 : 0);
667
+ }
668
+ queryJumper2D(slot) {
669
+ if (this.exports.zylem_stage_query_jumper_2d(slot) === 0) return null;
670
+ const v = this.queryView;
671
+ return {
672
+ grounded: v[0] > 0.5,
673
+ jumpCount: v[1] | 0,
674
+ coyote: v[2],
675
+ jumpBuffer: v[3]
676
+ };
677
+ }
678
+ attachJumper3D(slot, opts) {
679
+ return this.exports.zylem_stage_attach_jumper_3d(
680
+ slot,
681
+ opts.jumpForce,
682
+ opts.maxJumps >>> 0,
683
+ opts.gravity,
684
+ opts.coyoteTime ?? 0.1,
685
+ opts.jumpBufferTime ?? 0.08
686
+ ) !== 0;
687
+ }
688
+ setJumper3DInput(slot, jump) {
689
+ this.exports.zylem_stage_set_jumper_3d_input(slot, jump ? 1 : 0);
690
+ }
691
+ queryJumper3D(slot) {
692
+ if (this.exports.zylem_stage_query_jumper_3d(slot) === 0) return null;
693
+ const v = this.queryView;
694
+ return { grounded: v[0] > 0.5, jumpCount: v[1] | 0, verticalVelocity: v[2] };
695
+ }
696
+ attachShooter2D(slot, opts) {
697
+ return this.exports.zylem_stage_attach_shooter_2d(
698
+ slot,
699
+ opts.fireRateHz,
700
+ opts.muzzleOffsetX,
701
+ opts.muzzleOffsetY,
702
+ opts.muzzleSpeed
703
+ ) !== 0;
704
+ }
705
+ fireShooter2D(slot, x, y, z, yaw) {
706
+ return this.exports.zylem_stage_shooter_2d_fire(slot, x, y, z, yaw) !== 0;
707
+ }
708
+ queryShooter2D(slot) {
709
+ if (this.exports.zylem_stage_query_shooter_2d(slot) === 0) return null;
710
+ const v = this.queryView;
711
+ return { cooldown: v[0], firedCount: v[1] | 0 };
712
+ }
713
+ attachPlatformer3D(slot, opts) {
714
+ return this.exports.zylem_stage_attach_platformer_3d(
715
+ slot,
716
+ opts.halfHeight,
717
+ opts.radius,
718
+ opts.walkSpeed,
719
+ opts.runSpeed,
720
+ opts.jumpForce,
721
+ opts.maxJumps >>> 0,
722
+ opts.gravity,
723
+ opts.coyoteTime ?? 0.1,
724
+ opts.jumpBufferTime ?? 0.1,
725
+ opts.jumpCutMultiplier ?? 0.5,
726
+ opts.multiJumpWindow ?? 0.15,
727
+ opts.slopeClimbAngle ?? 50,
728
+ opts.slopeSlideAngle ?? 40,
729
+ opts.autostepHeight ?? 0.3,
730
+ opts.autostepMinWidth ?? 0.1,
731
+ opts.snapToGroundDistance ?? 0.3,
732
+ opts.characterOffset ?? 0.05
733
+ ) !== 0;
734
+ }
735
+ setPlatformer3DInputAxes(slot, moveX, moveZ) {
736
+ this.exports.zylem_stage_set_platformer_3d_input_axes(slot, moveX, moveZ);
737
+ }
738
+ setPlatformer3DInputButtons(slot, jump, run) {
739
+ this.exports.zylem_stage_set_platformer_3d_input_buttons(slot, jump ? 1 : 0, run ? 1 : 0);
740
+ }
741
+ queryPlatformer3D(slot) {
742
+ if (this.exports.zylem_stage_query_platformer_3d(slot) === 0) return null;
743
+ const v = this.queryView;
744
+ return {
745
+ grounded: v[0] > 0.5,
746
+ jumpCount: v[1] | 0,
747
+ fsmState: v[2] | 0,
748
+ speed: v[3]
749
+ };
750
+ }
751
+ attachPlatformer2D(slot, opts) {
752
+ return this.exports.zylem_stage_attach_platformer_2d(
753
+ slot,
754
+ opts.halfHeight,
755
+ opts.radius,
756
+ opts.walkSpeed,
757
+ opts.runSpeed,
758
+ opts.jumpForce,
759
+ opts.maxJumps >>> 0,
760
+ opts.gravity,
761
+ opts.coyoteTime ?? 0.1,
762
+ opts.jumpBufferTime ?? 0.1,
763
+ opts.jumpCutMultiplier ?? 0.5,
764
+ opts.multiJumpWindow ?? 0.15,
765
+ opts.slopeClimbAngle ?? 50,
766
+ opts.slopeSlideAngle ?? 40,
767
+ opts.autostepHeight ?? 0.25,
768
+ opts.autostepMinWidth ?? 0.05,
769
+ opts.snapToGroundDistance ?? 0.2,
770
+ opts.characterOffset ?? 0.05
771
+ ) !== 0;
772
+ }
773
+ setPlatformer2DInputAxes(slot, moveX) {
774
+ this.exports.zylem_stage_set_platformer_2d_input_axes(slot, moveX);
775
+ }
776
+ setPlatformer2DInputButtons(slot, jump, run) {
777
+ this.exports.zylem_stage_set_platformer_2d_input_buttons(slot, jump ? 1 : 0, run ? 1 : 0);
778
+ }
779
+ queryPlatformer2D(slot) {
780
+ if (this.exports.zylem_stage_query_platformer_2d(slot) === 0) return null;
781
+ const v = this.queryView;
782
+ return {
783
+ grounded: v[0] > 0.5,
784
+ jumpCount: v[1] | 0,
785
+ fsmState: v[2] | 0,
786
+ verticalVelocity: v[3]
787
+ };
788
+ }
789
+ attachFirstPerson(slot, opts) {
790
+ return this.exports.zylem_stage_attach_first_person(
791
+ slot,
792
+ opts.walkSpeed,
793
+ opts.runSpeed,
794
+ opts.eyeHeight,
795
+ opts.lookSensitivity
796
+ ) !== 0;
797
+ }
798
+ setFirstPersonInput(slot, input) {
799
+ this.exports.zylem_stage_set_first_person_input(
800
+ slot,
801
+ input.moveX,
802
+ input.moveZ,
803
+ input.lookYawDelta,
804
+ input.lookPitchDelta,
805
+ input.run ? 1 : 0
806
+ );
807
+ }
808
+ queryFirstPerson(slot) {
809
+ if (this.exports.zylem_stage_query_first_person(slot) === 0) return null;
810
+ const v = this.queryView;
811
+ return { yaw: v[0], pitch: v[1], speed: v[2], eyeHeight: v[3] };
812
+ }
813
+ };
814
+ async function createWasmStageRuntime(options = {}) {
815
+ const { exports } = await loadStageFfi({
816
+ source: options.source,
817
+ imports: options.imports
818
+ });
819
+ return new WasmStageRuntime(exports, options);
820
+ }
821
+
822
+ export {
823
+ STAGE_RENDER_STRIDE,
824
+ STAGE_INPUT_STRIDE,
825
+ STAGE_SNAPSHOT_STRIDE,
826
+ STAGE_EVENT_STRIDE,
827
+ STAGE_INVALID_SLOT,
828
+ StageBodyKind,
829
+ StageBoundaryDim,
830
+ StageRicochetDim,
831
+ StageRicochetReflection,
832
+ StageTopDownPlane,
833
+ StageEventType,
834
+ STAGE_INPUT_BUTTON_JUMP,
835
+ STAGE_INPUT_BUTTON_RUN,
836
+ readBehaviorSnapshot,
837
+ readStageRenderSlot,
838
+ WasmStageRuntime,
839
+ createWasmStageRuntime
840
+ };
841
+ //# sourceMappingURL=chunk-E4X4YJZB.js.map