@zylem/behaviors 0.5.1 → 0.5.5
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.
- package/README.md +1 -1
- package/dist/{behavior-system-CeJXzNvr.d.ts → behavior-system-HEt67el5.d.ts} +46 -6
- package/dist/{chunk-5EBIIYZD.js → chunk-3QUECYMT.js} +2 -2
- package/dist/{chunk-E4X4YJZB.js → chunk-4GW6DCYF.js} +54 -6
- package/dist/chunk-4GW6DCYF.js.map +1 -0
- package/dist/{chunk-ZRQWSURL.js → chunk-5XPPLTC7.js} +2 -2
- package/dist/chunk-5XPPLTC7.js.map +1 -0
- package/dist/{chunk-5NJGASUJ.js → chunk-B2ERQ6HD.js} +2 -2
- package/dist/{chunk-VFDUKGRZ.js → chunk-BAXJ7XHJ.js} +1 -1
- package/dist/chunk-BAXJ7XHJ.js.map +1 -0
- package/dist/{chunk-KOWGILCN.js → chunk-D7N6SC4D.js} +2 -2
- package/dist/{chunk-JGXRQUTC.js → chunk-DWVLGXMF.js} +2 -2
- package/dist/{chunk-AEBDZWCP.js → chunk-GL5JGXPR.js} +2 -2
- package/dist/{chunk-7JLWZXPA.js → chunk-GLXEJD2P.js} +2 -2
- package/dist/{chunk-VT3H43QA.js → chunk-IRMJTAIK.js} +41 -6
- package/dist/chunk-IRMJTAIK.js.map +1 -0
- package/dist/{chunk-F6ESSHQK.js → chunk-JACX7ZMJ.js} +2 -2
- package/dist/{chunk-W26PHBME.js → chunk-S5HFWDGM.js} +41 -6
- package/dist/chunk-S5HFWDGM.js.map +1 -0
- package/dist/{chunk-7JJEIADR.js → chunk-USFIJUDN.js} +300 -157
- package/dist/chunk-USFIJUDN.js.map +1 -0
- package/dist/{chunk-5UMCWV5A.js → chunk-WQUPSOFV.js} +2 -2
- package/dist/{chunk-GQAPBNGT.js → chunk-ZOYA3TZG.js} +2 -2
- package/dist/{components-BANNjAZP.d.ts → components-JZQoO2sU.d.ts} +1 -1
- package/dist/cooldown.d.ts +1 -1
- package/dist/cooldown.js +1 -1
- package/dist/coordinators/boundary-ricochet-3d.d.ts +2 -2
- package/dist/coordinators/boundary-ricochet.d.ts +2 -2
- package/dist/coordinators/multidirectional-space-shooter.d.ts +1 -1
- package/dist/coordinators/top-down-shooter.d.ts +1 -1
- package/dist/core.d.ts +32 -7
- package/dist/core.js +49 -5
- package/dist/core.js.map +1 -1
- package/dist/destructible-3d.d.ts +1 -1
- package/dist/first-person.d.ts +1 -1
- package/dist/first-person.js +2 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +15 -15
- package/dist/jumper-2d.d.ts +1 -1
- package/dist/jumper-2d.js +2 -2
- package/dist/jumper-3d.d.ts +1 -1
- package/dist/jumper-3d.js +2 -2
- package/dist/{moveable-XhzWPAw5.d.ts → moveable-BdFmI3s1.d.ts} +1 -1
- package/dist/particle-emitter/presets.d.ts +1 -1
- package/dist/particle-emitter/presets.js +1 -1
- package/dist/particle-emitter.d.ts +3 -3
- package/dist/particle-emitter.js +2 -2
- package/dist/platformer-2d.d.ts +9 -1
- package/dist/platformer-2d.js +2 -2
- package/dist/platformer-3d.d.ts +9 -1
- package/dist/platformer-3d.js +2 -2
- package/dist/ricochet-2d.d.ts +1 -1
- package/dist/ricochet-2d.js +2 -2
- package/dist/ricochet-3d.d.ts +1 -1
- package/dist/ricochet-3d.js +2 -2
- package/dist/runtime-2d.d.ts +1 -1
- package/dist/screen-visibility.d.ts +1 -1
- package/dist/screen-wrap.d.ts +1 -1
- package/dist/shooter-2d.d.ts +1 -1
- package/dist/{spark-Dx3cJbTW.d.ts → spark-C4Tp-52_.d.ts} +4 -2
- package/dist/thruster.d.ts +1 -1
- package/dist/thruster.js +1 -1
- package/dist/top-down-movement.d.ts +1 -1
- package/dist/top-down-movement.js +2 -2
- package/dist/world-boundary-2d.d.ts +1 -1
- package/dist/world-boundary-2d.js +2 -2
- package/dist/world-boundary-3d.d.ts +1 -1
- package/dist/world-boundary-3d.js +2 -2
- package/package.json +159 -161
- package/dist/chunk-7JJEIADR.js.map +0 -1
- package/dist/chunk-E4X4YJZB.js.map +0 -1
- package/dist/chunk-VFDUKGRZ.js.map +0 -1
- package/dist/chunk-VT3H43QA.js.map +0 -1
- package/dist/chunk-W26PHBME.js.map +0 -1
- package/dist/chunk-ZRQWSURL.js.map +0 -1
- /package/dist/{chunk-5EBIIYZD.js.map → chunk-3QUECYMT.js.map} +0 -0
- /package/dist/{chunk-5NJGASUJ.js.map → chunk-B2ERQ6HD.js.map} +0 -0
- /package/dist/{chunk-KOWGILCN.js.map → chunk-D7N6SC4D.js.map} +0 -0
- /package/dist/{chunk-JGXRQUTC.js.map → chunk-DWVLGXMF.js.map} +0 -0
- /package/dist/{chunk-AEBDZWCP.js.map → chunk-GL5JGXPR.js.map} +0 -0
- /package/dist/{chunk-7JLWZXPA.js.map → chunk-GLXEJD2P.js.map} +0 -0
- /package/dist/{chunk-F6ESSHQK.js.map → chunk-JACX7ZMJ.js.map} +0 -0
- /package/dist/{chunk-5UMCWV5A.js.map → chunk-WQUPSOFV.js.map} +0 -0
- /package/dist/{chunk-GQAPBNGT.js.map → chunk-ZOYA3TZG.js.map} +0 -0
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ The simulation layer of the Zylem framework: tree-shakable behavior descriptors,
|
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
- **`createSimulation()` / `Simulation`** — loads and owns the WASM stage, exposes `spawn`/`despawn` with opaque `EntityHandle`s, a fixed-timestep `update(delta)` loop, snapshot/pose accessors, raycasts, debug rendering, and translated `SimulationEvent`s (collision start/stop with handles instead of raw slots).
|
|
12
|
-
- **Behavior descriptors** (`Platformer3DBehavior`, `TopDownMovementBehavior`, …) — attach WASM-side controllers to entities and forward per-frame input through
|
|
12
|
+
- **Behavior descriptors** (`Platformer3DBehavior`, `TopDownMovementBehavior`, …) — attach WASM-side controllers to entities and forward per-frame input through slot-indexed buffers; FSM state is read back from snapshots.
|
|
13
13
|
- **`MockBehaviorRuntime`** — in-memory `BehaviorRuntime` implementation for unit-testing behaviors without loading WASM.
|
|
14
14
|
|
|
15
15
|
Physics simulation is WASM-only; there is no TypeScript physics fallback. Disposal chains downward: `Simulation.dispose()` destroys the WASM stage.
|
|
@@ -113,7 +113,7 @@ interface VelocityIntent {
|
|
|
113
113
|
priority?: number;
|
|
114
114
|
}
|
|
115
115
|
/**
|
|
116
|
-
* Transform state managed by Valtio for
|
|
116
|
+
* Transform state managed by Valtio for per-frame physics intent accumulation.
|
|
117
117
|
*
|
|
118
118
|
* This store accumulates transformation intents during the frame,
|
|
119
119
|
* then applies them all at once after onUpdate() callbacks complete.
|
|
@@ -372,7 +372,19 @@ interface StagePlatformer3DOptions {
|
|
|
372
372
|
snapToGroundDistance?: number;
|
|
373
373
|
/** KCC collision offset between collider and environment (default 0.05). */
|
|
374
374
|
characterOffset?: number;
|
|
375
|
-
|
|
375
|
+
/** Collider local offset X (fallback / override). */
|
|
376
|
+
offsetX?: number;
|
|
377
|
+
/** Collider local offset Y (fallback / override). */
|
|
378
|
+
offsetY?: number;
|
|
379
|
+
/** Collider local offset Z (fallback / override). */
|
|
380
|
+
offsetZ?: number;
|
|
381
|
+
/** 0 = auto-read attached collider; 1 = use stored shape fields. */
|
|
382
|
+
shapeSource?: number;
|
|
383
|
+
}
|
|
384
|
+
declare const StagePlatformerShapeSource: {
|
|
385
|
+
readonly Auto: 0;
|
|
386
|
+
readonly Override: 1;
|
|
387
|
+
};
|
|
376
388
|
interface StagePlatformer2DOptions {
|
|
377
389
|
halfHeight: number;
|
|
378
390
|
radius: number;
|
|
@@ -401,6 +413,14 @@ interface StagePlatformer2DOptions {
|
|
|
401
413
|
snapToGroundDistance?: number;
|
|
402
414
|
/** KCC collision offset between collider and environment (default 0.05). */
|
|
403
415
|
characterOffset?: number;
|
|
416
|
+
/** Collider local offset X (fallback / override). */
|
|
417
|
+
offsetX?: number;
|
|
418
|
+
/** Collider local offset Y (fallback / override). */
|
|
419
|
+
offsetY?: number;
|
|
420
|
+
/** Collider local offset Z (fallback / override). */
|
|
421
|
+
offsetZ?: number;
|
|
422
|
+
/** 0 = auto-read attached collider; 1 = use stored shape fields. */
|
|
423
|
+
shapeSource?: number;
|
|
404
424
|
}
|
|
405
425
|
interface StageFirstPersonOptions {
|
|
406
426
|
walkSpeed: number;
|
|
@@ -415,7 +435,7 @@ interface StageFirstPersonInput {
|
|
|
415
435
|
lookPitchDelta: number;
|
|
416
436
|
run: boolean;
|
|
417
437
|
}
|
|
418
|
-
/** Button bits for the
|
|
438
|
+
/** Button bits for the slot-indexed input buffer's bitmask field. */
|
|
419
439
|
declare const STAGE_INPUT_BUTTON_JUMP = 1;
|
|
420
440
|
declare const STAGE_INPUT_BUTTON_RUN = 2;
|
|
421
441
|
/**
|
|
@@ -522,13 +542,16 @@ interface StageEvent {
|
|
|
522
542
|
* Mirrors the `STAGE_RENDER_STRIDE` (12-float) packing documented in
|
|
523
543
|
* `runtime/stage/render.rs`:
|
|
524
544
|
* `[0..3]` position, `[3..7]` rotation xyzw, `[7]` uniform scale,
|
|
525
|
-
* `[8..
|
|
545
|
+
* `[8..11]` custom0..custom2 (shading hints), `[11]` custom3 sleeping flag
|
|
546
|
+
* (1.0 = sleeping).
|
|
526
547
|
*/
|
|
527
548
|
interface StageRenderSlot {
|
|
528
549
|
position: [number, number, number];
|
|
529
550
|
rotation: [number, number, number, number];
|
|
530
551
|
scale: number;
|
|
531
552
|
custom: [number, number, number, number];
|
|
553
|
+
/** True when custom[3] indicates the body is sleeping. */
|
|
554
|
+
isSleeping: boolean;
|
|
532
555
|
}
|
|
533
556
|
/**
|
|
534
557
|
* Read a single entity slot out of a unified-Stage render buffer view.
|
|
@@ -639,6 +662,23 @@ declare class WasmStageRuntime implements BehaviorRuntime {
|
|
|
639
662
|
get tickCount(): number;
|
|
640
663
|
get activeCount(): number;
|
|
641
664
|
setGravity(x: number, y: number, z: number): void;
|
|
665
|
+
/**
|
|
666
|
+
* Toggle per-step collision-event collection in the wasm stage. Hosts
|
|
667
|
+
* with no collision listeners should disable it — with thousands of
|
|
668
|
+
* touching bodies the per-step contact-pair hashing is a significant
|
|
669
|
+
* fraction of `step()`.
|
|
670
|
+
*/
|
|
671
|
+
setEventsEnabled(enabled: boolean): void;
|
|
672
|
+
/** Cap Rapier contact solver iterations (default 4). */
|
|
673
|
+
setSolverIterations(iterations: number): void;
|
|
674
|
+
/**
|
|
675
|
+
* Override sleep activation thresholds for sleep-capable dynamic bodies.
|
|
676
|
+
* Higher velocity thresholds / lower `timeUntilSleep` put piles to sleep
|
|
677
|
+
* sooner.
|
|
678
|
+
*/
|
|
679
|
+
setSleepThresholds(normalizedLinearThreshold: number, angularThreshold: number, timeUntilSleep: number): void;
|
|
680
|
+
/** Number of awake (non-sleeping) dynamic rigid bodies. */
|
|
681
|
+
awakeDynamicCount(): number;
|
|
642
682
|
createEntity(): number;
|
|
643
683
|
destroyEntity(slot: number): boolean;
|
|
644
684
|
attachBody(slot: number, config: StageBodyConfig): boolean;
|
|
@@ -676,7 +716,7 @@ declare class WasmStageRuntime implements BehaviorRuntime {
|
|
|
676
716
|
get snapshot(): Float32Array;
|
|
677
717
|
get snapshotStride(): number;
|
|
678
718
|
/**
|
|
679
|
-
* Write the primary movement axes for a slot into the
|
|
719
|
+
* Write the primary movement axes for a slot into the slot-indexed input
|
|
680
720
|
* buffer and mark the slot dirty. Field-scoped (doesn't touch look
|
|
681
721
|
* deltas or buttons) so multiple behaviors composed on one entity can
|
|
682
722
|
* each write their part.
|
|
@@ -865,4 +905,4 @@ interface BehaviorSystemContext {
|
|
|
865
905
|
*/
|
|
866
906
|
type BehaviorSystemFactory<T extends BehaviorSystem = BehaviorSystem> = (stage: BehaviorSystemContext) => T;
|
|
867
907
|
|
|
868
|
-
export { type
|
|
908
|
+
export { type VelocityIntentMode as $, type StageJumper2DOptions as A, type BaseBehaviorHandle as B, type CreateEntityFn as C, type DefineBehaviorConfig as D, type StageJumper3DOptions as E, type StagePlatformer2DOptions as F, GameEntity as G, type StagePlatformer3DOptions as H, StagePlatformerShapeSource as I, type StagePose as J, type StageRaycastHit as K, type StageRenderSlot as L, StageRicochetDim as M, type StageRicochetDimValue as N, type StageRicochetOptions as O, StageRicochetReflection as P, type StageRicochetReflectionValue as Q, type StageScreenWrapOptions as R, STAGE_INPUT_BUTTON_JUMP as S, type StageShooter2DOptions as T, type StageThrusterOptions as U, type StageTopDownOptions as V, StageTopDownPlane as W, type StageTopDownPlaneValue as X, type StageWorldBoundaryOptions as Y, type TransformState as Z, type VelocityIntent as _, type BehaviorDescriptor as a, type WasmSnapshotBackref as a0, WasmStageRuntime as a1, type WasmStageRuntimeOptions as a2, createTransformStore as a3, createWasmStageRuntime as a4, defineBehavior as a5, readBehaviorSnapshot as a6, readStageRenderSlot as a7, type BehaviorEntityLink as b, type BehaviorHandle as c, type BehaviorRef as d, type BehaviorRuntime as e, type BehaviorSystem as f, type BehaviorSystemContext as g, type BehaviorSystemFactory as h, type GameEntityOptions as i, STAGE_INPUT_BUTTON_RUN as j, STAGE_INVALID_SLOT as k, type StageBehaviorSnapshot as l, type StageBodyConfig as m, type StageBodyInfo as n, StageBodyKind as o, type StageBodyKindValue as p, StageBoundaryDim as q, type StageBoundaryDimValue as r, type StageColliderConfig as s, type StageColliderShape as t, type StageDebugRender as u, type StageEvent as v, StageEventType as w, type StageEventTypeValue as x, type StageFirstPersonInput as y, type StageFirstPersonOptions as z };
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-TBUKJKY6.js";
|
|
9
9
|
import {
|
|
10
10
|
StageTopDownPlane
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-4GW6DCYF.js";
|
|
12
12
|
import {
|
|
13
13
|
defineBehavior
|
|
14
14
|
} from "./chunk-EZNCCO4L.js";
|
|
@@ -95,4 +95,4 @@ var TopDownMovementBehavior = defineBehavior({
|
|
|
95
95
|
export {
|
|
96
96
|
TopDownMovementBehavior
|
|
97
97
|
};
|
|
98
|
-
//# sourceMappingURL=chunk-
|
|
98
|
+
//# sourceMappingURL=chunk-3QUECYMT.js.map
|
|
@@ -40,6 +40,10 @@ var StageEventType = {
|
|
|
40
40
|
Wrapped: 8,
|
|
41
41
|
CooldownFired: 9
|
|
42
42
|
};
|
|
43
|
+
var StagePlatformerShapeSource = {
|
|
44
|
+
Auto: 0,
|
|
45
|
+
Override: 1
|
|
46
|
+
};
|
|
43
47
|
var STAGE_INPUT_BUTTON_JUMP = 1;
|
|
44
48
|
var STAGE_INPUT_BUTTON_RUN = 2;
|
|
45
49
|
function readBehaviorSnapshot(ref) {
|
|
@@ -58,7 +62,8 @@ function readStageRenderSlot(view, slot, out) {
|
|
|
58
62
|
position: [0, 0, 0],
|
|
59
63
|
rotation: [0, 0, 0, 1],
|
|
60
64
|
scale: 1,
|
|
61
|
-
custom: [0, 0, 0, 0]
|
|
65
|
+
custom: [0, 0, 0, 0],
|
|
66
|
+
isSleeping: false
|
|
62
67
|
};
|
|
63
68
|
result.position[0] = view[base];
|
|
64
69
|
result.position[1] = view[base + 1];
|
|
@@ -73,6 +78,7 @@ function readStageRenderSlot(view, slot, out) {
|
|
|
73
78
|
result.custom[1] = view[base + 9];
|
|
74
79
|
result.custom[2] = view[base + 10];
|
|
75
80
|
result.custom[3] = view[base + 11];
|
|
81
|
+
result.isSleeping = result.custom[3] > 0.5;
|
|
76
82
|
return result;
|
|
77
83
|
}
|
|
78
84
|
var WasmStageRuntime = class {
|
|
@@ -145,6 +151,35 @@ var WasmStageRuntime = class {
|
|
|
145
151
|
setGravity(x, y, z) {
|
|
146
152
|
this.exports.zylem_stage_set_gravity(x, y, z);
|
|
147
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Toggle per-step collision-event collection in the wasm stage. Hosts
|
|
156
|
+
* with no collision listeners should disable it — with thousands of
|
|
157
|
+
* touching bodies the per-step contact-pair hashing is a significant
|
|
158
|
+
* fraction of `step()`.
|
|
159
|
+
*/
|
|
160
|
+
setEventsEnabled(enabled) {
|
|
161
|
+
this.exports.zylem_stage_set_events_enabled(enabled ? 1 : 0);
|
|
162
|
+
}
|
|
163
|
+
/** Cap Rapier contact solver iterations (default 4). */
|
|
164
|
+
setSolverIterations(iterations) {
|
|
165
|
+
this.exports.zylem_stage_set_solver_iterations(Math.max(1, iterations | 0));
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Override sleep activation thresholds for sleep-capable dynamic bodies.
|
|
169
|
+
* Higher velocity thresholds / lower `timeUntilSleep` put piles to sleep
|
|
170
|
+
* sooner.
|
|
171
|
+
*/
|
|
172
|
+
setSleepThresholds(normalizedLinearThreshold, angularThreshold, timeUntilSleep) {
|
|
173
|
+
this.exports.zylem_stage_set_sleep_thresholds(
|
|
174
|
+
normalizedLinearThreshold,
|
|
175
|
+
angularThreshold,
|
|
176
|
+
timeUntilSleep
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
/** Number of awake (non-sleeping) dynamic rigid bodies. */
|
|
180
|
+
awakeDynamicCount() {
|
|
181
|
+
return this.exports.zylem_stage_awake_dynamic_count();
|
|
182
|
+
}
|
|
148
183
|
// ─── Entity lifecycle ───────────────────────────────────────────────
|
|
149
184
|
createEntity() {
|
|
150
185
|
const slot = this.exports.zylem_stage_create_entity() >>> 0;
|
|
@@ -420,6 +455,7 @@ var WasmStageRuntime = class {
|
|
|
420
455
|
/** Wireframe debug render of every collider (all shapes). */
|
|
421
456
|
getDebugRender() {
|
|
422
457
|
const vertexCount = this.exports.zylem_stage_debug_render() >>> 0;
|
|
458
|
+
this.refreshViews();
|
|
423
459
|
if (vertexCount === 0) return null;
|
|
424
460
|
const buffer = this.memory.buffer;
|
|
425
461
|
const vertices = new Float32Array(
|
|
@@ -432,7 +468,10 @@ var WasmStageRuntime = class {
|
|
|
432
468
|
this.exports.zylem_stage_debug_colors_ptr(),
|
|
433
469
|
this.exports.zylem_stage_debug_colors_len()
|
|
434
470
|
);
|
|
435
|
-
return {
|
|
471
|
+
return {
|
|
472
|
+
vertices: new Float32Array(vertices),
|
|
473
|
+
colors: new Float32Array(colors)
|
|
474
|
+
};
|
|
436
475
|
}
|
|
437
476
|
// ─── Render / event reads ──────────────────────────────────────────
|
|
438
477
|
/** Read-only view over the render buffer; one slot occupies {@link STAGE_RENDER_STRIDE} floats. */
|
|
@@ -484,7 +523,7 @@ var WasmStageRuntime = class {
|
|
|
484
523
|
return STAGE_SNAPSHOT_STRIDE;
|
|
485
524
|
}
|
|
486
525
|
/**
|
|
487
|
-
* Write the primary movement axes for a slot into the
|
|
526
|
+
* Write the primary movement axes for a slot into the slot-indexed input
|
|
488
527
|
* buffer and mark the slot dirty. Field-scoped (doesn't touch look
|
|
489
528
|
* deltas or buttons) so multiple behaviors composed on one entity can
|
|
490
529
|
* each write their part.
|
|
@@ -729,7 +768,11 @@ var WasmStageRuntime = class {
|
|
|
729
768
|
opts.autostepHeight ?? 0.3,
|
|
730
769
|
opts.autostepMinWidth ?? 0.1,
|
|
731
770
|
opts.snapToGroundDistance ?? 0.3,
|
|
732
|
-
opts.characterOffset ?? 0.05
|
|
771
|
+
opts.characterOffset ?? 0.05,
|
|
772
|
+
opts.offsetX ?? 0,
|
|
773
|
+
opts.offsetY ?? 0,
|
|
774
|
+
opts.offsetZ ?? 0,
|
|
775
|
+
opts.shapeSource ?? StagePlatformerShapeSource.Auto
|
|
733
776
|
) !== 0;
|
|
734
777
|
}
|
|
735
778
|
setPlatformer3DInputAxes(slot, moveX, moveZ) {
|
|
@@ -767,7 +810,11 @@ var WasmStageRuntime = class {
|
|
|
767
810
|
opts.autostepHeight ?? 0.25,
|
|
768
811
|
opts.autostepMinWidth ?? 0.05,
|
|
769
812
|
opts.snapToGroundDistance ?? 0.2,
|
|
770
|
-
opts.characterOffset ?? 0.05
|
|
813
|
+
opts.characterOffset ?? 0.05,
|
|
814
|
+
opts.offsetX ?? 0,
|
|
815
|
+
opts.offsetY ?? 0,
|
|
816
|
+
opts.offsetZ ?? 0,
|
|
817
|
+
opts.shapeSource ?? StagePlatformerShapeSource.Auto
|
|
771
818
|
) !== 0;
|
|
772
819
|
}
|
|
773
820
|
setPlatformer2DInputAxes(slot, moveX) {
|
|
@@ -831,6 +878,7 @@ export {
|
|
|
831
878
|
StageRicochetReflection,
|
|
832
879
|
StageTopDownPlane,
|
|
833
880
|
StageEventType,
|
|
881
|
+
StagePlatformerShapeSource,
|
|
834
882
|
STAGE_INPUT_BUTTON_JUMP,
|
|
835
883
|
STAGE_INPUT_BUTTON_RUN,
|
|
836
884
|
readBehaviorSnapshot,
|
|
@@ -838,4 +886,4 @@ export {
|
|
|
838
886
|
WasmStageRuntime,
|
|
839
887
|
createWasmStageRuntime
|
|
840
888
|
};
|
|
841
|
-
//# sourceMappingURL=chunk-
|
|
889
|
+
//# sourceMappingURL=chunk-4GW6DCYF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/runtime/wasm-stage-runtime.ts"],"sourcesContent":["/**\n * `WasmStageRuntime` — owns one wasm `WebAssembly.Instance` of\n * `@zylem/runtime` and exposes the unified-Stage FFI as typed TypeScript\n * methods. This is the single simulation adapter for the whole framework:\n * behavior systems talk to it through the {@link BehaviorRuntime} contract,\n * and hosts (e.g. `@zylem/game-lib`) drive it through\n * {@link createSimulation} in `./simulation`.\n */\n\nimport {\n\tloadStageFfi,\n\ttype StageWasmExports,\n\tSTAGE_RENDER_STRIDE,\n\tSTAGE_INPUT_STRIDE,\n\tSTAGE_SNAPSHOT_STRIDE,\n\tSTAGE_EVENT_STRIDE,\n} from '@zylem/runtime';\n\nexport {\n\tSTAGE_RENDER_STRIDE,\n\tSTAGE_INPUT_STRIDE,\n\tSTAGE_SNAPSHOT_STRIDE,\n\tSTAGE_EVENT_STRIDE,\n};\nexport type { StageWasmExports };\n\n/** Sentinel handle for \"no entity / failed allocation\". Mirrors `INVALID_SLOT` in Rust. */\nexport const STAGE_INVALID_SLOT = 0xffffffff;\n\nexport const StageBodyKind = {\n\tDynamic: 0,\n\tStatic: 1,\n\tKinematicPosition: 2,\n\tKinematicVelocity: 3,\n} as const;\n\nexport type StageBodyKindValue = (typeof StageBodyKind)[keyof typeof StageBodyKind];\n\nexport const StageBoundaryDim = {\n\tTwo: 2,\n\tThree: 3,\n} as const;\n\nexport const StageRicochetDim = {\n\tTwo: 2,\n\tThree: 3,\n} as const;\n\nexport const StageRicochetReflection = {\n\tMirror: 0,\n\tAngled: 1,\n} as const;\n\nexport const StageTopDownPlane = {\n\tXy: 0,\n\tXz: 1,\n} as const;\n\nexport const StageEventType = {\n\tCollisionStarted: 1,\n\tCollisionStopped: 2,\n\tBoundaryHit: 3,\n\tRicochet: 4,\n\tRegionEntered: 5,\n\tJumpStarted: 6,\n\tLanded: 7,\n\tWrapped: 8,\n\tCooldownFired: 9,\n} as const;\n\nexport type StageBoundaryDimValue = (typeof StageBoundaryDim)[keyof typeof StageBoundaryDim];\nexport type StageRicochetDimValue = (typeof StageRicochetDim)[keyof typeof StageRicochetDim];\nexport type StageRicochetReflectionValue =\n\t(typeof StageRicochetReflection)[keyof typeof StageRicochetReflection];\nexport type StageTopDownPlaneValue = (typeof StageTopDownPlane)[keyof typeof StageTopDownPlane];\n\n/** Position + rotation snapshot for one runtime slot. */\nexport interface StagePose {\n\tposition: [number, number, number];\n\trotation: [number, number, number, number];\n}\n\nexport interface StageWorldBoundaryOptions {\n\ttop: number;\n\tbottom: number;\n\tleft: number;\n\tright: number;\n\tfront?: number;\n\tback?: number;\n\tpadding?: number;\n}\n\nexport interface StageScreenWrapOptions {\n\twidth: number;\n\theight: number;\n\tcenterX?: number;\n\tcenterY?: number;\n\tedgeThreshold?: number;\n}\n\nexport interface StageRicochetOptions {\n\tminSpeed: number;\n\tmaxSpeed: number;\n\tspeedMultiplier: number;\n\tmaxAngleDeg: number;\n\treflectionMode: StageRicochetReflectionValue;\n}\n\nexport interface StageThrusterOptions {\n\tmaxSpeed: number;\n\tacceleration: number;\n\tturnRateRadPerSec: number;\n\tlinearDamping: number;\n}\n\nexport interface StageTopDownOptions {\n\tplane: StageTopDownPlaneValue;\n\tspeed: number;\n\tfaceMovement?: boolean;\n}\n\nexport interface StageShooter2DOptions {\n\tfireRateHz: number;\n\tmuzzleOffsetX: number;\n\tmuzzleOffsetY: number;\n\tmuzzleSpeed: number;\n}\n\nexport interface StageJumper2DOptions {\n\tjumpForce: number;\n\tmaxJumps: number;\n\tjumpBufferTime: number;\n\tcoyoteTime: number;\n\tgravity: number;\n}\n\nexport interface StageJumper3DOptions {\n\tjumpForce: number;\n\tmaxJumps: number;\n\tgravity: number;\n\t/** Coyote time in seconds (default 0.1). */\n\tcoyoteTime?: number;\n\t/** Jump buffer window in seconds (default 0.08). */\n\tjumpBufferTime?: number;\n}\n\nexport interface StagePlatformer3DOptions {\n\thalfHeight: number;\n\tradius: number;\n\twalkSpeed: number;\n\trunSpeed: number;\n\tjumpForce: number;\n\tmaxJumps: number;\n\tgravity: number;\n\t/** Coyote time in seconds (default 0.1). */\n\tcoyoteTime?: number;\n\t/** Jump buffer window in seconds (default 0.1). */\n\tjumpBufferTime?: number;\n\t/** Velocity multiplier applied on early jump release (default 0.5). */\n\tjumpCutMultiplier?: number;\n\t/** Seconds before a multi-jump becomes available (default 0.15). */\n\tmultiJumpWindow?: number;\n\t/** Max slope angle in degrees the KCC can climb (default 50). */\n\tslopeClimbAngle?: number;\n\t/** Slope angle in degrees past which the character slides (default 40). */\n\tslopeSlideAngle?: number;\n\t/** Autostep max height in world units; 0 disables (default 0.3). */\n\tautostepHeight?: number;\n\t/** Minimum unobstructed width for an autostep (default 0.1). */\n\tautostepMinWidth?: number;\n\t/** Snap-to-ground distance in world units; 0 disables (default 0.3). */\n\tsnapToGroundDistance?: number;\n\t/** KCC collision offset between collider and environment (default 0.05). */\n\tcharacterOffset?: number;\n\t/** Collider local offset X (fallback / override). */\n\toffsetX?: number;\n\t/** Collider local offset Y (fallback / override). */\n\toffsetY?: number;\n\t/** Collider local offset Z (fallback / override). */\n\toffsetZ?: number;\n\t/** 0 = auto-read attached collider; 1 = use stored shape fields. */\n\tshapeSource?: number;\n}\n\nexport const StagePlatformerShapeSource = {\n\tAuto: 0,\n\tOverride: 1,\n} as const;\n\nexport interface StagePlatformer2DOptions {\n\thalfHeight: number;\n\tradius: number;\n\twalkSpeed: number;\n\trunSpeed: number;\n\tjumpForce: number;\n\tmaxJumps: number;\n\tgravity: number;\n\t/** Coyote time in seconds (default 0.1). */\n\tcoyoteTime?: number;\n\t/** Jump buffer window in seconds (default 0.1). */\n\tjumpBufferTime?: number;\n\t/** Velocity multiplier applied on early jump release (default 0.5). */\n\tjumpCutMultiplier?: number;\n\t/** Seconds before a multi-jump becomes available (default 0.15). */\n\tmultiJumpWindow?: number;\n\t/** Max slope angle in degrees the KCC can climb (default 50). */\n\tslopeClimbAngle?: number;\n\t/** Slope angle in degrees past which the character slides (default 40). */\n\tslopeSlideAngle?: number;\n\t/** Autostep max height in world units; 0 disables (default 0.25). */\n\tautostepHeight?: number;\n\t/** Minimum unobstructed width for an autostep (default 0.05). */\n\tautostepMinWidth?: number;\n\t/** Snap-to-ground distance in world units; 0 disables (default 0.2). */\n\tsnapToGroundDistance?: number;\n\t/** KCC collision offset between collider and environment (default 0.05). */\n\tcharacterOffset?: number;\n\t/** Collider local offset X (fallback / override). */\n\toffsetX?: number;\n\t/** Collider local offset Y (fallback / override). */\n\toffsetY?: number;\n\t/** Collider local offset Z (fallback / override). */\n\toffsetZ?: number;\n\t/** 0 = auto-read attached collider; 1 = use stored shape fields. */\n\tshapeSource?: number;\n}\n\nexport interface StageFirstPersonOptions {\n\twalkSpeed: number;\n\trunSpeed: number;\n\teyeHeight: number;\n\tlookSensitivity: number;\n}\n\nexport interface StageFirstPersonInput {\n\tmoveX: number;\n\tmoveZ: number;\n\tlookYawDelta: number;\n\tlookPitchDelta: number;\n\trun: boolean;\n}\n\n/** Button bits for the slot-indexed input buffer's bitmask field. */\nexport const STAGE_INPUT_BUTTON_JUMP = 1;\nexport const STAGE_INPUT_BUTTON_RUN = 2;\n\n/**\n * Decoded per-slot behavior snapshot written by the runtime after every\n * step: movement fields come from whichever character behavior the entity\n * has (platformer 3D/2D, jumper 3D/2D); first-person fills yaw/pitch.\n * Values reflect the end of the previous `step()` (one-frame read lag).\n */\nexport interface StageBehaviorSnapshot {\n\tgrounded: boolean;\n\tfsmState: number;\n\tjumpCount: number;\n\tverticalVelocity: number;\n\tspeed: number;\n\tyaw: number;\n\tpitch: number;\n}\n\n/**\n * Wasm fast-path backrefs a behavior system stores on its `BehaviorRef` every\n * frame so descriptor handles can read the runtime snapshot buffer instead of\n * a duplicate TS FSM (or hardcoded defaults).\n */\nexport interface WasmSnapshotBackref {\n\t__wasmStage?: BehaviorRuntime | null;\n\t__entity?: { runtimeHandle?: number } | null;\n}\n\n/**\n * Read the behavior snapshot for the entity a `BehaviorRef` is linked to.\n * Returns `null` off the wasm fast path (no stage runtime / no\n * `runtimeHandle` / no snapshot yet), in which case handles should fall back\n * to their TS FSM.\n */\nexport function readBehaviorSnapshot(ref: object): StageBehaviorSnapshot | null {\n\tconst backref = ref as WasmSnapshotBackref;\n\tconst wasmStage = backref.__wasmStage;\n\tconst handle = backref.__entity?.runtimeHandle ?? -1;\n\tif (!wasmStage || handle < 0) return null;\n\treturn wasmStage.readSnapshot(handle);\n}\n\n/**\n * Runtime surface behavior systems rely on. `WasmStageRuntime` is the real\n * wasm-backed implementation; `MockBehaviorRuntime` (see\n * `./mock-behavior-runtime`) implements the same contract for unit tests, so\n * descriptors stay runtime-agnostic.\n */\nexport interface BehaviorRuntime {\n\tgetPose(handle: number, out?: StagePose): StagePose | null;\n\tsetPosition(handle: number, x: number, y: number, z: number): boolean;\n\tsetRotation(handle: number, x: number, y: number, z: number, w: number): boolean;\n\n\t// ─── Batched input / snapshot buffers (preferred fast path) ─────────\n\t// Field-scoped writes into the slot-indexed input buffer, consumed by\n\t// the runtime in one pass at the start of each step. Behaviors composed\n\t// on one entity each write only their part of the slot.\n\twriteInputAxes(handle: number, axisA: number, axisB: number): boolean;\n\twriteInputLook(handle: number, yawDelta: number, pitchDelta: number): boolean;\n\t/** Write reserved input slots (thruster world-space vector X/Y). */\n\twriteInputReserved(handle: number, reservedA: number, reservedB: number): boolean;\n\twriteInputButton(handle: number, buttonMask: number, pressed: boolean): boolean;\n\t/** Read the per-slot behavior snapshot written at the end of the previous step. */\n\treadSnapshot(handle: number, out?: StageBehaviorSnapshot): StageBehaviorSnapshot | null;\n\n\tattachThruster(handle: number, opts: StageThrusterOptions): boolean;\n\tsetThrusterInput(\n\t\thandle: number,\n\t\tthrust: number,\n\t\trotate: number,\n\t\tvectorX?: number,\n\t\tvectorY?: number,\n\t): void;\n\n\tattachTopDown(handle: number, opts: StageTopDownOptions): boolean;\n\tsetTopDownInput(handle: number, moveX: number, moveY: number): void;\n\n\tattachShooter2D(handle: number, opts: StageShooter2DOptions): boolean;\n\n\tattachScreenWrap(handle: number, opts: StageScreenWrapOptions): boolean;\n\tqueryScreenWrap(handle: number): { fsm: number; lastWrappedAxes: number } | null;\n\n\tattachWorldBoundary(\n\t\thandle: number,\n\t\tdim: StageBoundaryDimValue,\n\t\topts: StageWorldBoundaryOptions,\n\t): boolean;\n\tqueryWorldBoundary(handle: number): { hits: number; clamped: [number, number, number] } | null;\n\n\tattachRicochet(handle: number, dim: StageRicochetDimValue, opts: StageRicochetOptions): boolean;\n\n\tattachPlatformer3D(handle: number, opts: StagePlatformer3DOptions): boolean;\n\tsetPlatformer3DInputAxes(handle: number, moveX: number, moveZ: number): void;\n\tsetPlatformer3DInputButtons(handle: number, jump: boolean, run: boolean): void;\n\n\tattachPlatformer2D(handle: number, opts: StagePlatformer2DOptions): boolean;\n\tsetPlatformer2DInputAxes(handle: number, moveX: number): void;\n\tsetPlatformer2DInputButtons(handle: number, jump: boolean, run: boolean): void;\n\n\tattachFirstPerson(handle: number, opts: StageFirstPersonOptions): boolean;\n\tsetFirstPersonInput(handle: number, input: StageFirstPersonInput): void;\n\n\tattachJumper2D(handle: number, opts: StageJumper2DOptions): boolean;\n\tsetJumper2DInput(handle: number, jumpPressed: boolean): void;\n\n\tattachJumper3D(handle: number, opts: StageJumper3DOptions): boolean;\n\tsetJumper3DInput(handle: number, jumpPressed: boolean): void;\n}\n\n/** Default options used when constructing a wasm-backed Stage runtime. */\nexport interface WasmStageRuntimeOptions {\n\tinitialCapacity?: number;\n\tgravity?: readonly [number, number, number];\n\timports?: WebAssembly.Imports;\n\t/**\n\t * Custom wasm source. Defaults to the `zylem_runtime.wasm` bundled with\n\t * `@zylem/runtime`.\n\t */\n\tsource?: RequestInfo | URL | ArrayBuffer | Uint8Array;\n}\n\nexport type StageEventTypeValue = (typeof StageEventType)[keyof typeof StageEventType];\n\n/** One decoded event drained from the runtime's per-step event buffer. */\nexport interface StageEvent {\n\ttype: StageEventTypeValue;\n\tprimarySlot: number | null;\n\tsecondarySlot: number | null;\n\tpayload: [number, number, number];\n}\n\n/**\n * Decoded view of one entity's slot in the unified render buffer.\n *\n * Mirrors the `STAGE_RENDER_STRIDE` (12-float) packing documented in\n * `runtime/stage/render.rs`:\n * `[0..3]` position, `[3..7]` rotation xyzw, `[7]` uniform scale,\n * `[8..11]` custom0..custom2 (shading hints), `[11]` custom3 sleeping flag\n * (1.0 = sleeping).\n */\nexport interface StageRenderSlot {\n\tposition: [number, number, number];\n\trotation: [number, number, number, number];\n\tscale: number;\n\tcustom: [number, number, number, number];\n\t/** True when custom[3] indicates the body is sleeping. */\n\tisSleeping: boolean;\n}\n\n/**\n * Read a single entity slot out of a unified-Stage render buffer view.\n *\n * @param view The `Float32Array` over wasm memory (e.g. `WasmStageRuntime.render`).\n * @param slot The entity's wasm slot id (its `runtimeHandle`).\n * @param out Optional target object to write into (avoids per-call allocation).\n * @returns The decoded slot, or `null` when the slot is out of range.\n */\nexport function readStageRenderSlot(\n\tview: Float32Array,\n\tslot: number,\n\tout?: StageRenderSlot,\n): StageRenderSlot | null {\n\tconst base = slot * STAGE_RENDER_STRIDE;\n\tif (slot < 0 || base + STAGE_RENDER_STRIDE > view.length) {\n\t\treturn null;\n\t}\n\tconst result: StageRenderSlot = out ?? {\n\t\tposition: [0, 0, 0],\n\t\trotation: [0, 0, 0, 1],\n\t\tscale: 1,\n\t\tcustom: [0, 0, 0, 0],\n\t\tisSleeping: false,\n\t};\n\tresult.position[0] = view[base]!;\n\tresult.position[1] = view[base + 1]!;\n\tresult.position[2] = view[base + 2]!;\n\tresult.rotation[0] = view[base + 3]!;\n\tresult.rotation[1] = view[base + 4]!;\n\tresult.rotation[2] = view[base + 5]!;\n\tresult.rotation[3] = view[base + 6]!;\n\t// A freshly-zeroed slot reports scale 0; treat that as the identity scale so\n\t// entities aren't collapsed before the runtime writes a real value.\n\tconst scale = view[base + 7]!;\n\tresult.scale = scale === 0 ? 1 : scale;\n\tresult.custom[0] = view[base + 8]!;\n\tresult.custom[1] = view[base + 9]!;\n\tresult.custom[2] = view[base + 10]!;\n\tresult.custom[3] = view[base + 11]!;\n\tresult.isSleeping = result.custom[3] > 0.5;\n\treturn result;\n}\n\nexport interface StageBodyConfig {\n\tkind: StageBodyKindValue;\n\tposition: readonly [number, number, number];\n\trotation: readonly [number, number, number, number];\n\tlinearDamping: number;\n\tangularDamping: number;\n\tgravityScale: number;\n\tcanSleep: boolean;\n\tccdEnabled: boolean;\n\tlockRotation: readonly [boolean, boolean, boolean];\n\tlockTranslation: readonly [boolean, boolean, boolean];\n}\n\nexport type StageColliderShape =\n\t| { type: 'box'; halfExtents: readonly [number, number, number] }\n\t| { type: 'sphere'; radius: number }\n\t| { type: 'capsule'; halfHeight: number; radius: number }\n\t| { type: 'cylinder'; halfHeight: number; radius: number }\n\t| { type: 'cone'; halfHeight: number; radius: number }\n\t| { type: 'convexHull'; vertices: Float32Array }\n\t| { type: 'trimesh'; vertices: Float32Array; indices: Uint32Array }\n\t| {\n\t\ttype: 'heightfield';\n\t\trows: number;\n\t\tcols: number;\n\t\tscale: readonly [number, number, number];\n\t\theights: Float32Array;\n\t};\n\nexport interface StageColliderConfig {\n\tshape: StageColliderShape;\n\toffset: readonly [number, number, number];\n\tfriction: number;\n\trestitution: number;\n\tsensor: boolean;\n\t/** Packed interaction-groups: high 16 bits = membership, low 16 bits = filter. */\n\tcollisionGroups: number;\n}\n\n/** Result of a physics raycast against the stage. */\nexport interface StageRaycastHit {\n\tslot: number;\n\tdistance: number;\n\tnormal: [number, number, number];\n}\n\n/** Body introspection payload for debug tooling. */\nexport interface StageBodyInfo {\n\tbodyType: number;\n\tmass: number;\n\tisSleeping: boolean;\n\tisEnabled: boolean;\n\tlinearVelocity: [number, number, number];\n}\n\n/** Line-list wireframe for physics debug rendering. */\nexport interface StageDebugRender {\n\t/** `[x, y, z]` per vertex, two vertices per line. */\n\tvertices: Float32Array;\n\t/** RGBA per vertex. */\n\tcolors: Float32Array;\n}\n\n/**\n * Owns the wasm instance plus the live float-views over its render / event /\n * pose / scratch buffers. One instance per logical stage; each stage gets\n * its own `WebAssembly.Instance` so the singleton inside `stage_ffi.rs`\n * stays single-stage scoped (today's `thread_local!` contract).\n */\nexport class WasmStageRuntime implements BehaviorRuntime {\n\treadonly exports: StageWasmExports;\n\tprivate readonly memory: WebAssembly.Memory;\n\tprivate renderView: Float32Array = new Float32Array(0);\n\tprivate inputView: Float32Array = new Float32Array(0);\n\tprivate snapshotView: Float32Array = new Float32Array(0);\n\tprivate eventView: Float32Array = new Float32Array(0);\n\tprivate poseView: Float32Array = new Float32Array(0);\n\tprivate vec3View: Float32Array = new Float32Array(0);\n\tprivate queryView: Float32Array = new Float32Array(0);\n\tprivate scratchView: Float32Array = new Float32Array(0);\n\n\tconstructor(exports: StageWasmExports, options: WasmStageRuntimeOptions = {}) {\n\t\tthis.exports = exports;\n\t\tthis.memory = exports.memory;\n\t\tconst capacity = Math.max(options.initialCapacity ?? 64, 8);\n\t\texports.zylem_stage_create(capacity);\n\t\tif (options.gravity) {\n\t\t\texports.zylem_stage_set_gravity(\n\t\t\t\toptions.gravity[0],\n\t\t\t\toptions.gravity[1],\n\t\t\t\toptions.gravity[2],\n\t\t\t);\n\t\t}\n\t\tthis.refreshViews();\n\t}\n\n\t/** Recreate typed views over wasm memory. Call after step() or whenever memory may have grown. */\n\trefreshViews(): void {\n\t\tconst buffer = this.memory.buffer;\n\t\tconst renderPtr = this.exports.zylem_stage_render_ptr();\n\t\tconst renderLen = this.exports.zylem_stage_render_len();\n\t\tconst inputPtr = this.exports.zylem_stage_input_ptr();\n\t\tconst inputLen = this.exports.zylem_stage_input_len();\n\t\tconst snapshotPtr = this.exports.zylem_stage_snapshot_ptr();\n\t\tconst snapshotLen = this.exports.zylem_stage_snapshot_len();\n\t\tconst eventPtr = this.exports.zylem_stage_event_ptr();\n\t\tconst eventLen = this.exports.zylem_stage_event_len();\n\t\tconst posePtr = this.exports.zylem_stage_pose_ptr();\n\t\tconst poseLen = this.exports.zylem_stage_pose_len();\n\t\tconst vec3Ptr = this.exports.zylem_stage_vec3_ptr();\n\t\tconst queryPtr = this.exports.zylem_stage_query_ptr();\n\t\tconst queryLen = this.exports.zylem_stage_query_len();\n\t\tconst scratchPtr = this.exports.zylem_stage_scratch_ptr();\n\t\tconst scratchCap = this.exports.zylem_stage_scratch_capacity();\n\n\t\tthis.renderView = renderLen > 0 ? new Float32Array(buffer, renderPtr, renderLen) : new Float32Array(0);\n\t\tthis.inputView = inputLen > 0 ? new Float32Array(buffer, inputPtr, inputLen) : new Float32Array(0);\n\t\tthis.snapshotView = snapshotLen > 0 ? new Float32Array(buffer, snapshotPtr, snapshotLen) : new Float32Array(0);\n\t\tthis.eventView = eventLen > 0 ? new Float32Array(buffer, eventPtr, eventLen) : new Float32Array(0);\n\t\tthis.poseView = poseLen > 0 ? new Float32Array(buffer, posePtr, poseLen) : new Float32Array(0);\n\t\tthis.vec3View = vec3Ptr !== 0 ? new Float32Array(buffer, vec3Ptr, 3) : new Float32Array(0);\n\t\tthis.queryView = queryLen > 0 ? new Float32Array(buffer, queryPtr, queryLen) : new Float32Array(0);\n\t\tthis.scratchView = scratchCap > 0 ? new Float32Array(buffer, scratchPtr, scratchCap) : new Float32Array(0);\n\t}\n\n\t/** Step the simulation by `dt` seconds. Refreshes views afterwards. */\n\tstep(dt: number): number {\n\t\tconst active = this.exports.zylem_stage_step(dt);\n\t\tthis.refreshViews();\n\t\treturn active;\n\t}\n\n\tdispose(): void {\n\t\tthis.exports.zylem_stage_destroy();\n\t}\n\n\tget tickCount(): number {\n\t\treturn this.exports.zylem_stage_tick_count() >>> 0;\n\t}\n\n\tget activeCount(): number {\n\t\treturn this.exports.zylem_stage_active_count() >>> 0;\n\t}\n\n\tsetGravity(x: number, y: number, z: number): void {\n\t\tthis.exports.zylem_stage_set_gravity(x, y, z);\n\t}\n\n\t/**\n\t * Toggle per-step collision-event collection in the wasm stage. Hosts\n\t * with no collision listeners should disable it — with thousands of\n\t * touching bodies the per-step contact-pair hashing is a significant\n\t * fraction of `step()`.\n\t */\n\tsetEventsEnabled(enabled: boolean): void {\n\t\tthis.exports.zylem_stage_set_events_enabled(enabled ? 1 : 0);\n\t}\n\n\t/** Cap Rapier contact solver iterations (default 4). */\n\tsetSolverIterations(iterations: number): void {\n\t\tthis.exports.zylem_stage_set_solver_iterations(Math.max(1, iterations | 0));\n\t}\n\n\t/**\n\t * Override sleep activation thresholds for sleep-capable dynamic bodies.\n\t * Higher velocity thresholds / lower `timeUntilSleep` put piles to sleep\n\t * sooner.\n\t */\n\tsetSleepThresholds(\n\t\tnormalizedLinearThreshold: number,\n\t\tangularThreshold: number,\n\t\ttimeUntilSleep: number,\n\t): void {\n\t\tthis.exports.zylem_stage_set_sleep_thresholds(\n\t\t\tnormalizedLinearThreshold,\n\t\t\tangularThreshold,\n\t\t\ttimeUntilSleep,\n\t\t);\n\t}\n\n\t/** Number of awake (non-sleeping) dynamic rigid bodies. */\n\tawakeDynamicCount(): number {\n\t\treturn this.exports.zylem_stage_awake_dynamic_count();\n\t}\n\n\t// ─── Entity lifecycle ───────────────────────────────────────────────\n\n\tcreateEntity(): number {\n\t\tconst slot = this.exports.zylem_stage_create_entity() >>> 0;\n\t\t// The wasm may have grown memory while resizing the slot table; refresh views.\n\t\tthis.refreshViews();\n\t\treturn slot;\n\t}\n\n\tdestroyEntity(slot: number): boolean {\n\t\treturn this.exports.zylem_stage_destroy_entity(slot) !== 0;\n\t}\n\n\t// ─── Body / collider attach ────────────────────────────────────────\n\n\tattachBody(slot: number, config: StageBodyConfig): boolean {\n\t\tconst ok = this.exports.zylem_stage_attach_body(\n\t\t\tslot,\n\t\t\tconfig.kind,\n\t\t\tconfig.position[0], config.position[1], config.position[2],\n\t\t\tconfig.rotation[0], config.rotation[1], config.rotation[2], config.rotation[3],\n\t\t\tconfig.linearDamping,\n\t\t\tconfig.angularDamping,\n\t\t\tconfig.gravityScale,\n\t\t\tconfig.canSleep ? 1 : 0,\n\t\t\tconfig.ccdEnabled ? 1 : 0,\n\t\t\tconfig.lockRotation[0] ? 1 : 0, config.lockRotation[1] ? 1 : 0, config.lockRotation[2] ? 1 : 0,\n\t\t\tconfig.lockTranslation[0] ? 1 : 0, config.lockTranslation[1] ? 1 : 0, config.lockTranslation[2] ? 1 : 0,\n\t\t);\n\t\treturn ok !== 0;\n\t}\n\n\taddCollider(slot: number, config: StageColliderConfig): boolean {\n\t\tconst offset = config.offset;\n\t\tconst sensor = config.sensor ? 1 : 0;\n\t\tconst groups = config.collisionGroups >>> 0;\n\t\tconst friction = config.friction;\n\t\tconst restitution = config.restitution;\n\t\tswitch (config.shape.type) {\n\t\t\tcase 'box': {\n\t\t\t\tconst [hx, hy, hz] = config.shape.halfExtents;\n\t\t\t\treturn (\n\t\t\t\t\tthis.exports.zylem_stage_add_collider_box(\n\t\t\t\t\t\tslot, hx, hy, hz, offset[0], offset[1], offset[2],\n\t\t\t\t\t\tfriction, restitution, sensor, groups,\n\t\t\t\t\t) !== 0\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase 'sphere': {\n\t\t\t\treturn (\n\t\t\t\t\tthis.exports.zylem_stage_add_collider_sphere(\n\t\t\t\t\t\tslot, config.shape.radius, offset[0], offset[1], offset[2],\n\t\t\t\t\t\tfriction, restitution, sensor, groups,\n\t\t\t\t\t) !== 0\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase 'capsule': {\n\t\t\t\treturn (\n\t\t\t\t\tthis.exports.zylem_stage_add_collider_capsule(\n\t\t\t\t\t\tslot, config.shape.halfHeight, config.shape.radius,\n\t\t\t\t\t\toffset[0], offset[1], offset[2], friction, restitution, sensor, groups,\n\t\t\t\t\t) !== 0\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase 'cylinder': {\n\t\t\t\treturn (\n\t\t\t\t\tthis.exports.zylem_stage_add_collider_cylinder(\n\t\t\t\t\t\tslot, config.shape.halfHeight, config.shape.radius,\n\t\t\t\t\t\toffset[0], offset[1], offset[2], friction, restitution, sensor, groups,\n\t\t\t\t\t) !== 0\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase 'cone': {\n\t\t\t\treturn (\n\t\t\t\t\tthis.exports.zylem_stage_add_collider_cone(\n\t\t\t\t\t\tslot, config.shape.halfHeight, config.shape.radius,\n\t\t\t\t\t\toffset[0], offset[1], offset[2], friction, restitution, sensor, groups,\n\t\t\t\t\t) !== 0\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase 'convexHull': {\n\t\t\t\tconst verts = config.shape.vertices;\n\t\t\t\tif (verts.length % 3 !== 0) return false;\n\t\t\t\tconst offsetFloats = this.stageScratch(verts);\n\t\t\t\treturn (\n\t\t\t\t\tthis.exports.zylem_stage_add_collider_convex_hull(\n\t\t\t\t\t\tslot, offsetFloats, verts.length / 3,\n\t\t\t\t\t\toffset[0], offset[1], offset[2], friction, restitution, sensor, groups,\n\t\t\t\t\t) !== 0\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase 'trimesh': {\n\t\t\t\tconst verts = config.shape.vertices;\n\t\t\t\tconst indices = config.shape.indices;\n\t\t\t\tif (verts.length % 3 !== 0 || indices.length % 3 !== 0) return false;\n\t\t\t\tconst vertOffset = this.stageScratch(verts);\n\t\t\t\tconst indexOffset = this.stageScratchIndices(indices, vertOffset + verts.length);\n\t\t\t\treturn (\n\t\t\t\t\tthis.exports.zylem_stage_add_collider_trimesh(\n\t\t\t\t\t\tslot, vertOffset, verts.length / 3, indexOffset, indices.length,\n\t\t\t\t\t\toffset[0], offset[1], offset[2], friction, restitution, sensor, groups,\n\t\t\t\t\t) !== 0\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase 'heightfield': {\n\t\t\t\tconst heights = config.shape.heights;\n\t\t\t\tconst heightOffset = this.stageScratch(heights);\n\t\t\t\treturn (\n\t\t\t\t\tthis.exports.zylem_stage_add_collider_heightfield(\n\t\t\t\t\t\tslot, config.shape.rows, config.shape.cols,\n\t\t\t\t\t\tconfig.shape.scale[0], config.shape.scale[1], config.shape.scale[2],\n\t\t\t\t\t\theightOffset, offset[0], offset[1], offset[2],\n\t\t\t\t\t\tfriction, restitution, sensor, groups,\n\t\t\t\t\t) !== 0\n\t\t\t\t);\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconst _exhaustive: never = config.shape;\n\t\t\t\tvoid _exhaustive;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate stageScratch(values: Float32Array, baseOffset = 0): number {\n\t\tthis.scratchView.set(values, baseOffset);\n\t\treturn baseOffset;\n\t}\n\n\tprivate stageScratchIndices(indices: Uint32Array, baseOffset: number): number {\n\t\tfor (let i = 0; i < indices.length; i++) {\n\t\t\tthis.scratchView[baseOffset + i] = indices[i]!;\n\t\t}\n\t\treturn baseOffset;\n\t}\n\n\t// ─── Pose / velocity ───────────────────────────────────────────────\n\n\tgetPose(slot: number, out?: StagePose): StagePose | null {\n\t\tconst ok = this.exports.zylem_stage_get_pose(slot) !== 0;\n\t\tif (!ok) return null;\n\t\tconst v = this.poseView;\n\t\tconst result: StagePose = out ?? {\n\t\t\tposition: [0, 0, 0],\n\t\t\trotation: [0, 0, 0, 1],\n\t\t};\n\t\tresult.position[0] = v[0]!;\n\t\tresult.position[1] = v[1]!;\n\t\tresult.position[2] = v[2]!;\n\t\tresult.rotation[0] = v[3]!;\n\t\tresult.rotation[1] = v[4]!;\n\t\tresult.rotation[2] = v[5]!;\n\t\tresult.rotation[3] = v[6]!;\n\t\treturn result;\n\t}\n\n\tsetPosition(slot: number, x: number, y: number, z: number): boolean {\n\t\treturn this.exports.zylem_stage_set_position(slot, x, y, z) !== 0;\n\t}\n\n\tsetRotation(slot: number, x: number, y: number, z: number, w: number): boolean {\n\t\treturn this.exports.zylem_stage_set_rotation(slot, x, y, z, w) !== 0;\n\t}\n\n\tsetLinearVelocity(slot: number, x: number, y: number, z: number): boolean {\n\t\treturn this.exports.zylem_stage_set_linvel(slot, x, y, z) !== 0;\n\t}\n\n\tgetLinearVelocity(slot: number, out?: [number, number, number]): [number, number, number] | null {\n\t\tif (this.exports.zylem_stage_get_linvel(slot) === 0) return null;\n\t\tconst v = this.vec3View;\n\t\tconst result = out ?? ([0, 0, 0] as [number, number, number]);\n\t\tresult[0] = v[0]!;\n\t\tresult[1] = v[1]!;\n\t\tresult[2] = v[2]!;\n\t\treturn result;\n\t}\n\n\tsetAngularVelocity(slot: number, x: number, y: number, z: number): boolean {\n\t\treturn this.exports.zylem_stage_set_angvel(slot, x, y, z) !== 0;\n\t}\n\n\tgetAngularVelocity(slot: number, out?: [number, number, number]): [number, number, number] | null {\n\t\tif (this.exports.zylem_stage_get_angvel(slot) === 0) return null;\n\t\tconst v = this.vec3View;\n\t\tconst result = out ?? ([0, 0, 0] as [number, number, number]);\n\t\tresult[0] = v[0]!;\n\t\tresult[1] = v[1]!;\n\t\tresult[2] = v[2]!;\n\t\treturn result;\n\t}\n\n\tapplyImpulse(slot: number, x: number, y: number, z: number): boolean {\n\t\treturn this.exports.zylem_stage_apply_impulse(slot, x, y, z) !== 0;\n\t}\n\n\t// ─── Queries / diagnostics ─────────────────────────────────────────\n\n\t/** Cast a ray against the physics world. Returns the closest hit or `null`. */\n\tcastRay(\n\t\torigin: readonly [number, number, number],\n\t\tdir: readonly [number, number, number],\n\t\tmaxDistance: number,\n\t\tsolidOnly = true,\n\t): StageRaycastHit | null {\n\t\tconst hit = this.exports.zylem_stage_cast_ray(\n\t\t\torigin[0], origin[1], origin[2],\n\t\t\tdir[0], dir[1], dir[2],\n\t\t\tmaxDistance, solidOnly ? 1 : 0,\n\t\t);\n\t\tif (hit === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn {\n\t\t\tslot: v[0]! >>> 0,\n\t\t\tdistance: v[1]!,\n\t\t\tnormal: [v[2]!, v[3]!, v[4]!],\n\t\t};\n\t}\n\n\t/** Body introspection for debug tooling. */\n\tgetBodyInfo(slot: number): StageBodyInfo | null {\n\t\tif (this.exports.zylem_stage_body_info(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn {\n\t\t\tbodyType: v[0]! | 0,\n\t\t\tmass: v[1]!,\n\t\t\tisSleeping: v[2]! > 0.5,\n\t\t\tisEnabled: v[3]! > 0.5,\n\t\t\tlinearVelocity: [v[4]!, v[5]!, v[6]!],\n\t\t};\n\t}\n\n\t/** Wireframe debug render of every collider (all shapes). */\n\tgetDebugRender(): StageDebugRender | null {\n\t\tconst vertexCount = this.exports.zylem_stage_debug_render() >>> 0;\n\t\tthis.refreshViews();\n\t\tif (vertexCount === 0) return null;\n\t\tconst buffer = this.memory.buffer;\n\t\tconst vertices = new Float32Array(\n\t\t\tbuffer,\n\t\t\tthis.exports.zylem_stage_debug_vertices_ptr(),\n\t\t\tthis.exports.zylem_stage_debug_vertices_len(),\n\t\t);\n\t\tconst colors = new Float32Array(\n\t\t\tbuffer,\n\t\t\tthis.exports.zylem_stage_debug_colors_ptr(),\n\t\t\tthis.exports.zylem_stage_debug_colors_len(),\n\t\t);\n\t\treturn {\n\t\t\tvertices: new Float32Array(vertices),\n\t\t\tcolors: new Float32Array(colors),\n\t\t};\n\t}\n\n\t// ─── Render / event reads ──────────────────────────────────────────\n\n\t/** Read-only view over the render buffer; one slot occupies {@link STAGE_RENDER_STRIDE} floats. */\n\tget render(): Float32Array {\n\t\treturn this.renderView;\n\t}\n\n\tget renderStride(): number {\n\t\treturn STAGE_RENDER_STRIDE;\n\t}\n\n\t/**\n\t * Decode a single entity slot from the live render buffer. Convenience\n\t * wrapper over {@link readStageRenderSlot} bound to this runtime's view.\n\t */\n\treadRenderSlot(slot: number, out?: StageRenderSlot): StageRenderSlot | null {\n\t\treturn readStageRenderSlot(this.renderView, slot, out);\n\t}\n\n\t/** Drain the wasm event buffer into a fresh array of typed events. */\n\tdrainEvents(): StageEvent[] {\n\t\tconst count = this.exports.zylem_stage_event_count() >>> 0;\n\t\tif (count === 0) return [];\n\t\tconst view = this.eventView;\n\t\tconst events: StageEvent[] = new Array(count);\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tconst base = i * STAGE_EVENT_STRIDE;\n\t\t\tconst primaryRaw = view[base + 1]!;\n\t\t\tconst secondaryRaw = view[base + 2]!;\n\t\t\tevents[i] = {\n\t\t\t\ttype: (view[base]! | 0) as StageEventTypeValue,\n\t\t\t\tprimarySlot: Number.isNaN(primaryRaw) ? null : primaryRaw >>> 0,\n\t\t\t\tsecondarySlot: Number.isNaN(secondaryRaw) ? null : secondaryRaw >>> 0,\n\t\t\t\tpayload: [view[base + 3]!, view[base + 4]!, view[base + 5]!],\n\t\t\t};\n\t\t}\n\t\treturn events;\n\t}\n\n\t// ─── Batched input / snapshot buffers ─────────────────────────────\n\n\t/** Writable view over the slot-indexed input buffer ({@link STAGE_INPUT_STRIDE} floats/slot). */\n\tget input(): Float32Array {\n\t\treturn this.inputView;\n\t}\n\n\tget inputStride(): number {\n\t\treturn STAGE_INPUT_STRIDE;\n\t}\n\n\t/** Read-only view over the per-slot behavior snapshot buffer ({@link STAGE_SNAPSHOT_STRIDE} floats/slot). */\n\tget snapshot(): Float32Array {\n\t\treturn this.snapshotView;\n\t}\n\n\tget snapshotStride(): number {\n\t\treturn STAGE_SNAPSHOT_STRIDE;\n\t}\n\n\t/**\n\t * Write the primary movement axes for a slot into the slot-indexed input\n\t * buffer and mark the slot dirty. Field-scoped (doesn't touch look\n\t * deltas or buttons) so multiple behaviors composed on one entity can\n\t * each write their part.\n\t */\n\twriteInputAxes(slot: number, axisA: number, axisB: number): boolean {\n\t\tconst base = slot * STAGE_INPUT_STRIDE;\n\t\tconst view = this.inputView;\n\t\tif (slot < 0 || base + STAGE_INPUT_STRIDE > view.length) return false;\n\t\tview[base] = axisA;\n\t\tview[base + 1] = axisB;\n\t\tview[base + 7] = 1;\n\t\treturn true;\n\t}\n\n\t/** Write the look deltas (first-person yaw/pitch) for a slot. */\n\twriteInputLook(slot: number, yawDelta: number, pitchDelta: number): boolean {\n\t\tconst base = slot * STAGE_INPUT_STRIDE;\n\t\tconst view = this.inputView;\n\t\tif (slot < 0 || base + STAGE_INPUT_STRIDE > view.length) return false;\n\t\tview[base + 2] = yawDelta;\n\t\tview[base + 3] = pitchDelta;\n\t\tview[base + 7] = 1;\n\t\treturn true;\n\t}\n\n\t/** Write reserved input slots (thruster world-space vector X/Y). */\n\twriteInputReserved(slot: number, reservedA: number, reservedB: number): boolean {\n\t\tconst base = slot * STAGE_INPUT_STRIDE;\n\t\tconst view = this.inputView;\n\t\tif (slot < 0 || base + STAGE_INPUT_STRIDE > view.length) return false;\n\t\tview[base + 5] = reservedA;\n\t\tview[base + 6] = reservedB;\n\t\tview[base + 7] = 1;\n\t\treturn true;\n\t}\n\n\t/**\n\t * Set or clear one button bit ({@link STAGE_INPUT_BUTTON_JUMP} /\n\t * {@link STAGE_INPUT_BUTTON_RUN}) in a slot's input bitmask.\n\t */\n\twriteInputButton(slot: number, buttonMask: number, pressed: boolean): boolean {\n\t\tconst base = slot * STAGE_INPUT_STRIDE;\n\t\tconst view = this.inputView;\n\t\tif (slot < 0 || base + STAGE_INPUT_STRIDE > view.length) return false;\n\t\tconst current = view[base + 4]! | 0;\n\t\tview[base + 4] = pressed ? (current | buttonMask) : (current & ~buttonMask);\n\t\tview[base + 7] = 1;\n\t\treturn true;\n\t}\n\n\t/**\n\t * Decode a slot's behavior snapshot from the buffer written at the end of\n\t * the previous step. Returns `null` when the slot has no behavior data.\n\t */\n\treadSnapshot(slot: number, out?: StageBehaviorSnapshot): StageBehaviorSnapshot | null {\n\t\tconst base = slot * STAGE_SNAPSHOT_STRIDE;\n\t\tconst view = this.snapshotView;\n\t\tif (slot < 0 || base + STAGE_SNAPSHOT_STRIDE > view.length) return null;\n\t\tif (view[base + 7] === 0) return null;\n\t\tconst result: StageBehaviorSnapshot = out ?? {\n\t\t\tgrounded: false,\n\t\t\tfsmState: 0,\n\t\t\tjumpCount: 0,\n\t\t\tverticalVelocity: 0,\n\t\t\tspeed: 0,\n\t\t\tyaw: 0,\n\t\t\tpitch: 0,\n\t\t};\n\t\tresult.grounded = view[base]! > 0.5;\n\t\tresult.fsmState = view[base + 1]! | 0;\n\t\tresult.jumpCount = view[base + 2]! | 0;\n\t\tresult.verticalVelocity = view[base + 3]!;\n\t\tresult.speed = view[base + 4]!;\n\t\tresult.yaw = view[base + 5]!;\n\t\tresult.pitch = view[base + 6]!;\n\t\treturn result;\n\t}\n\n\t// ─── Behavior helpers ─────────────────────────────────────────────\n\n\tget queryScratch(): Float32Array {\n\t\treturn this.queryView;\n\t}\n\n\tattachCooldown(slot: number): boolean {\n\t\treturn this.exports.zylem_stage_attach_cooldown(slot) !== 0;\n\t}\n\n\tregisterCooldown(slot: number, id: number, durationSeconds: number, immediate = false): boolean {\n\t\treturn (\n\t\t\tthis.exports.zylem_stage_cooldown_register(slot, id >>> 0, durationSeconds, immediate ? 1 : 0) !== 0\n\t\t);\n\t}\n\n\tfireCooldown(slot: number, id: number): boolean {\n\t\treturn this.exports.zylem_stage_cooldown_fire(slot, id >>> 0) !== 0;\n\t}\n\n\tresetCooldown(slot: number, id: number): boolean {\n\t\treturn this.exports.zylem_stage_cooldown_reset(slot, id >>> 0) !== 0;\n\t}\n\n\tcooldownRemaining(slot: number, id: number): number {\n\t\treturn this.exports.zylem_stage_cooldown_remaining(slot, id >>> 0);\n\t}\n\n\tattachWorldBoundary(\n\t\tslot: number,\n\t\tdim: StageBoundaryDimValue,\n\t\tbounds: StageWorldBoundaryOptions,\n\t): boolean {\n\t\treturn (\n\t\t\tthis.exports.zylem_stage_attach_world_boundary(\n\t\t\t\tslot,\n\t\t\t\tdim,\n\t\t\t\tbounds.top, bounds.bottom, bounds.left, bounds.right,\n\t\t\t\tbounds.front ?? 0, bounds.back ?? 0, bounds.padding ?? 0,\n\t\t\t) !== 0\n\t\t);\n\t}\n\n\tqueryWorldBoundary(slot: number): { hits: number; clamped: [number, number, number] } | null {\n\t\tif (this.exports.zylem_stage_query_world_boundary(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn {\n\t\t\thits: v[0]! | 0,\n\t\t\tclamped: [v[1]!, v[2]!, v[3]!],\n\t\t};\n\t}\n\n\tattachScreenWrap(slot: number, opts: StageScreenWrapOptions): boolean {\n\t\treturn (\n\t\t\tthis.exports.zylem_stage_attach_screen_wrap(\n\t\t\t\tslot, opts.width, opts.height,\n\t\t\t\topts.centerX ?? 0, opts.centerY ?? 0, opts.edgeThreshold ?? 0,\n\t\t\t) !== 0\n\t\t);\n\t}\n\n\tqueryScreenWrap(slot: number): { fsm: number; lastWrappedAxes: number } | null {\n\t\tif (this.exports.zylem_stage_query_screen_wrap(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn { fsm: v[0]! | 0, lastWrappedAxes: v[1]! | 0 };\n\t}\n\n\tattachRicochet(\n\t\tslot: number,\n\t\tdim: StageRicochetDimValue,\n\t\topts: StageRicochetOptions,\n\t): boolean {\n\t\treturn (\n\t\t\tthis.exports.zylem_stage_attach_ricochet(\n\t\t\t\tslot, dim, opts.minSpeed, opts.maxSpeed, opts.speedMultiplier,\n\t\t\t\topts.maxAngleDeg, opts.reflectionMode,\n\t\t\t) !== 0\n\t\t);\n\t}\n\n\tqueryRicochet(slot: number): { bounces: number; lastKind: number } | null {\n\t\tif (this.exports.zylem_stage_query_ricochet(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn { bounces: v[0]! | 0, lastKind: v[1]! | 0 };\n\t}\n\n\tattachThruster(slot: number, opts: StageThrusterOptions): boolean {\n\t\treturn (\n\t\t\tthis.exports.zylem_stage_attach_thruster(\n\t\t\t\tslot, opts.maxSpeed, opts.acceleration, opts.turnRateRadPerSec, opts.linearDamping,\n\t\t\t) !== 0\n\t\t);\n\t}\n\n\tsetThrusterInput(\n\t\tslot: number,\n\t\tthrust: number,\n\t\tturn: number,\n\t\tvectorX = 0,\n\t\tvectorY = 0,\n\t): void {\n\t\tthis.exports.zylem_stage_set_thruster_input(slot, thrust, turn, vectorX, vectorY);\n\t}\n\n\tqueryThruster(slot: number): { headingRad: number; speed: number } | null {\n\t\tif (this.exports.zylem_stage_query_thruster(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn { headingRad: v[0]!, speed: v[1]! };\n\t}\n\n\tattachTopDown(slot: number, opts: StageTopDownOptions): boolean {\n\t\treturn this.exports.zylem_stage_attach_top_down(slot, opts.plane, opts.speed, opts.faceMovement ? 1 : 0) !== 0;\n\t}\n\n\tsetTopDownInput(slot: number, axisA: number, axisB: number): void {\n\t\tthis.exports.zylem_stage_set_top_down_input(slot, axisA, axisB);\n\t}\n\n\tattachJumper2D(slot: number, opts: StageJumper2DOptions): boolean {\n\t\treturn (\n\t\t\tthis.exports.zylem_stage_attach_jumper_2d(\n\t\t\t\tslot, opts.jumpForce, opts.maxJumps >>> 0,\n\t\t\t\topts.jumpBufferTime, opts.coyoteTime, opts.gravity,\n\t\t\t) !== 0\n\t\t);\n\t}\n\n\tsetJumper2DInput(slot: number, jumpPressed: boolean): void {\n\t\tthis.exports.zylem_stage_set_jumper_2d_input(slot, jumpPressed ? 1 : 0);\n\t}\n\n\tqueryJumper2D(slot: number): { grounded: boolean; jumpCount: number; coyote: number; jumpBuffer: number } | null {\n\t\tif (this.exports.zylem_stage_query_jumper_2d(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn {\n\t\t\tgrounded: v[0]! > 0.5,\n\t\t\tjumpCount: v[1]! | 0,\n\t\t\tcoyote: v[2]!,\n\t\t\tjumpBuffer: v[3]!,\n\t\t};\n\t}\n\n\tattachJumper3D(slot: number, opts: StageJumper3DOptions): boolean {\n\t\treturn this.exports.zylem_stage_attach_jumper_3d(\n\t\t\tslot, opts.jumpForce, opts.maxJumps >>> 0, opts.gravity,\n\t\t\topts.coyoteTime ?? 0.1, opts.jumpBufferTime ?? 0.08,\n\t\t) !== 0;\n\t}\n\n\tsetJumper3DInput(slot: number, jump: boolean): void {\n\t\tthis.exports.zylem_stage_set_jumper_3d_input(slot, jump ? 1 : 0);\n\t}\n\n\tqueryJumper3D(slot: number): { grounded: boolean; jumpCount: number; verticalVelocity: number } | null {\n\t\tif (this.exports.zylem_stage_query_jumper_3d(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn { grounded: v[0]! > 0.5, jumpCount: v[1]! | 0, verticalVelocity: v[2]! };\n\t}\n\n\tattachShooter2D(slot: number, opts: StageShooter2DOptions): boolean {\n\t\treturn (\n\t\t\tthis.exports.zylem_stage_attach_shooter_2d(\n\t\t\t\tslot, opts.fireRateHz, opts.muzzleOffsetX, opts.muzzleOffsetY, opts.muzzleSpeed,\n\t\t\t) !== 0\n\t\t);\n\t}\n\n\tfireShooter2D(slot: number, x: number, y: number, z: number, yaw: number): boolean {\n\t\treturn this.exports.zylem_stage_shooter_2d_fire(slot, x, y, z, yaw) !== 0;\n\t}\n\n\tqueryShooter2D(slot: number): { cooldown: number; firedCount: number } | null {\n\t\tif (this.exports.zylem_stage_query_shooter_2d(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn { cooldown: v[0]!, firedCount: v[1]! | 0 };\n\t}\n\n\tattachPlatformer3D(slot: number, opts: StagePlatformer3DOptions): boolean {\n\t\treturn (\n\t\t\tthis.exports.zylem_stage_attach_platformer_3d(\n\t\t\t\tslot, opts.halfHeight, opts.radius,\n\t\t\t\topts.walkSpeed, opts.runSpeed, opts.jumpForce,\n\t\t\t\topts.maxJumps >>> 0, opts.gravity,\n\t\t\t\topts.coyoteTime ?? 0.1, opts.jumpBufferTime ?? 0.1,\n\t\t\t\topts.jumpCutMultiplier ?? 0.5, opts.multiJumpWindow ?? 0.15,\n\t\t\t\topts.slopeClimbAngle ?? 50, opts.slopeSlideAngle ?? 40,\n\t\t\t\topts.autostepHeight ?? 0.3, opts.autostepMinWidth ?? 0.1,\n\t\t\t\topts.snapToGroundDistance ?? 0.3, opts.characterOffset ?? 0.05,\n\t\t\t\topts.offsetX ?? 0, opts.offsetY ?? 0, opts.offsetZ ?? 0,\n\t\t\t\topts.shapeSource ?? StagePlatformerShapeSource.Auto,\n\t\t\t) !== 0\n\t\t);\n\t}\n\n\tsetPlatformer3DInputAxes(slot: number, moveX: number, moveZ: number): void {\n\t\tthis.exports.zylem_stage_set_platformer_3d_input_axes(slot, moveX, moveZ);\n\t}\n\n\tsetPlatformer3DInputButtons(slot: number, jump: boolean, run: boolean): void {\n\t\tthis.exports.zylem_stage_set_platformer_3d_input_buttons(slot, jump ? 1 : 0, run ? 1 : 0);\n\t}\n\n\tqueryPlatformer3D(slot: number): { grounded: boolean; jumpCount: number; fsmState: number; speed: number } | null {\n\t\tif (this.exports.zylem_stage_query_platformer_3d(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn {\n\t\t\tgrounded: v[0]! > 0.5,\n\t\t\tjumpCount: v[1]! | 0,\n\t\t\tfsmState: v[2]! | 0,\n\t\t\tspeed: v[3]!,\n\t\t};\n\t}\n\n\tattachPlatformer2D(slot: number, opts: StagePlatformer2DOptions): boolean {\n\t\treturn (\n\t\t\tthis.exports.zylem_stage_attach_platformer_2d(\n\t\t\t\tslot, opts.halfHeight, opts.radius,\n\t\t\t\topts.walkSpeed, opts.runSpeed, opts.jumpForce,\n\t\t\t\topts.maxJumps >>> 0, opts.gravity,\n\t\t\t\topts.coyoteTime ?? 0.1, opts.jumpBufferTime ?? 0.1,\n\t\t\t\topts.jumpCutMultiplier ?? 0.5, opts.multiJumpWindow ?? 0.15,\n\t\t\t\topts.slopeClimbAngle ?? 50, opts.slopeSlideAngle ?? 40,\n\t\t\t\topts.autostepHeight ?? 0.25, opts.autostepMinWidth ?? 0.05,\n\t\t\t\topts.snapToGroundDistance ?? 0.2, opts.characterOffset ?? 0.05,\n\t\t\t\topts.offsetX ?? 0, opts.offsetY ?? 0, opts.offsetZ ?? 0,\n\t\t\t\topts.shapeSource ?? StagePlatformerShapeSource.Auto,\n\t\t\t) !== 0\n\t\t);\n\t}\n\n\tsetPlatformer2DInputAxes(slot: number, moveX: number): void {\n\t\tthis.exports.zylem_stage_set_platformer_2d_input_axes(slot, moveX);\n\t}\n\n\tsetPlatformer2DInputButtons(slot: number, jump: boolean, run: boolean): void {\n\t\tthis.exports.zylem_stage_set_platformer_2d_input_buttons(slot, jump ? 1 : 0, run ? 1 : 0);\n\t}\n\n\tqueryPlatformer2D(slot: number): { grounded: boolean; jumpCount: number; fsmState: number; verticalVelocity: number } | null {\n\t\tif (this.exports.zylem_stage_query_platformer_2d(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn {\n\t\t\tgrounded: v[0]! > 0.5,\n\t\t\tjumpCount: v[1]! | 0,\n\t\t\tfsmState: v[2]! | 0,\n\t\t\tverticalVelocity: v[3]!,\n\t\t};\n\t}\n\n\tattachFirstPerson(slot: number, opts: StageFirstPersonOptions): boolean {\n\t\treturn (\n\t\t\tthis.exports.zylem_stage_attach_first_person(\n\t\t\t\tslot, opts.walkSpeed, opts.runSpeed, opts.eyeHeight, opts.lookSensitivity,\n\t\t\t) !== 0\n\t\t);\n\t}\n\n\tsetFirstPersonInput(slot: number, input: StageFirstPersonInput): void {\n\t\tthis.exports.zylem_stage_set_first_person_input(\n\t\t\tslot, input.moveX, input.moveZ, input.lookYawDelta, input.lookPitchDelta, input.run ? 1 : 0,\n\t\t);\n\t}\n\n\tqueryFirstPerson(slot: number): { yaw: number; pitch: number; speed: number; eyeHeight: number } | null {\n\t\tif (this.exports.zylem_stage_query_first_person(slot) === 0) return null;\n\t\tconst v = this.queryView;\n\t\treturn { yaw: v[0]!, pitch: v[1]!, speed: v[2]!, eyeHeight: v[3]! };\n\t}\n}\n\n/**\n * Load the bundled `@zylem/runtime` wasm (or a custom `source`), instantiate\n * it, and construct a `WasmStageRuntime` around the exports.\n */\nexport async function createWasmStageRuntime(\n\toptions: WasmStageRuntimeOptions = {},\n): Promise<WasmStageRuntime> {\n\tconst { exports } = await loadStageFfi({\n\t\tsource: options.source,\n\t\timports: options.imports,\n\t});\n\treturn new WasmStageRuntime(exports, options);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-EZNCCO4L.js";
|
|
4
4
|
|
|
5
5
|
// src/lib/behaviors/cooldown/cooldown-store.ts
|
|
6
|
-
import { proxy } from "valtio";
|
|
6
|
+
import { proxy } from "valtio/vanilla";
|
|
7
7
|
var cooldownStore = proxy({});
|
|
8
8
|
function registerCooldown(name, duration, immediate = true) {
|
|
9
9
|
cooldownStore[name] = {
|
|
@@ -115,4 +115,4 @@ export {
|
|
|
115
115
|
getCooldownStore,
|
|
116
116
|
CooldownBehavior
|
|
117
117
|
};
|
|
118
|
-
//# sourceMappingURL=chunk-
|
|
118
|
+
//# sourceMappingURL=chunk-5XPPLTC7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/behaviors/cooldown/cooldown-store.ts","../src/lib/behaviors/cooldown/cooldown.descriptor.ts"],"sourcesContent":["import { proxy } from 'valtio/vanilla';\n\n/**\n * A single cooldown entry in the global store.\n */\nexport interface CooldownEntry {\n\t/** Identifier for this cooldown */\n\tname: string;\n\t/** Total cooldown time in seconds */\n\tduration: number;\n\t/** Time accumulated since last fire */\n\telapsed: number;\n\t/** Whether the cooldown is ready (elapsed >= duration) */\n\tready: boolean;\n\t/** Normalized progress 0..1 (0 = just fired, 1 = ready) */\n\tprogress: number;\n\t/** Whether this cooldown is currently counting down */\n\tactive: boolean;\n}\n\n/**\n * Global reactive cooldown registry (valtio proxy).\n * Accessible from entities, behaviors, and UI components.\n */\nconst cooldownStore = proxy<Record<string, CooldownEntry>>({});\n\n/**\n * Register a named cooldown in the global store.\n * If a cooldown with the same name already exists, it is overwritten.\n *\n * @param name Unique cooldown identifier\n * @param duration Cooldown duration in seconds\n * @param immediate If true, the cooldown starts ready (default: true)\n */\nexport function registerCooldown(\n\tname: string,\n\tduration: number,\n\timmediate: boolean = true,\n): void {\n\tcooldownStore[name] = {\n\t\tname,\n\t\tduration,\n\t\telapsed: immediate ? duration : 0,\n\t\tready: immediate,\n\t\tprogress: immediate ? 1 : 0,\n\t\tactive: !immediate,\n\t};\n}\n\n/**\n * Get a cooldown entry by name.\n * Returns undefined if the cooldown has not been registered.\n */\nexport function getCooldown(name: string): CooldownEntry | undefined {\n\treturn cooldownStore[name];\n}\n\n/**\n * Fire (trigger) a cooldown, resetting its timer.\n * Sets the cooldown to not-ready and starts the countdown.\n */\nexport function fireCooldown(name: string): void {\n\tconst entry = cooldownStore[name];\n\tif (!entry) return;\n\tentry.elapsed = 0;\n\tentry.ready = false;\n\tentry.progress = 0;\n\tentry.active = true;\n}\n\n/**\n * Force a cooldown to ready immediately.\n */\nexport function resetCooldown(name: string): void {\n\tconst entry = cooldownStore[name];\n\tif (!entry) return;\n\tentry.elapsed = entry.duration;\n\tentry.ready = true;\n\tentry.progress = 1;\n\tentry.active = false;\n}\n\n/**\n * Advance all active cooldowns by delta seconds.\n * Called once per frame by the CooldownBehavior system.\n */\nexport function tickCooldowns(delta: number): void {\n\tfor (const name in cooldownStore) {\n\t\tconst entry = cooldownStore[name];\n\t\tif (!entry.active) continue;\n\n\t\tentry.elapsed += delta;\n\t\tif (entry.elapsed >= entry.duration) {\n\t\t\tentry.elapsed = entry.duration;\n\t\t\tentry.ready = true;\n\t\t\tentry.progress = 1;\n\t\t\tentry.active = false;\n\t\t} else {\n\t\t\tentry.progress = entry.duration > 0 ? entry.elapsed / entry.duration : 1;\n\t\t}\n\t}\n}\n\n/**\n * Get the raw cooldown store (for advanced/debugging use).\n */\nexport function getCooldownStore(): Record<string, CooldownEntry> {\n\treturn cooldownStore;\n}\n","/**\n * CooldownBehavior\n *\n * A stage-scoped behavior that manages named cooldowns via the global CooldownStore.\n * Entities use this to register, check, and fire cooldowns.\n * UI components (CooldownIcon) can read from the same store.\n */\n\nimport { defineBehavior, type BehaviorRef } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport {\n\tregisterCooldown,\n\tgetCooldown,\n\tfireCooldown,\n\tresetCooldown,\n\ttickCooldowns,\n} from './cooldown-store';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Options\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface CooldownConfig {\n\t/** Duration in seconds */\n\tduration: number;\n\t/** Whether the cooldown starts ready (default: true) */\n\timmediate?: boolean;\n}\n\nexport interface CooldownOptions {\n\t/**\n\t * Named cooldowns to register.\n\t * Keys are the cooldown names, values are their config.\n\t */\n\tcooldowns: Record<string, CooldownConfig>;\n}\n\ninterface CompiledCooldownEntry {\n\tname: string;\n\tduration: number;\n\timmediate: boolean;\n}\n\nconst COOLDOWN_BEHAVIOR_KEY = Symbol.for('zylem:behavior:cooldown');\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Handle\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Handle methods returned by entity.use(CooldownBehavior, ...).\n */\nexport interface CooldownHandle {\n\t/** Check if a named cooldown is ready */\n\tisReady(name: string): boolean;\n\t/** Fire (trigger) a named cooldown, resetting its timer */\n\tfire(name: string): void;\n\t/** Force a cooldown to ready immediately */\n\treset(name: string): void;\n\t/** Get cooldown progress 0..1 (0 = just fired, 1 = ready) */\n\tgetProgress(name: string): number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// System\n// ─────────────────────────────────────────────────────────────────────────────\n\nclass CooldownSystem implements BehaviorSystem {\n\tconstructor(\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) { }\n\n\tupdate(_ecs: unknown, delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(COOLDOWN_BEHAVIOR_KEY);\n\t\tif (links) {\n\t\t\tfor (const link of links) {\n\t\t\t\tensureCooldownEntriesRegistered(link.ref as BehaviorRef<CooldownOptions>);\n\t\t\t}\n\t\t}\n\n\t\ttickCooldowns(delta);\n\t}\n\n\tdestroy(_ecs: unknown): void { }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Handle factory\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction createCooldownHandle(ref: BehaviorRef<CooldownOptions>): CooldownHandle {\n\tensureCooldownEntriesRegistered(ref);\n\n\treturn {\n\t\tisReady: (name: string) => getCooldown(name)?.ready ?? false,\n\t\tfire: (name: string) => fireCooldown(name),\n\t\treset: (name: string) => resetCooldown(name),\n\t\tgetProgress: (name: string) => getCooldown(name)?.progress ?? 1,\n\t};\n}\n\nfunction getCompiledCooldownEntries(\n\tref: BehaviorRef<CooldownOptions>,\n): CompiledCooldownEntry[] {\n\tconst compiled = (ref as any).__compiledCooldownEntries as CompiledCooldownEntry[] | undefined;\n\tif (compiled) return compiled;\n\n\tconst entries = Object.entries(ref.options.cooldowns).map(([name, config]) => ({\n\t\tname,\n\t\tduration: config.duration,\n\t\timmediate: config.immediate ?? true,\n\t}));\n\t(ref as any).__compiledCooldownEntries = entries;\n\treturn entries;\n}\n\nfunction ensureCooldownEntriesRegistered(ref: BehaviorRef<CooldownOptions>): void {\n\tif ((ref as any).__cooldownsRegistered) return;\n\n\tfor (const entry of getCompiledCooldownEntries(ref)) {\n\t\tregisterCooldown(entry.name, entry.duration, entry.immediate);\n\t}\n\n\t(ref as any).__cooldownsRegistered = true;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Behavior Definition\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * CooldownBehavior\n *\n * @example\n * ```ts\n * import { CooldownBehavior } from '@zylem/game-lib/behavior';\n * import { moveBy } from '@zylem/game-lib/actions';\n *\n * const hero = createBox({ ... });\n * const cd = hero.use(CooldownBehavior, {\n * cooldowns: {\n * attack: { duration: 5 },\n * dash: { duration: 2, immediate: false },\n * },\n * });\n *\n * hero.onUpdate(({ me, inputs }) => {\n * if (cd.isReady('attack') && inputs.p1.buttons.A.pressed) {\n * cd.fire('attack');\n * // perform attack\n * }\n * if (cd.isReady('dash') && inputs.p1.buttons.B.pressed) {\n * cd.fire('dash');\n * me.runAction(moveBy({ x: 10, duration: 0.3 }));\n * }\n * });\n * ```\n */\nexport const CooldownBehavior = defineBehavior<CooldownOptions, CooldownHandle>({\n\tname: 'cooldown',\n\tdefaultOptions: { cooldowns: {} },\n\tsystemFactory: (ctx) =>\n\t\tnew CooldownSystem(ctx.getBehaviorLinks),\n\tcreateHandle: createCooldownHandle,\n});\n"],"mappings":"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","names":[]}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
STAGE_INPUT_BUTTON_RUN,
|
|
16
16
|
readBehaviorSnapshot
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-4GW6DCYF.js";
|
|
18
18
|
import {
|
|
19
19
|
defineBehavior
|
|
20
20
|
} from "./chunk-EZNCCO4L.js";
|
|
@@ -301,4 +301,4 @@ export {
|
|
|
301
301
|
FirstPersonPresentation,
|
|
302
302
|
FirstPersonBehavior
|
|
303
303
|
};
|
|
304
|
-
//# sourceMappingURL=chunk-
|
|
304
|
+
//# sourceMappingURL=chunk-B2ERQ6HD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/behaviors/thruster/thruster-fsm.ts","../src/lib/behaviors/thruster/thruster.descriptor.ts"],"sourcesContent":["/**\n * ThrusterFSM\n * \n * State machine controller for thruster behavior.\n * FSM does NOT touch physics or ThrusterSystem - it only writes ThrusterInputComponent.\n */\n\nimport { SyncStateMachine, t } from '../../core/utility/sync-state-machine';\nimport type { ThrusterInputComponent } from './components';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM State Model\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport enum ThrusterState {\n\tIdle = 'idle',\n\tActive = 'active',\n\tBoosting = 'boosting',\n\tDisabled = 'disabled',\n\tDocked = 'docked',\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM Events\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport enum ThrusterEvent {\n\tActivate = 'activate',\n\tDeactivate = 'deactivate',\n\tBoost = 'boost',\n\tEndBoost = 'endBoost',\n\tDisable = 'disable',\n\tEnable = 'enable',\n\tDock = 'dock',\n\tUndock = 'undock',\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM Context Object\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface ThrusterFSMContext {\n\tinput: ThrusterInputComponent;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Player Input (raw input from controller/keyboard)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PlayerInput {\n\tthrust: number;\n\trotate: number;\n\tthrustX?: number;\n\tthrustY?: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// ThrusterFSM Controller\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport class ThrusterFSM {\n\tmachine: SyncStateMachine<ThrusterState, ThrusterEvent, never>;\n\n\tconstructor(private ctx: ThrusterFSMContext) {\n\t\tthis.machine = new SyncStateMachine<ThrusterState, ThrusterEvent, never>(\n\t\t\tThrusterState.Idle,\n\t\t\t[\n\t\t\t\t// Core transitions\n\t\t\t\tt(ThrusterState.Idle, ThrusterEvent.Activate, ThrusterState.Active),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Deactivate, ThrusterState.Idle),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Boost, ThrusterState.Boosting),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Disable, ThrusterState.Disabled),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Dock, ThrusterState.Docked),\n\t\t\t\tt(ThrusterState.Boosting, ThrusterEvent.EndBoost, ThrusterState.Active),\n\t\t\t\tt(ThrusterState.Boosting, ThrusterEvent.Disable, ThrusterState.Disabled),\n\t\t\t\tt(ThrusterState.Disabled, ThrusterEvent.Enable, ThrusterState.Idle),\n\t\t\t\tt(ThrusterState.Docked, ThrusterEvent.Undock, ThrusterState.Idle),\n\t\t\t\t// Self-transitions (no-ops for redundant events)\n\t\t\t\tt(ThrusterState.Idle, ThrusterEvent.Deactivate, ThrusterState.Idle),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Activate, ThrusterState.Active),\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Get current state\n\t */\n\tgetState(): ThrusterState {\n\t\treturn this.machine.getState();\n\t}\n\n\t/**\n\t * Dispatch an event to transition state\n\t */\n\tdispatch(event: ThrusterEvent): void {\n\t\tif (this.machine.can(event)) {\n\t\t\tthis.machine.syncDispatch(event);\n\t\t}\n\t}\n\n\t/**\n\t * Update FSM state based on player input.\n\t * Auto-transitions between Idle/Active to report current state.\n\t * Does NOT modify input - just observes and reports.\n\t */\n\tupdate(playerInput: PlayerInput): void {\n\t\tconst state = this.machine.getState();\n\t\tconst hasInput =\n\t\t\tMath.abs(playerInput.thrust) > 0.01\n\t\t\t|| Math.abs(playerInput.rotate) > 0.01\n\t\t\t|| Math.abs(playerInput.thrustX ?? 0) > 0.01\n\t\t\t|| Math.abs(playerInput.thrustY ?? 0) > 0.01;\n\n\t\t// Auto-transition to report state based on input\n\t\tif (hasInput && state === ThrusterState.Idle) {\n\t\t\tthis.dispatch(ThrusterEvent.Activate);\n\t\t} else if (!hasInput && state === ThrusterState.Active) {\n\t\t\tthis.dispatch(ThrusterEvent.Deactivate);\n\t\t}\n\t}\n}\n","/**\n * Thruster Behavior Descriptor\n *\n * Type-safe descriptor for the thruster behavior using the entity.use() API.\n * The wasm runtime owns the thruster simulation; this system attaches the\n * Rust behavior and forwards input into the slot-indexed input buffer.\n */\n\nimport { defineBehavior } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport {\n\tcreateThrusterInputComponent,\n\tcreateThrusterMovementComponent,\n\ttype ThrusterMovementComponent,\n\ttype ThrusterInputComponent,\n} from './components';\nimport type { BehaviorRuntime } from '../../runtime/wasm-stage-runtime';\n\n/**\n * Entity with thruster components (input written by the game, state owned by\n * the wasm runtime).\n */\nexport interface ThrusterEntity {\n\tthruster: ThrusterMovementComponent;\n\t$thruster: ThrusterInputComponent;\n}\n\n/**\n * Thruster behavior options (typed for entity.use() autocomplete)\n */\nexport interface ThrusterBehaviorOptions {\n\t/** Forward thrust force (default: 10) */\n\tlinearThrust: number;\n\t/** Rotation torque (default: 5) */\n\tangularThrust: number;\n\t/** Optional linear damping override */\n\tlinearDamping?: number;\n}\n\nconst defaultOptions: ThrusterBehaviorOptions = {\n\tlinearThrust: 10,\n\tangularThrust: 5,\n\tlinearDamping: undefined,\n};\n\nconst THRUSTER_BEHAVIOR_KEY = Symbol.for('zylem:behavior:thruster');\n\n/**\n * Adapter that forwards thruster input into the wasm runtime.\n *\n * The Rust `thruster` Stage behavior is the single simulation path: this\n * system attaches it once per entity and writes `$thruster` input into the\n * slot-indexed input buffer each frame.\n */\nclass ThrusterBehaviorSystem implements BehaviorSystem {\n\tprivate attachedRuntimeSlots = new Set<number>();\n\n\tconstructor(\n\t\tprivate wasmStage: BehaviorRuntime | null,\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) {}\n\n\tupdate(_ecs: unknown, _delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(THRUSTER_BEHAVIOR_KEY);\n\t\tif (!links) return;\n\n\t\tfor (const link of links) {\n\t\t\tconst gameEntity = link.entity as any;\n\t\t\tconst thrusterRef = link.ref as any;\n\n\t\t\tconst options = thrusterRef.options as ThrusterBehaviorOptions;\n\n\t\t\tif (!gameEntity.thruster) {\n\t\t\t\tgameEntity.thruster = createThrusterMovementComponent(\n\t\t\t\t\toptions.linearThrust,\n\t\t\t\t\toptions.angularThrust,\n\t\t\t\t\t{ linearDamping: options.linearDamping },\n\t\t\t\t) as ThrusterMovementComponent;\n\t\t\t}\n\n\t\t\tif (!gameEntity.$thruster) {\n\t\t\t\tgameEntity.$thruster = createThrusterInputComponent() as ThrusterInputComponent;\n\t\t\t}\n\n\t\t\tconst handle = (gameEntity.runtimeHandle ?? -1) as number;\n\t\t\tif (!this.wasmStage || handle < 0) continue;\n\n\t\t\tthis.ensureWasmAttached(handle, options);\n\t\t\tconst input = gameEntity.$thruster as ThrusterInputComponent | undefined;\n\t\t\tif (input) {\n\t\t\t\tthis.wasmStage.writeInputAxes(handle, input.thrust, input.rotate);\n\t\t\t\tthis.wasmStage.writeInputReserved(handle, input.thrustX, input.thrustY);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate ensureWasmAttached(handle: number, options: ThrusterBehaviorOptions): void {\n\t\tif (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;\n\t\tthis.wasmStage.attachThruster(handle, {\n\t\t\tmaxSpeed: 50,\n\t\t\tacceleration: options.linearThrust,\n\t\t\tturnRateRadPerSec: options.angularThrust,\n\t\t\tlinearDamping: options.linearDamping ?? 0,\n\t\t});\n\t\tthis.attachedRuntimeSlots.add(handle);\n\t}\n\n\tdestroy(_ecs: unknown): void {\n\t\tthis.attachedRuntimeSlots.clear();\n\t}\n}\n\n/**\n * ThrusterBehavior - typed descriptor for thruster movement.\n *\n * @example\n * ```typescript\n * import { ThrusterBehavior } from \"@zylem/game-lib/behavior\";\n *\n * const ship = createSprite({ ... });\n * ship.use(ThrusterBehavior, { linearThrust: 15, angularThrust: 8 });\n * ```\n */\nexport const ThrusterBehavior = defineBehavior<ThrusterBehaviorOptions, Record<string, never>, ThrusterEntity>({\n\tname: 'thruster',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew ThrusterBehaviorSystem(ctx.wasmStage ?? null, ctx.getBehaviorLinks),\n});\n"],"mappings":"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","names":["ThrusterState","ThrusterEvent"]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
StageRicochetDim,
|
|
7
7
|
StageRicochetReflection
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-4GW6DCYF.js";
|
|
9
9
|
import {
|
|
10
10
|
defineBehavior
|
|
11
11
|
} from "./chunk-EZNCCO4L.js";
|
|
@@ -419,4 +419,4 @@ export {
|
|
|
419
419
|
Ricochet2DFSM,
|
|
420
420
|
Ricochet2DBehavior
|
|
421
421
|
};
|
|
422
|
-
//# sourceMappingURL=chunk-
|
|
422
|
+
//# sourceMappingURL=chunk-D7N6SC4D.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
STAGE_INPUT_BUTTON_JUMP,
|
|
10
10
|
readBehaviorSnapshot
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-4GW6DCYF.js";
|
|
12
12
|
import {
|
|
13
13
|
defineBehavior
|
|
14
14
|
} from "./chunk-EZNCCO4L.js";
|
|
@@ -188,4 +188,4 @@ export {
|
|
|
188
188
|
Jumper3DFSM,
|
|
189
189
|
Jumper3DBehavior
|
|
190
190
|
};
|
|
191
|
-
//# sourceMappingURL=chunk-
|
|
191
|
+
//# sourceMappingURL=chunk-DWVLGXMF.js.map
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-AS3HR7AS.js";
|
|
12
12
|
import {
|
|
13
13
|
StageBoundaryDim
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-4GW6DCYF.js";
|
|
15
15
|
import {
|
|
16
16
|
defineBehavior
|
|
17
17
|
} from "./chunk-EZNCCO4L.js";
|
|
@@ -198,4 +198,4 @@ export {
|
|
|
198
198
|
WorldBoundary3DFSM,
|
|
199
199
|
WorldBoundary3DBehavior
|
|
200
200
|
};
|
|
201
|
-
//# sourceMappingURL=chunk-
|
|
201
|
+
//# sourceMappingURL=chunk-GL5JGXPR.js.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
magicPresets,
|
|
7
7
|
particleEffect,
|
|
8
8
|
waterPresets
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-USFIJUDN.js";
|
|
10
10
|
import {
|
|
11
11
|
VEC3_ZERO,
|
|
12
12
|
normalizeVec3
|
|
@@ -410,4 +410,4 @@ export {
|
|
|
410
410
|
ParticleEmitterBehavior,
|
|
411
411
|
particlePresets
|
|
412
412
|
};
|
|
413
|
-
//# sourceMappingURL=chunk-
|
|
413
|
+
//# sourceMappingURL=chunk-GLXEJD2P.js.map
|