@zylem/game-lib 0.6.4 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/README.md +3 -1
  2. package/dist/actions.d.ts +255 -8
  3. package/dist/actions.js +1 -936
  4. package/dist/audio.d.ts +13 -0
  5. package/dist/audio.js +1 -0
  6. package/dist/base-node-life-cycle-CnJ-7zX-.d.ts +143 -0
  7. package/dist/behavior.d.ts +3 -0
  8. package/dist/behavior.js +1 -0
  9. package/dist/chunk-4QLJUQSJ.js +1 -0
  10. package/dist/chunk-73VZQZUL.js +1 -0
  11. package/dist/chunk-A34ZG3L4.js +1 -0
  12. package/dist/chunk-CDPY4VOQ.js +1 -0
  13. package/dist/chunk-DR6XXZE7.js +19 -0
  14. package/dist/chunk-FM5TBEPO.js +1 -0
  15. package/dist/chunk-G2IIMSUH.js +1 -0
  16. package/dist/chunk-MSC2BEO5.js +1 -0
  17. package/dist/chunk-NIH5CONO.js +1 -0
  18. package/dist/chunk-ONWXGBWB.js +1 -0
  19. package/dist/chunk-QEDQDR27.js +1 -0
  20. package/dist/chunk-QXVH6POE.js +1 -0
  21. package/dist/chunk-RXDTAWI2.js +29 -0
  22. package/dist/chunk-WKHW2QO2.js +1 -0
  23. package/dist/chunk-XRP4JJXL.js +1 -0
  24. package/dist/chunk-YHEWKN7N.js +1 -0
  25. package/dist/chunk-YHKXQ2ZN.js +1 -0
  26. package/dist/core.d.ts +206 -14
  27. package/dist/core.js +24 -12424
  28. package/dist/debug.d.ts +24 -0
  29. package/dist/debug.js +1 -0
  30. package/dist/default-controls-BGc61yYl.d.ts +111 -0
  31. package/dist/{entity-vj-HTjzU.d.ts → entity-DNkYKfdp.d.ts} +452 -578
  32. package/dist/entity-type-map-C94h2TDW.d.ts +781 -0
  33. package/dist/entity.d.ts +265 -0
  34. package/dist/entity.js +1 -0
  35. package/dist/events.d.ts +172 -0
  36. package/dist/events.js +1 -0
  37. package/dist/game-Cuj5gy7U.d.ts +1590 -0
  38. package/dist/game-default-PZLLHYL7.js +1 -0
  39. package/dist/game-interfaces-tfpM5NBk.d.ts +90 -0
  40. package/dist/globals.d.ts +104 -0
  41. package/dist/globals.js +1 -0
  42. package/dist/graphics.d.ts +83 -0
  43. package/dist/graphics.js +1 -0
  44. package/dist/input-ui.d.ts +34 -0
  45. package/dist/input-ui.js +1 -0
  46. package/dist/input.d.ts +72 -0
  47. package/dist/input.js +1 -0
  48. package/dist/material-Wz83vTTp.d.ts +151 -0
  49. package/dist/runtime.d.ts +433 -0
  50. package/dist/runtime.js +1 -0
  51. package/dist/web-components.d.ts +67 -0
  52. package/dist/web-components.js +9 -0
  53. package/dist/world-C9zdyl5d.d.ts +103 -0
  54. package/dist/{camera-4XO5gbQH.d.ts → zylem-stage-runtime-Cs-UDEVU.d.ts} +201 -329
  55. package/package.json +52 -63
  56. package/dist/actions.js.map +0 -1
  57. package/dist/behavior/jumper-2d.d.ts +0 -114
  58. package/dist/behavior/jumper-2d.js +0 -711
  59. package/dist/behavior/jumper-2d.js.map +0 -1
  60. package/dist/behavior/platformer-3d.d.ts +0 -296
  61. package/dist/behavior/platformer-3d.js +0 -761
  62. package/dist/behavior/platformer-3d.js.map +0 -1
  63. package/dist/behavior/ricochet-2d.d.ts +0 -275
  64. package/dist/behavior/ricochet-2d.js +0 -425
  65. package/dist/behavior/ricochet-2d.js.map +0 -1
  66. package/dist/behavior/ricochet-3d.d.ts +0 -117
  67. package/dist/behavior/ricochet-3d.js +0 -443
  68. package/dist/behavior/ricochet-3d.js.map +0 -1
  69. package/dist/behavior/screen-visibility.d.ts +0 -79
  70. package/dist/behavior/screen-visibility.js +0 -358
  71. package/dist/behavior/screen-visibility.js.map +0 -1
  72. package/dist/behavior/screen-wrap.d.ts +0 -87
  73. package/dist/behavior/screen-wrap.js +0 -246
  74. package/dist/behavior/screen-wrap.js.map +0 -1
  75. package/dist/behavior/shooter-2d.d.ts +0 -79
  76. package/dist/behavior/shooter-2d.js +0 -180
  77. package/dist/behavior/shooter-2d.js.map +0 -1
  78. package/dist/behavior/thruster.d.ts +0 -11
  79. package/dist/behavior/thruster.js +0 -292
  80. package/dist/behavior/thruster.js.map +0 -1
  81. package/dist/behavior/top-down-movement.d.ts +0 -56
  82. package/dist/behavior/top-down-movement.js +0 -125
  83. package/dist/behavior/top-down-movement.js.map +0 -1
  84. package/dist/behavior/world-boundary-2d.d.ts +0 -142
  85. package/dist/behavior/world-boundary-2d.js +0 -235
  86. package/dist/behavior/world-boundary-2d.js.map +0 -1
  87. package/dist/behavior/world-boundary-3d.d.ts +0 -76
  88. package/dist/behavior/world-boundary-3d.js +0 -274
  89. package/dist/behavior/world-boundary-3d.js.map +0 -1
  90. package/dist/behavior-descriptor-BXnVR8Ki.d.ts +0 -159
  91. package/dist/blueprints-DmbK2dki.d.ts +0 -26
  92. package/dist/camera.d.ts +0 -6
  93. package/dist/camera.js +0 -1993
  94. package/dist/camera.js.map +0 -1
  95. package/dist/composition-BASvMKrW.d.ts +0 -218
  96. package/dist/core-CARRaS55.d.ts +0 -541
  97. package/dist/core.js.map +0 -1
  98. package/dist/entities-ChFirVL9.d.ts +0 -410
  99. package/dist/entities.d.ts +0 -9
  100. package/dist/entities.js +0 -4986
  101. package/dist/entities.js.map +0 -1
  102. package/dist/entity-Bq_eNEDI.d.ts +0 -28
  103. package/dist/entity-types-DAu8sGJH.d.ts +0 -26
  104. package/dist/global-change-2JvMaz44.d.ts +0 -25
  105. package/dist/main.d.ts +0 -1353
  106. package/dist/main.js +0 -19525
  107. package/dist/main.js.map +0 -1
  108. package/dist/physics-pose-DCc4oE44.d.ts +0 -25
  109. package/dist/physics-protocol-BDD3P5W2.d.ts +0 -200
  110. package/dist/physics-worker.d.ts +0 -21
  111. package/dist/physics-worker.js +0 -306
  112. package/dist/physics-worker.js.map +0 -1
  113. package/dist/physics.d.ts +0 -205
  114. package/dist/physics.js +0 -577
  115. package/dist/physics.js.map +0 -1
  116. package/dist/stage-types-C19IhuzA.d.ts +0 -731
  117. package/dist/stage.d.ts +0 -52
  118. package/dist/stage.js +0 -8479
  119. package/dist/stage.js.map +0 -1
  120. package/dist/sync-state-machine-CZyspBpj.d.ts +0 -16
  121. package/dist/thruster-23lzoPZd.d.ts +0 -180
  122. package/dist/world-DfgxoNMt.d.ts +0 -105
@@ -1,147 +1,9 @@
1
- import { Vector3, Vector2, Color, Material, BufferGeometry, Mesh, Group, ShaderMaterial } from 'three';
2
- import { Vector3 as Vector3$1, RigidBodyDesc, ColliderDesc, RigidBody, Vector, Collider } from '@dimforge/rapier3d-compat';
3
- import { IComponent } from 'bitecs';
4
- import * as mitt from 'mitt';
5
- import { c as BehaviorDescriptor, d as BehaviorHandle, e as BehaviorRef } from './behavior-descriptor-BXnVR8Ki.js';
6
-
7
- /** Input
8
- *
9
- * Maximum number of local players is 8.
10
- * All input can be mapped to a gamepad or keyboard but shares the common
11
- * interface represented as a gamepad.
12
- */
13
- type InputPlayerNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
14
- type InputPlayer = `p${InputPlayerNumber}`;
15
- interface ButtonState {
16
- pressed: boolean;
17
- released: boolean;
18
- held: number;
19
- }
20
- interface AnalogState {
21
- value: number;
22
- held: number;
23
- }
24
- interface InputGamepad {
25
- playerNumber: InputPlayerNumber;
26
- buttons: {
27
- A: ButtonState;
28
- B: ButtonState;
29
- X: ButtonState;
30
- Y: ButtonState;
31
- Start: ButtonState;
32
- Select: ButtonState;
33
- L: ButtonState;
34
- R: ButtonState;
35
- };
36
- directions: {
37
- Up: ButtonState;
38
- Down: ButtonState;
39
- Left: ButtonState;
40
- Right: ButtonState;
41
- };
42
- shoulders: {
43
- LTrigger: ButtonState;
44
- RTrigger: ButtonState;
45
- };
46
- axes: {
47
- Horizontal: AnalogState;
48
- Vertical: AnalogState;
49
- SecondaryHorizontal: AnalogState;
50
- SecondaryVertical: AnalogState;
51
- };
52
- /** Screen-space cursor position (normalized 0..1). Only populated by MouseProvider. */
53
- pointer?: {
54
- x: number;
55
- y: number;
56
- };
57
- }
58
- type Inputs = Record<InputPlayer, InputGamepad>;
59
- interface InputProvider {
60
- getInput(delta: number): Partial<InputGamepad>;
61
- isConnected(): boolean;
62
- getName(): string;
63
- dispose?(): void;
64
- }
65
-
66
- type LoadingEvent = {
67
- type: 'start' | 'progress' | 'complete';
68
- message?: string;
69
- progress?: number;
70
- total?: number;
71
- current?: number;
72
- };
73
- interface IGame<TGlobals extends Record<string, unknown> = any> {
74
- start: () => Promise<this>;
75
- nextStage: () => void;
76
- previousStage: () => void;
77
- reset: () => Promise<void>;
78
- pause: () => Promise<void>;
79
- resume: () => Promise<void>;
80
- onLoading: (callback: (event: LoadingEvent) => void) => void;
81
- loadStageFromId: (stageId: string) => Promise<void>;
82
- end: () => Promise<void>;
83
- goToStage: () => void;
84
- }
85
- interface IStage {
86
- onUpdate: (callback: UpdateFunction<IStage>) => void;
87
- onSetup: (callback: SetupFunction<IStage>) => void;
88
- onDestroy: (callback: DestroyFunction<IStage>) => void;
89
- }
90
- interface ICamera {
91
- move: (position: Vector3) => void;
92
- rotate: (pitch: number, yaw: number, roll: number) => void;
93
- }
94
-
95
- type GlobalRecord = Record<string, unknown>;
96
- /** Setup */
97
- interface SetupContext<T, TGlobals extends GlobalRecord = any> {
98
- me: T;
99
- globals: TGlobals;
100
- inputs?: Inputs;
101
- camera?: ICamera;
102
- stage?: IStage;
103
- game?: IGame<TGlobals>;
104
- }
105
- interface SetupFunction<T, TGlobals extends GlobalRecord = any> {
106
- (context: SetupContext<T, TGlobals>): void;
107
- }
108
- /** Loaded */
109
- interface LoadedContext<T, TGlobals extends GlobalRecord = any> {
110
- me: T;
111
- globals: TGlobals;
112
- }
113
- interface LoadedFunction<T, TGlobals extends GlobalRecord = any> {
114
- (context: LoadedContext<T, TGlobals>): void;
115
- }
116
- /** Update */
117
- type UpdateContext<T, TGlobals extends GlobalRecord = any> = {
118
- me: T;
119
- delta: number;
120
- inputs: Inputs;
121
- globals: TGlobals;
122
- camera: ICamera;
123
- stage?: IStage;
124
- game?: IGame<TGlobals>;
125
- };
126
- interface UpdateFunction<T, TGlobals extends GlobalRecord = any> {
127
- (context: UpdateContext<T, TGlobals>): void;
128
- }
129
- /** Destroy */
130
- interface DestroyContext<T, TGlobals extends GlobalRecord = any> {
131
- me: T;
132
- globals: TGlobals;
133
- }
134
- interface DestroyFunction<T, TGlobals extends GlobalRecord = any> {
135
- (context: DestroyContext<T, TGlobals>): void;
136
- }
137
- /** Cleanup */
138
- interface CleanupContext<T, TGlobals extends GlobalRecord = any> {
139
- me: T;
140
- globals: TGlobals;
141
- }
142
- interface CleanupFunction<T, TGlobals extends GlobalRecord = any> {
143
- (context: CleanupContext<T, TGlobals>): void;
144
- }
1
+ import { BufferGeometry, Material, Mesh, Group, Vector3, Color, ShaderMaterial } from 'three';
2
+ import { RigidBodyDesc, ColliderDesc, RigidBody, Collider, Vector } from '@dimforge/rapier3d-compat';
3
+ import { a as Vec3Input, c as Vec3, s as MaterialBuilder, M as MaterialOptions, b as Vec2Input } from './material-Wz83vTTp.js';
4
+ import { S as SetupContext, f as UpdateContext, D as DestroyContext, h as SetupFunction, i as LoadedFunction, U as UpdateFunction, j as DestroyFunction, k as CleanupFunction, L as LoadedContext, C as CleanupContext } from './base-node-life-cycle-CnJ-7zX-.js';
5
+ import { EventEmitterDelegate, EntityEvents } from './events.js';
6
+ import { TransformState, MoveableEntity, BehaviorDescriptor, BehaviorHandle, BehaviorRef } from '@zylem/behaviors/core';
145
7
 
146
8
  interface NodeInterface {
147
9
  uuid: string;
@@ -170,7 +32,6 @@ declare abstract class BaseNode<Options = any, T = any> implements NodeInterface
170
32
  protected parent: NodeInterface | null;
171
33
  protected children: NodeInterface[];
172
34
  options: Options;
173
- eid: number;
174
35
  uuid: string;
175
36
  name: string;
176
37
  markedForRemoval: boolean;
@@ -237,95 +98,374 @@ declare abstract class BaseNode<Options = any, T = any> implements NodeInterface
237
98
  private recordLifecycleRegistration;
238
99
  }
239
100
 
240
- type Vec3 = Vector3 | Vector3$1;
241
-
242
- declare function shortHash(objString: string): string;
243
-
244
- /**
245
- * GLSL shader object (traditional approach for WebGL)
246
- */
247
- type ZylemShaderObject = {
248
- fragment: string;
249
- vertex: string;
250
- };
251
101
  /**
252
- * TSL shader type (for WebGPU)
253
- * colorNode should be a TSL node that returns the fragment color
102
+ * `WasmStageRuntime` — owns one wasm `WebAssembly.Instance` of `@zylem/runtime`
103
+ * and exposes the unified-Stage FFI as a set of typed TypeScript methods.
104
+ * Replaces the legacy {@link ZylemRuntimeStageAdapter} + {@link ZylemWorld}
105
+ * pair; every `ZylemStage` instantiates exactly one `WasmStageRuntime`.
106
+ *
107
+ * The runtime is the single source of truth for per-frame physics state.
108
+ * TS-side behaviors and visual layers (destructible-3d, particle-emitter,
109
+ * screen-visibility) read transforms from the render buffer; sim-only
110
+ * behaviors push their attach/query payload through the per-behavior
111
+ * helpers exposed here.
254
112
  */
255
- type ZylemTSLShader = {
256
- colorNode: any;
257
- transparent?: boolean;
113
+ /** Sentinel handle for "no entity / failed allocation". Mirrors `INVALID_SLOT` in Rust. */
114
+ declare const STAGE_INVALID_SLOT = 4294967295;
115
+ /** Fixed render-buffer stride in floats. Must match `STAGE_RENDER_STRIDE` in Rust. */
116
+ declare const STAGE_RENDER_STRIDE = 12;
117
+ /** Fixed event-buffer stride in floats. Must match `STAGE_EVENT_STRIDE` in Rust. */
118
+ declare const STAGE_EVENT_STRIDE = 6;
119
+ /** Fixed pose-scratch stride in floats. Must match `POSE_SCRATCH_LEN` in Rust. */
120
+ declare const STAGE_POSE_LEN = 7;
121
+ declare const enum StageBodyKind {
122
+ Dynamic = 0,
123
+ Static = 1,
124
+ KinematicPosition = 2,
125
+ KinematicVelocity = 3
126
+ }
127
+ declare const enum StageBoundaryDim {
128
+ Two = 2,
129
+ Three = 3
130
+ }
131
+ declare const enum StageRicochetDim {
132
+ Two = 2,
133
+ Three = 3
134
+ }
135
+ declare const enum StageRicochetReflection {
136
+ Mirror = 0,
137
+ Angled = 1
138
+ }
139
+ declare const enum StageTopDownPlane {
140
+ Xy = 0,
141
+ Xz = 1
142
+ }
143
+ declare const enum StageEventType {
144
+ CollisionStarted = 1,
145
+ CollisionStopped = 2,
146
+ BoundaryHit = 3,
147
+ Ricochet = 4,
148
+ RegionEntered = 5,
149
+ JumpStarted = 6,
150
+ Landed = 7,
151
+ Wrapped = 8,
152
+ CooldownFired = 9
153
+ }
154
+ interface StageEvent {
155
+ type: StageEventType;
156
+ primarySlot: number | null;
157
+ secondarySlot: number | null;
158
+ payload: [number, number, number];
159
+ }
160
+ interface StagePose {
161
+ position: [number, number, number];
162
+ rotation: [number, number, number, number];
163
+ }
164
+ interface StageBodyConfig {
165
+ kind: StageBodyKind;
166
+ position: readonly [number, number, number];
167
+ rotation: readonly [number, number, number, number];
168
+ linearDamping: number;
169
+ angularDamping: number;
170
+ gravityScale: number;
171
+ canSleep: boolean;
172
+ ccdEnabled: boolean;
173
+ lockRotation: readonly [boolean, boolean, boolean];
174
+ lockTranslation: readonly [boolean, boolean, boolean];
175
+ }
176
+ type StageColliderShape = {
177
+ type: 'box';
178
+ halfExtents: readonly [number, number, number];
179
+ } | {
180
+ type: 'sphere';
181
+ radius: number;
182
+ } | {
183
+ type: 'capsule';
184
+ halfHeight: number;
185
+ radius: number;
186
+ } | {
187
+ type: 'cylinder';
188
+ halfHeight: number;
189
+ radius: number;
190
+ } | {
191
+ type: 'convexHull';
192
+ vertices: Float32Array;
193
+ } | {
194
+ type: 'trimesh';
195
+ vertices: Float32Array;
196
+ indices: Uint32Array;
197
+ } | {
198
+ type: 'heightfield';
199
+ rows: number;
200
+ cols: number;
201
+ scale: readonly [number, number, number];
202
+ heights: Float32Array;
258
203
  };
259
- /**
260
- * Combined shader type supporting both GLSL and TSL
261
- */
262
- type ZylemShader = ZylemShaderObject | ZylemTSLShader;
263
- /**
264
- * Check if a shader is a TSL shader
265
- */
266
- declare function isTSLShader(shader: ZylemShader): shader is ZylemTSLShader;
267
- /**
268
- * Check if a shader is a GLSL shader
269
- */
270
- declare function isGLSLShader(shader: ZylemShader): shader is ZylemShaderObject;
271
- interface MaterialOptions {
272
- path?: string;
273
- normalMap?: string;
274
- repeat?: Vector2;
275
- shader?: ZylemShader;
276
- color?: Color;
277
- /** Opacity from 0 (fully transparent) to 1 (fully opaque). */
278
- opacity?: number;
279
- /**
280
- * When true, prefer TSL/NodeMaterial (for WebGPU)
281
- * When false, prefer GLSL/ShaderMaterial (for WebGL)
282
- */
283
- useTSL?: boolean;
204
+ interface StageColliderConfig {
205
+ shape: StageColliderShape;
206
+ offset: readonly [number, number, number];
207
+ friction: number;
208
+ restitution: number;
209
+ sensor: boolean;
210
+ /** Packed Rapier interaction-groups: high 16 bits = membership, low 16 bits = filter. */
211
+ collisionGroups: number;
284
212
  }
285
- type BatchGeometryMap = Map<symbol, number>;
286
- interface BatchMaterialMapObject {
287
- geometryMap: BatchGeometryMap;
288
- material: Material;
213
+ /** Minimal exports surface used by `WasmStageRuntime`. Mirrors `stage_ffi.rs`. */
214
+ interface StageWasmExports {
215
+ readonly memory: WebAssembly.Memory;
216
+ zylem_stage_create(initialCapacity: number): number;
217
+ zylem_stage_destroy(): void;
218
+ zylem_stage_set_gravity(x: number, y: number, z: number): void;
219
+ zylem_stage_step(dt: number): number;
220
+ zylem_stage_active_count(): number;
221
+ zylem_stage_capacity(): number;
222
+ zylem_stage_tick_count(): number;
223
+ zylem_stage_create_entity(): number;
224
+ zylem_stage_destroy_entity(slot: number): number;
225
+ zylem_stage_attach_body(slot: number, kind: number, px: number, py: number, pz: number, rx: number, ry: number, rz: number, rw: number, linearDamping: number, angularDamping: number, gravityScale: number, canSleep: number, ccdEnabled: number, lockRotX: number, lockRotY: number, lockRotZ: number, lockTransX: number, lockTransY: number, lockTransZ: number): number;
226
+ zylem_stage_add_collider_box(slot: number, hx: number, hy: number, hz: number, ox: number, oy: number, oz: number, friction: number, restitution: number, sensor: number, collisionGroups: number): number;
227
+ zylem_stage_add_collider_sphere(slot: number, radius: number, ox: number, oy: number, oz: number, friction: number, restitution: number, sensor: number, collisionGroups: number): number;
228
+ zylem_stage_add_collider_capsule(slot: number, halfHeight: number, radius: number, ox: number, oy: number, oz: number, friction: number, restitution: number, sensor: number, collisionGroups: number): number;
229
+ zylem_stage_add_collider_cylinder(slot: number, halfHeight: number, radius: number, ox: number, oy: number, oz: number, friction: number, restitution: number, sensor: number, collisionGroups: number): number;
230
+ zylem_stage_add_collider_convex_hull(slot: number, vertexOffset: number, vertexCount: number, ox: number, oy: number, oz: number, friction: number, restitution: number, sensor: number, collisionGroups: number): number;
231
+ zylem_stage_add_collider_trimesh(slot: number, vertexOffset: number, vertexCount: number, indexOffset: number, indexCount: number, ox: number, oy: number, oz: number, friction: number, restitution: number, sensor: number, collisionGroups: number): number;
232
+ zylem_stage_add_collider_heightfield(slot: number, rows: number, cols: number, sx: number, sy: number, sz: number, heightOffset: number, px: number, py: number, pz: number, friction: number, restitution: number, collisionGroups: number): number;
233
+ zylem_stage_get_pose(slot: number): number;
234
+ zylem_stage_pose_ptr(): number;
235
+ zylem_stage_pose_len(): number;
236
+ zylem_stage_set_position(slot: number, x: number, y: number, z: number): number;
237
+ zylem_stage_set_rotation(slot: number, x: number, y: number, z: number, w: number): number;
238
+ zylem_stage_set_linvel(slot: number, x: number, y: number, z: number): number;
239
+ zylem_stage_get_linvel(slot: number): number;
240
+ zylem_stage_set_angvel(slot: number, x: number, y: number, z: number): number;
241
+ zylem_stage_apply_impulse(slot: number, x: number, y: number, z: number): number;
242
+ zylem_stage_vec3_ptr(): number;
243
+ zylem_stage_render_ptr(): number;
244
+ zylem_stage_render_len(): number;
245
+ zylem_stage_render_stride(): number;
246
+ zylem_stage_event_ptr(): number;
247
+ zylem_stage_event_len(): number;
248
+ zylem_stage_event_count(): number;
249
+ zylem_stage_event_stride(): number;
250
+ zylem_stage_query_ptr(): number;
251
+ zylem_stage_query_len(): number;
252
+ zylem_stage_scratch_ptr(): number;
253
+ zylem_stage_scratch_capacity(): number;
254
+ zylem_stage_attach_cooldown(slot: number): number;
255
+ zylem_stage_cooldown_register(slot: number, id: number, duration: number, immediate: number): number;
256
+ zylem_stage_cooldown_fire(slot: number, id: number): number;
257
+ zylem_stage_cooldown_reset(slot: number, id: number): number;
258
+ zylem_stage_cooldown_remaining(slot: number, id: number): number;
259
+ zylem_stage_attach_world_boundary(slot: number, dim: number, top: number, bottom: number, left: number, right: number, front: number, back: number, padding: number): number;
260
+ zylem_stage_query_world_boundary(slot: number): number;
261
+ zylem_stage_attach_screen_wrap(slot: number, width: number, height: number, centerX: number, centerY: number, edgeThreshold: number): number;
262
+ zylem_stage_query_screen_wrap(slot: number): number;
263
+ zylem_stage_attach_ricochet(slot: number, dim: number, minSpeed: number, maxSpeed: number, speedMultiplier: number, maxAngleDeg: number, reflectionMode: number): number;
264
+ zylem_stage_query_ricochet(slot: number): number;
265
+ zylem_stage_attach_thruster(slot: number, maxSpeed: number, acceleration: number, turnRateRadS: number, linearDamping: number): number;
266
+ zylem_stage_set_thruster_input(slot: number, thrust: number, turn: number): void;
267
+ zylem_stage_query_thruster(slot: number): number;
268
+ zylem_stage_attach_top_down(slot: number, plane: number, speed: number, faceMovement: number): number;
269
+ zylem_stage_set_top_down_input(slot: number, a: number, b: number): void;
270
+ zylem_stage_attach_jumper_2d(slot: number, jumpForce: number, maxJumps: number, jumpBufferTime: number, coyoteTime: number, gravity: number): number;
271
+ zylem_stage_set_jumper_2d_input(slot: number, jumpPressed: number): void;
272
+ zylem_stage_query_jumper_2d(slot: number): number;
273
+ zylem_stage_attach_jumper_3d(slot: number, jumpForce: number, maxJumps: number, gravity: number): number;
274
+ zylem_stage_set_jumper_3d_input(slot: number, jump: number): void;
275
+ zylem_stage_query_jumper_3d(slot: number): number;
276
+ zylem_stage_attach_shooter_2d(slot: number, fireRateHz: number, muzzleOffsetX: number, muzzleOffsetY: number, muzzleSpeed: number): number;
277
+ zylem_stage_shooter_2d_fire(slot: number, x: number, y: number, z: number, yaw: number): number;
278
+ zylem_stage_query_shooter_2d(slot: number): number;
279
+ zylem_stage_attach_platformer_3d(slot: number, halfHeight: number, radius: number, walkSpeed: number, runSpeed: number, jumpForce: number, maxJumps: number, gravity: number): number;
280
+ zylem_stage_set_platformer_3d_input_axes(slot: number, moveX: number, moveZ: number): void;
281
+ zylem_stage_set_platformer_3d_input_buttons(slot: number, jump: number, run: number): void;
282
+ zylem_stage_query_platformer_3d(slot: number): number;
283
+ zylem_stage_attach_first_person(slot: number, walkSpeed: number, runSpeed: number, eyeHeight: number, lookSensitivity: number): number;
284
+ zylem_stage_set_first_person_input(slot: number, moveX: number, moveZ: number, lookYaw: number, lookPitch: number, run: number): void;
285
+ zylem_stage_query_first_person(slot: number): number;
286
+ zylem_stage_invalid_slot(): number;
289
287
  }
290
- type BatchKey = ReturnType<typeof shortHash>;
291
- type TexturePath = string | null;
292
- declare class MaterialBuilder {
293
- static batchMaterialMap: Map<BatchKey, BatchMaterialMapObject>;
294
- /**
295
- * Clear the static batch material cache.
296
- * Should be called during game disposal to prevent stale material references
297
- * from persisting across demo/stage switches.
298
- */
299
- static clearBatchCache(): void;
300
- materials: Material[];
301
- /** Whether to use TSL/NodeMaterial (for WebGPU compatibility) */
302
- private useTSL;
303
- constructor(useTSL?: boolean);
304
- batchMaterial(options: Partial<MaterialOptions>, entityType: symbol): void;
305
- build(options: Partial<MaterialOptions>, entityType: symbol): void;
306
- withColor(color: Color, useTSL?: boolean, opacity?: number): this;
307
- withShader(shader: ZylemShaderObject, opacity?: number): this;
308
- withTSLShader(shader: ZylemTSLShader, opacity?: number): this;
309
- private applyOpacity;
310
- /**
311
- * Set texture - loads in background (deferred).
312
- * Material is created immediately with null map, texture applies when loaded.
313
- */
314
- setTexture(texturePath?: TexturePath, repeat?: Vector2, useTSL?: boolean, opacity?: number): void;
315
- /**
316
- * Set normal map for the current material
317
- */
318
- setNormalMap(normalMapPath: string, repeat?: Vector2): void;
319
- setColor(color: Color, useTSL?: boolean, opacity?: number): void;
320
- /**
321
- * Set GLSL shader (WebGL only)
322
- */
323
- setShader(customShader: ZylemShaderObject, opacity?: number): void;
324
- /**
325
- * Set TSL shader (WebGPU compatible)
326
- */
327
- setTSLShader(tslShader: ZylemTSLShader, opacity?: number): void;
288
+ /** Default options for `createWasmStageRuntime`. */
289
+ interface WasmStageRuntimeOptions {
290
+ initialCapacity?: number;
291
+ gravity?: readonly [number, number, number];
292
+ imports?: WebAssembly.Imports;
328
293
  }
294
+ /**
295
+ * Owns the wasm instance plus the live float-views over its render / event /
296
+ * pose / scratch buffers. The instance is per-`ZylemStage`; each stage gets
297
+ * its own `WebAssembly.Instance` so the singleton inside `stage_ffi.rs`
298
+ * stays single-stage scoped (today's `thread_local!` contract).
299
+ */
300
+ declare class WasmStageRuntime {
301
+ readonly exports: StageWasmExports;
302
+ private readonly memory;
303
+ private renderView;
304
+ private eventView;
305
+ private poseView;
306
+ private vec3View;
307
+ private queryView;
308
+ private scratchView;
309
+ constructor(exports: StageWasmExports, options?: WasmStageRuntimeOptions);
310
+ /** Recreate typed views over wasm memory. Call after step() or whenever memory may have grown. */
311
+ refreshViews(): void;
312
+ /** Step the simulation by `dt` seconds. Refreshes views afterwards. */
313
+ step(dt: number): number;
314
+ dispose(): void;
315
+ get tickCount(): number;
316
+ get activeCount(): number;
317
+ setGravity(x: number, y: number, z: number): void;
318
+ createEntity(): number;
319
+ destroyEntity(slot: number): boolean;
320
+ attachBody(slot: number, config: StageBodyConfig): boolean;
321
+ addCollider(slot: number, config: StageColliderConfig): boolean;
322
+ private stageScratch;
323
+ private stageScratchIndices;
324
+ getPose(slot: number, out?: StagePose): StagePose | null;
325
+ setPosition(slot: number, x: number, y: number, z: number): boolean;
326
+ setRotation(slot: number, x: number, y: number, z: number, w: number): boolean;
327
+ setLinearVelocity(slot: number, x: number, y: number, z: number): boolean;
328
+ getLinearVelocity(slot: number, out?: [number, number, number]): [number, number, number] | null;
329
+ setAngularVelocity(slot: number, x: number, y: number, z: number): boolean;
330
+ applyImpulse(slot: number, x: number, y: number, z: number): boolean;
331
+ /** Read-only view over the render buffer; one slot occupies {@link STAGE_RENDER_STRIDE} floats. */
332
+ get render(): Float32Array;
333
+ get renderStride(): number;
334
+ /** Drain the wasm event buffer into a fresh array of typed events. */
335
+ drainEvents(): StageEvent[];
336
+ get queryScratch(): Float32Array;
337
+ attachCooldown(slot: number): boolean;
338
+ registerCooldown(slot: number, id: number, durationSeconds: number, immediate?: boolean): boolean;
339
+ fireCooldown(slot: number, id: number): boolean;
340
+ resetCooldown(slot: number, id: number): boolean;
341
+ cooldownRemaining(slot: number, id: number): number;
342
+ attachWorldBoundary(slot: number, dim: StageBoundaryDim, bounds: {
343
+ top: number;
344
+ bottom: number;
345
+ left: number;
346
+ right: number;
347
+ front: number;
348
+ back: number;
349
+ padding?: number;
350
+ }): boolean;
351
+ queryWorldBoundary(slot: number): {
352
+ hits: number;
353
+ clamped: [number, number, number];
354
+ } | null;
355
+ attachScreenWrap(slot: number, opts: {
356
+ width: number;
357
+ height: number;
358
+ centerX?: number;
359
+ centerY?: number;
360
+ edgeThreshold?: number;
361
+ }): boolean;
362
+ queryScreenWrap(slot: number): {
363
+ fsm: number;
364
+ lastWrappedAxes: number;
365
+ } | null;
366
+ attachRicochet(slot: number, dim: StageRicochetDim, opts: {
367
+ minSpeed: number;
368
+ maxSpeed: number;
369
+ speedMultiplier: number;
370
+ maxAngleDeg: number;
371
+ reflectionMode: StageRicochetReflection;
372
+ }): boolean;
373
+ queryRicochet(slot: number): {
374
+ bounces: number;
375
+ lastKind: number;
376
+ } | null;
377
+ attachThruster(slot: number, opts: {
378
+ maxSpeed: number;
379
+ acceleration: number;
380
+ turnRateRadPerSec: number;
381
+ linearDamping: number;
382
+ }): boolean;
383
+ setThrusterInput(slot: number, thrust: number, turn: number): void;
384
+ queryThruster(slot: number): {
385
+ headingRad: number;
386
+ speed: number;
387
+ } | null;
388
+ attachTopDown(slot: number, opts: {
389
+ plane: StageTopDownPlane;
390
+ speed: number;
391
+ faceMovement?: boolean;
392
+ }): boolean;
393
+ setTopDownInput(slot: number, axisA: number, axisB: number): void;
394
+ attachJumper2D(slot: number, opts: {
395
+ jumpForce: number;
396
+ maxJumps: number;
397
+ jumpBufferTime: number;
398
+ coyoteTime: number;
399
+ gravity: number;
400
+ }): boolean;
401
+ setJumper2DInput(slot: number, jumpPressed: boolean): void;
402
+ queryJumper2D(slot: number): {
403
+ grounded: boolean;
404
+ jumpCount: number;
405
+ coyote: number;
406
+ jumpBuffer: number;
407
+ } | null;
408
+ attachJumper3D(slot: number, opts: {
409
+ jumpForce: number;
410
+ maxJumps: number;
411
+ gravity: number;
412
+ }): boolean;
413
+ setJumper3DInput(slot: number, jump: boolean): void;
414
+ queryJumper3D(slot: number): {
415
+ grounded: boolean;
416
+ jumpCount: number;
417
+ verticalVelocity: number;
418
+ } | null;
419
+ attachShooter2D(slot: number, opts: {
420
+ fireRateHz: number;
421
+ muzzleOffsetX: number;
422
+ muzzleOffsetY: number;
423
+ muzzleSpeed: number;
424
+ }): boolean;
425
+ fireShooter2D(slot: number, x: number, y: number, z: number, yaw: number): boolean;
426
+ queryShooter2D(slot: number): {
427
+ cooldown: number;
428
+ firedCount: number;
429
+ } | null;
430
+ attachPlatformer3D(slot: number, opts: {
431
+ halfHeight: number;
432
+ radius: number;
433
+ walkSpeed: number;
434
+ runSpeed: number;
435
+ jumpForce: number;
436
+ maxJumps: number;
437
+ gravity: number;
438
+ }): boolean;
439
+ setPlatformer3DInputAxes(slot: number, moveX: number, moveZ: number): void;
440
+ setPlatformer3DInputButtons(slot: number, jump: boolean, run: boolean): void;
441
+ queryPlatformer3D(slot: number): {
442
+ grounded: boolean;
443
+ jumpCount: number;
444
+ fsmState: number;
445
+ speed: number;
446
+ } | null;
447
+ attachFirstPerson(slot: number, opts: {
448
+ walkSpeed: number;
449
+ runSpeed: number;
450
+ eyeHeight: number;
451
+ lookSensitivity: number;
452
+ }): boolean;
453
+ setFirstPersonInput(slot: number, opts: {
454
+ moveX: number;
455
+ moveZ: number;
456
+ lookYawDelta: number;
457
+ lookPitchDelta: number;
458
+ run: boolean;
459
+ }): void;
460
+ queryFirstPerson(slot: number): {
461
+ yaw: number;
462
+ pitch: number;
463
+ speed: number;
464
+ eyeHeight: number;
465
+ } | null;
466
+ }
467
+ /** Loads + instantiates a wasm module and constructs a `WasmStageRuntime`. */
468
+ declare function createWasmStageRuntime(source: RequestInfo | URL | ArrayBuffer, options?: WasmStageRuntimeOptions): Promise<WasmStageRuntime>;
329
469
 
330
470
  /**
331
471
  * Options for configuring entity collision behavior.
@@ -333,8 +473,8 @@ declare class MaterialBuilder {
333
473
  interface CollisionOptions {
334
474
  static?: boolean;
335
475
  sensor?: boolean;
336
- size?: Vector3$1;
337
- position?: Vector3$1;
476
+ size?: Vec3Input;
477
+ position?: Vec3Input;
338
478
  collisionType?: string;
339
479
  collisionFilter?: string[];
340
480
  }
@@ -374,343 +514,18 @@ declare abstract class EntityMeshBuilder extends MeshBuilder {
374
514
  build(options: GameEntityOptions): BufferGeometry;
375
515
  postBuild(): void;
376
516
  }
377
-
378
- interface Behavior {
379
- component: IComponent;
380
- values: any;
381
- }
382
-
383
- /**
384
- * Reusable delegate for event emission and subscription.
385
- * Use via composition in Game, Stage, and Entity classes.
386
- *
387
- * @example
388
- * class Game {
389
- * private eventDelegate = new EventEmitterDelegate<GameEvents>();
390
- *
391
- * dispatch<K extends keyof GameEvents>(event: K, payload: GameEvents[K]) {
392
- * this.eventDelegate.dispatch(event, payload);
393
- * }
394
- * }
395
- */
396
- declare class EventEmitterDelegate<TEvents extends Record<string, unknown>> {
397
- private emitter;
398
- private unsubscribes;
399
- constructor();
400
- /**
401
- * Dispatch an event to all listeners.
402
- */
403
- dispatch<K extends keyof TEvents>(event: K, payload: TEvents[K]): void;
404
- /**
405
- * Subscribe to an event. Returns an unsubscribe function.
406
- */
407
- listen<K extends keyof TEvents>(event: K, handler: (payload: TEvents[K]) => void): () => void;
408
- /**
409
- * Subscribe to all events.
410
- */
411
- listenAll(handler: (type: keyof TEvents, payload: TEvents[keyof TEvents]) => void): () => void;
412
- /**
413
- * Clean up all subscriptions.
414
- */
415
- dispose(): void;
416
- }
417
-
418
- /**
419
- * Payload for game loading events with stage context.
420
- */
421
- interface GameLoadingPayload extends LoadingEvent {
422
- stageName?: string;
423
- stageIndex?: number;
424
- }
425
- /** Payload for stage configuration sent to editor. */
426
- interface StageConfigPayload {
427
- id: string;
428
- backgroundColor: string;
429
- backgroundImage: string | null;
430
- gravity: {
431
- x: number;
432
- y: number;
433
- z: number;
434
- };
435
- inputs: Record<string, string[]>;
436
- variables: Record<string, unknown>;
437
- }
438
- /** Payload for entity configuration sent to editor. */
439
- interface EntityConfigPayload {
440
- uuid: string;
441
- name: string;
442
- type: string;
443
- position: {
444
- x: number;
445
- y: number;
446
- z: number;
447
- };
448
- rotation: {
449
- x: number;
450
- y: number;
451
- z: number;
452
- };
453
- scale: {
454
- x: number;
455
- y: number;
456
- z: number;
457
- };
458
- }
459
- /** Payload for state dispatch events from game to editor. */
460
- interface StateDispatchPayload {
461
- scope: 'game' | 'stage' | 'entity';
462
- path: string;
463
- value: unknown;
464
- previousValue?: unknown;
465
- config?: {
466
- id: string;
467
- aspectRatio: number;
468
- fullscreen: boolean;
469
- bodyBackground: string | undefined;
470
- internalResolution: {
471
- width: number;
472
- height: number;
473
- } | undefined;
474
- debug: boolean;
475
- } | null;
476
- stageConfig?: StageConfigPayload | null;
477
- entities?: EntityConfigPayload[] | null;
478
- }
479
- type GameEvents = {
480
- 'loading:start': GameLoadingPayload;
481
- 'loading:progress': GameLoadingPayload;
482
- 'loading:complete': GameLoadingPayload;
483
- 'paused': {
484
- paused: boolean;
485
- };
486
- 'debug': {
487
- enabled: boolean;
488
- };
489
- 'state:dispatch': StateDispatchPayload;
490
- };
491
- type StageEvents = {
492
- 'stage:loaded': {
493
- stageId: string;
494
- };
495
- 'stage:unloaded': {
496
- stageId: string;
497
- };
498
- 'stage:variable:changed': {
499
- key: string;
500
- value: unknown;
501
- };
502
- };
503
- type EntityEvents = {
504
- 'entity:spawned': {
505
- entityId: string;
506
- name: string;
507
- };
508
- 'entity:destroyed': {
509
- entityId: string;
510
- };
511
- 'entity:collision': {
512
- entityId: string;
513
- otherId: string;
514
- };
515
- 'entity:model:loading': {
516
- entityId: string;
517
- files: string[];
518
- };
519
- 'entity:model:loaded': {
520
- entityId: string;
521
- success: boolean;
522
- meshCount?: number;
523
- };
524
- 'entity:animation:loaded': {
525
- entityId: string;
526
- animationCount: number;
527
- };
528
- };
529
- type ZylemEvents = GameEvents & StageEvents & EntityEvents;
530
- /**
531
- * Global event bus for cross-package communication.
532
- *
533
- * Usage:
534
- * ```ts
535
- * import { zylemEventBus } from '@zylem/game-lib';
536
- *
537
- * // Subscribe
538
- * const unsub = zylemEventBus.on('loading:progress', (e) => console.log(e));
539
- *
540
- * // Emit
541
- * zylemEventBus.emit('loading:progress', { type: 'progress', progress: 0.5 });
542
- *
543
- * // Cleanup
544
- * unsub();
545
- * ```
546
- */
547
- declare const zylemEventBus: mitt.Emitter<ZylemEvents>;
548
-
549
- type VelocityIntentMode = 'replace' | 'add';
550
- interface VelocityIntent {
551
- x?: number;
552
- y?: number;
553
- z?: number;
554
- mode: VelocityIntentMode;
555
- priority?: number;
556
- }
557
- /**
558
- * Transform state managed by Valtio for batched physics updates.
559
- *
560
- * This store accumulates transformation intents during the frame,
561
- * then applies them all at once after onUpdate() callbacks complete.
562
- *
563
- * Design decisions:
564
- * - Position: Accumulated deltas (additive)
565
- * - Rotation: Last value wins (replacement)
566
- * - Velocity: Accumulated deltas (additive)
567
- * - Angular velocity: Accumulated deltas (additive)
568
- */
569
- interface TransformState {
570
- /** Position deltas to be applied (accumulated) */
571
- position: {
572
- x: number;
573
- y: number;
574
- z: number;
575
- };
576
- /** Rotation quaternion (last value wins) */
577
- rotation: {
578
- x: number;
579
- y: number;
580
- z: number;
581
- w: number;
582
- };
583
- /** Linear velocity (accumulated) */
584
- velocity: {
585
- x: number;
586
- y: number;
587
- z: number;
588
- };
589
- /** Angular velocity (accumulated) */
590
- angularVelocity: {
591
- x: number;
592
- y: number;
593
- z: number;
594
- };
595
- /** Per-source velocity intents composed once per frame */
596
- velocityChannels: Record<string, VelocityIntent>;
597
- /** Dirty flags to track what needs to be applied */
598
- dirty: {
599
- position: boolean;
600
- rotation: boolean;
601
- /** @deprecated Use per-axis velocityX/Y/Z flags for new code */
602
- velocity: boolean;
603
- velocityX: boolean;
604
- velocityY: boolean;
605
- velocityZ: boolean;
606
- velocityChannels: boolean;
607
- angularVelocity: boolean;
608
- };
609
- }
610
- /**
611
- * Create a new transform store with optional initial values.
612
- * The store is a Valtio proxy, making it reactive for debugging/visualization.
613
- *
614
- * @param initial Optional initial state values
615
- * @returns Reactive transform state
616
- */
617
- declare function createTransformStore(initial?: Partial<TransformState>): TransformState;
618
- /**
619
- * Reset a transform store to its initial clean state.
620
- * Called after applying changes to prepare for the next frame.
621
- *
622
- * @param store The transform store to reset
623
- */
624
- declare function resetTransformStore(store: TransformState): void;
625
-
626
- interface EntityWithBody {
627
- body: RigidBody | null;
628
- transformStore?: TransformState;
629
- }
630
- /**
631
- * Move an entity along the X axis, preserving other velocities.
632
- */
633
- declare function moveX(entity: EntityWithBody, delta: number): void;
634
- /**
635
- * Move an entity along the Y axis, preserving other velocities.
636
- */
637
- declare function moveY(entity: EntityWithBody, delta: number): void;
638
- /**
639
- * Move an entity along the Z axis, preserving other velocities.
640
- */
641
- declare function moveZ(entity: EntityWithBody, delta: number): void;
642
- /**
643
- * Move an entity along the X and Y axis, preserving Z velocity.
644
- */
645
- declare function moveXY(entity: EntityWithBody, deltaX: number, deltaY: number): void;
646
- /**
647
- * Move an entity along the X and Z axis, preserving Y velocity.
648
- */
649
- declare function moveXZ(entity: EntityWithBody, deltaX: number, deltaZ: number): void;
650
- /**
651
- * Move entity based on a vector, adding to existing velocities.
652
- */
653
- declare function move(entity: EntityWithBody, vector: Vector3): void;
654
- /**
655
- * Reset entity velocity
656
- */
657
- declare function resetVelocity(entity: EntityWithBody): void;
658
- /**
659
- * Move entity forward in 2D space, preserving Z velocity
660
- */
661
- declare function moveForwardXY(entity: EntityWithBody, delta: number, rotation2DAngle: number): void;
662
- /**
663
- * Get entity position
664
- */
665
- declare function getPosition(entity: EntityWithBody): Vector | null;
666
- /**
667
- * Get entity velocity
668
- */
669
- declare function getVelocity(entity: EntityWithBody): Vector | null;
670
- /**
671
- * Set entity position
672
- */
673
- declare function setPosition(entity: EntityWithBody, x: number, y: number, z: number): void;
674
- /**
675
- * Set entity X position
676
- */
677
- declare function setPositionX(entity: EntityWithBody, x: number): void;
678
- /**
679
- * Set entity Y position
680
- */
681
- declare function setPositionY(entity: EntityWithBody, y: number): void;
682
- /**
683
- * Set entity Z position
684
- */
685
- declare function setPositionZ(entity: EntityWithBody, z: number): void;
686
- /**
687
- * Wrap entity around 2D bounds
688
- */
689
- declare function wrapAroundXY(entity: EntityWithBody, boundsX: number, boundsY: number): void;
690
- /**
691
- * Wrap entity around 3D bounds
692
- */
693
- declare function wrapAround3D(entity: EntityWithBody, boundsX: number, boundsY: number, boundsZ: number): void;
694
- /**
695
- * Enhanced moveable entity with bound methods
696
- */
697
- interface MoveableEntity extends EntityWithBody {
698
- moveX(delta: number): void;
699
- moveY(delta: number): void;
700
- moveZ(delta: number): void;
701
- moveXY(deltaX: number, deltaY: number): void;
702
- moveXZ(deltaX: number, deltaZ: number): void;
703
- move(vector: Vector3): void;
704
- resetVelocity(): void;
705
- moveForwardXY(delta: number, rotation2DAngle: number): void;
706
- getPosition(): Vector | null;
707
- getVelocity(): Vector | null;
708
- setPosition(x: number, y: number, z: number): void;
709
- setPositionX(x: number): void;
710
- setPositionY(y: number): void;
711
- setPositionZ(z: number): void;
712
- wrapAroundXY(boundsX: number, boundsY: number): void;
713
- wrapAround3D(boundsX: number, boundsY: number, boundsZ: number): void;
517
+ declare abstract class EntityBuilder<T extends GameEntity<U> & P, U extends GameEntityOptions, P = any> {
518
+ protected meshBuilder: EntityMeshBuilder | null;
519
+ protected collisionBuilder: EntityCollisionBuilder | null;
520
+ protected materialBuilder: MaterialBuilder | null;
521
+ protected options: Partial<U>;
522
+ protected entity: T;
523
+ constructor(options: Partial<U>, entity: T, meshBuilder: EntityMeshBuilder | null, collisionBuilder: EntityCollisionBuilder | null);
524
+ withPosition(setupPosition: Vec3): this;
525
+ withMaterial(options: Partial<MaterialOptions>, entityType: symbol): this;
526
+ applyMaterialToGroup(group: Group, materials: Material[]): void;
527
+ build(): T;
528
+ protected abstract createEntity(options: Partial<U>): T;
714
529
  }
715
530
 
716
531
  interface RotatableEntity {
@@ -816,7 +631,7 @@ interface BaseCollisionOptions {
816
631
  /** Whether this collider is a sensor */
817
632
  sensor?: boolean;
818
633
  /** Position offset relative to the entity origin */
819
- offset?: Vec3;
634
+ offset?: Vec3Input;
820
635
  /** Collision type string for group filtering */
821
636
  collisionType?: string;
822
637
  /** Allowed collision types for filtering */
@@ -824,7 +639,7 @@ interface BaseCollisionOptions {
824
639
  }
825
640
  interface BoxCollisionOptions extends BaseCollisionOptions {
826
641
  /** Box dimensions (default: 1x1x1) */
827
- size?: Vec3;
642
+ size?: Vec3Input;
828
643
  }
829
644
  /**
830
645
  * Create a box (cuboid) collision component.
@@ -882,10 +697,7 @@ interface PillCollisionOptions extends BaseCollisionOptions {
882
697
  declare function pillCollision(opts?: PillCollisionOptions): CollisionComponent;
883
698
  interface PlaneCollisionOptions extends BaseCollisionOptions {
884
699
  /** Tile dimensions (default: 10x10) */
885
- tile?: {
886
- x: number;
887
- y: number;
888
- };
700
+ tile?: Vec2Input;
889
701
  /** Number of subdivisions per axis (default: 10) */
890
702
  subdivisions?: number;
891
703
  /** Pre-computed height data for the heightfield */
@@ -898,7 +710,7 @@ interface PlaneCollisionOptions extends BaseCollisionOptions {
898
710
  declare function planeCollision(opts?: PlaneCollisionOptions): CollisionComponent;
899
711
  interface ZoneCollisionOptions extends BaseCollisionOptions {
900
712
  /** Zone dimensions (default: 1x1x1) */
901
- size?: Vec3;
713
+ size?: Vec3Input;
902
714
  }
903
715
  /**
904
716
  * Create a zone (sensor cuboid) collision component.
@@ -958,12 +770,24 @@ type IBuilder<BuilderOptions = any> = {
958
770
  build: (options: BuilderOptions) => BuilderOptions;
959
771
  postBuild: (options: BuilderOptions) => BuilderOptions;
960
772
  };
773
+ type GameEntitySimulationMode = 'ts' | 'runtime';
774
+ type GameEntityRenderMode = 'mesh' | 'instanced';
775
+ type RuntimeEntityBodyMode = 'dynamic' | 'static' | 'none';
776
+ type RuntimeEntityColorMode = 'base' | 'heatTint';
777
+ interface RuntimeEntityOptions {
778
+ simulation?: GameEntitySimulationMode;
779
+ render?: GameEntityRenderMode;
780
+ batchKeyOverride?: string;
781
+ body?: RuntimeEntityBodyMode;
782
+ colorMode?: RuntimeEntityColorMode;
783
+ }
961
784
  type GameEntityOptions = {
962
785
  name?: string;
963
786
  color?: Color;
964
- size?: Vec3;
965
- position?: Vec3;
787
+ size?: Vec3Input;
788
+ position?: Vec3Input;
966
789
  batched?: boolean;
790
+ runtime?: RuntimeEntityOptions;
967
791
  collision?: Partial<CollisionOptions>;
968
792
  material?: Partial<MaterialOptions>;
969
793
  custom?: {
@@ -987,7 +811,6 @@ interface EntityDebugInfo {
987
811
  buildInfo: () => Record<string, string>;
988
812
  }
989
813
  declare class GameEntity<O extends GameEntityOptions> extends BaseNode<O> implements GameEntityLifeCycle, EntityDebugInfo, MoveableEntity, RotatableEntityAPI {
990
- behaviors: Behavior[];
991
814
  group: Group | undefined;
992
815
  mesh: Mesh | undefined;
993
816
  materials: Material[] | undefined;
@@ -1013,6 +836,24 @@ declare class GameEntity<O extends GameEntityOptions> extends BaseNode<O> implem
1013
836
  instanceId: number;
1014
837
  /** Whether this entity uses instanced rendering */
1015
838
  isInstanced: boolean;
839
+ /** Runtime slot index when owned by a stage runtime adapter (legacy alias for runtimeHandle). */
840
+ runtimeSlot: number;
841
+ /**
842
+ * Stable u32 handle into the wasm `StageSimulation`. Returned by
843
+ * `WasmStageRuntime.createEntity()`; -1 means the entity is not currently
844
+ * attached to the runtime. Replaces `runtimeSlot` and the legacy
845
+ * `entity.body` / `entity.collider` fields once Phase 3 lands.
846
+ */
847
+ runtimeHandle: number;
848
+ /** True once the entity has been attached to the wasm `StageSimulation`. */
849
+ runtimeAttached: boolean;
850
+ /**
851
+ * Optional reference to the stage's {@link WasmStageRuntime}. Set by
852
+ * `StageEntityDelegate.spawnEntity()` so {@link GameEntity.getPose} /
853
+ * {@link GameEntity.setPose} can route through the unified-Stage runtime
854
+ * without each call site needing to thread the wasm handle around.
855
+ */
856
+ wasmStageRef: WasmStageRuntime | null;
1016
857
  protected eventDelegate: EventEmitterDelegate<EntityEvents>;
1017
858
  private behaviorRefs;
1018
859
  private cloneFactory;
@@ -1051,6 +892,37 @@ declare class GameEntity<O extends GameEntityOptions> extends BaseNode<O> implem
1051
892
  setRotation: (x: number, y: number, z: number) => void;
1052
893
  getRotation: () => any;
1053
894
  constructor();
895
+ /**
896
+ * Read the entity's pose. Prefers the unified-Stage wasm runtime when
897
+ * the entity has a live `runtimeHandle`; otherwise falls back to the
898
+ * legacy TS Rapier `RigidBody` translation/rotation. Returns `null` when
899
+ * neither source is available.
900
+ */
901
+ getPose(): {
902
+ position: Vec3;
903
+ rotation: {
904
+ x: number;
905
+ y: number;
906
+ z: number;
907
+ w: number;
908
+ };
909
+ } | null;
910
+ /**
911
+ * Write the entity's pose. Routes through the unified-Stage wasm runtime
912
+ * when present; otherwise writes to the legacy TS Rapier `RigidBody`.
913
+ *
914
+ * Either or both of `position` and `rotation` may be omitted to leave
915
+ * that component unchanged.
916
+ */
917
+ setPose(input: {
918
+ position?: Vec3Input;
919
+ rotation?: {
920
+ x: number;
921
+ y: number;
922
+ z: number;
923
+ w: number;
924
+ };
925
+ }): boolean;
1054
926
  /**
1055
927
  * Add meshes, collision components, or child entities to this entity.
1056
928
  * Supports fluent chaining: `entity.add(boxMesh()).add(boxCollision())`.
@@ -1076,6 +948,8 @@ declare class GameEntity<O extends GameEntityOptions> extends BaseNode<O> implem
1076
948
  * @example `const press = entity.action(onPress())`
1077
949
  */
1078
950
  action<A extends Action>(action: A): A;
951
+ /** Remove all registered actions (fire-and-forget and persistent). */
952
+ clearActions(): void;
1079
953
  /**
1080
954
  * Tick all registered actions. Called automatically before user onUpdate callbacks.
1081
955
  *
@@ -1166,4 +1040,4 @@ declare class GameEntity<O extends GameEntityOptions> extends BaseNode<O> implem
1166
1040
  */
1167
1041
  declare function create(options?: Partial<GameEntityOptions>): GameEntity<GameEntityOptions>;
1168
1042
 
1169
- export { sphereCollision as $, type Action as A, setRotationZ as B, setRotationDegrees as C, setRotationDegreesY as D, setRotationDegreesX as E, setRotationDegreesZ as F, setRotation as G, getRotation as H, GameEntity as I, type UpdateFunction as J, type DestroyFunction as K, type SetupContext as L, type DestroyContext as M, type LoadingEvent as N, BaseNode as O, type GameEntityOptions as P, type StageEvents as Q, type MaterialOptions as R, type SetupFunction as S, type TransformState as T, type UpdateContext as U, type Vec3 as V, type MoveableEntity as W, type InputPlayer as X, create as Y, type ZylemShader as Z, boxCollision as _, moveX as a, coneCollision as a0, pyramidCollision as a1, cylinderCollision as a2, pillCollision as a3, planeCollision as a4, zoneCollision as a5, type CollisionComponent as a6, EventEmitterDelegate as a7, zylemEventBus as a8, type ZylemEvents as a9, type GameEvents as aa, type EntityEvents as ab, type GameLoadingPayload as ac, type StateDispatchPayload as ad, type StageConfigPayload as ae, type EntityConfigPayload as af, type ZylemShaderObject as ag, type ZylemTSLShader as ah, isTSLShader as ai, isGLSLShader as aj, type InputPlayerNumber as ak, type InputProvider as al, type Inputs as am, GameEntityLifeCycle as an, type IGame as ao, type LoadedContext as ap, type CleanupContext as aq, type NodeInterface as ar, type TexturePath as as, moveY as b, createTransformStore as c, moveZ as d, moveXY as e, moveXZ as f, resetVelocity as g, moveForwardXY as h, getPosition as i, getVelocity as j, setPositionX as k, setPositionY as l, move as m, setPositionZ as n, wrapAround3D as o, rotateInDirection as p, rotateYEuler as q, resetTransformStore as r, setPosition as s, rotateEuler as t, rotateX as u, rotateY as v, wrapAroundXY as w, rotateZ as x, setRotationY as y, setRotationX as z };
1043
+ export { type Action as A, setRotationDegrees as B, setRotationDegreesY as C, setRotationDegreesX as D, setRotationDegreesZ as E, setRotation as F, GameEntity as G, getRotation as H, type GameEntityOptions as I, EntityBuilder as J, EntityMeshBuilder as K, EntityCollisionBuilder as L, BaseNode as M, create as N, boxCollision as O, sphereCollision as P, coneCollision as Q, pyramidCollision as R, StageBodyKind as S, cylinderCollision as T, pillCollision as U, planeCollision as V, type WasmStageRuntimeOptions as W, zoneCollision as X, type CollisionComponent as Y, type NodeInterface as Z, GameEntityLifeCycle as _, type StageBodyConfig as a, type StageColliderConfig as b, type StageColliderShape as c, type StageEvent as d, type StagePose as e, type StageWasmExports as f, StageBoundaryDim as g, StageEventType as h, StageRicochetDim as i, StageRicochetReflection as j, StageTopDownPlane as k, STAGE_EVENT_STRIDE as l, STAGE_INVALID_SLOT as m, STAGE_POSE_LEN as n, STAGE_RENDER_STRIDE as o, WasmStageRuntime as p, createWasmStageRuntime as q, rotateInDirection as r, rotateYEuler as s, rotateEuler as t, rotateX as u, rotateY as v, rotateZ as w, setRotationY as x, setRotationX as y, setRotationZ as z };