@zylem/game-lib 0.6.2 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -16
  3. package/dist/actions.d.ts +30 -21
  4. package/dist/actions.js +793 -146
  5. package/dist/actions.js.map +1 -1
  6. package/dist/behavior/jumper-2d.d.ts +114 -0
  7. package/dist/behavior/jumper-2d.js +711 -0
  8. package/dist/behavior/jumper-2d.js.map +1 -0
  9. package/dist/behavior/platformer-3d.d.ts +296 -0
  10. package/dist/behavior/platformer-3d.js +761 -0
  11. package/dist/behavior/platformer-3d.js.map +1 -0
  12. package/dist/behavior/ricochet-2d.d.ts +275 -0
  13. package/dist/behavior/ricochet-2d.js +425 -0
  14. package/dist/behavior/ricochet-2d.js.map +1 -0
  15. package/dist/behavior/ricochet-3d.d.ts +117 -0
  16. package/dist/behavior/ricochet-3d.js +443 -0
  17. package/dist/behavior/ricochet-3d.js.map +1 -0
  18. package/dist/behavior/screen-visibility.d.ts +79 -0
  19. package/dist/behavior/screen-visibility.js +358 -0
  20. package/dist/behavior/screen-visibility.js.map +1 -0
  21. package/dist/behavior/screen-wrap.d.ts +87 -0
  22. package/dist/behavior/screen-wrap.js +246 -0
  23. package/dist/behavior/screen-wrap.js.map +1 -0
  24. package/dist/behavior/shooter-2d.d.ts +79 -0
  25. package/dist/behavior/shooter-2d.js +180 -0
  26. package/dist/behavior/shooter-2d.js.map +1 -0
  27. package/dist/behavior/thruster.d.ts +11 -0
  28. package/dist/behavior/thruster.js +292 -0
  29. package/dist/behavior/thruster.js.map +1 -0
  30. package/dist/behavior/top-down-movement.d.ts +56 -0
  31. package/dist/behavior/top-down-movement.js +125 -0
  32. package/dist/behavior/top-down-movement.js.map +1 -0
  33. package/dist/behavior/world-boundary-2d.d.ts +142 -0
  34. package/dist/behavior/world-boundary-2d.js +235 -0
  35. package/dist/behavior/world-boundary-2d.js.map +1 -0
  36. package/dist/behavior/world-boundary-3d.d.ts +76 -0
  37. package/dist/behavior/world-boundary-3d.js +274 -0
  38. package/dist/behavior/world-boundary-3d.js.map +1 -0
  39. package/dist/behavior-descriptor-BXnVR8Ki.d.ts +159 -0
  40. package/dist/{blueprints-Cq3Ko6_G.d.ts → blueprints-DmbK2dki.d.ts} +2 -2
  41. package/dist/camera-4XO5gbQH.d.ts +905 -0
  42. package/dist/camera.d.ts +3 -2
  43. package/dist/camera.js +1653 -377
  44. package/dist/camera.js.map +1 -1
  45. package/dist/composition-BASvMKrW.d.ts +218 -0
  46. package/dist/{core-bO8TzV7u.d.ts → core-CARRaS55.d.ts} +110 -69
  47. package/dist/core.d.ts +11 -6
  48. package/dist/core.js +10766 -5626
  49. package/dist/core.js.map +1 -1
  50. package/dist/{entities-DvByhMGU.d.ts → entities-ChFirVL9.d.ts} +133 -29
  51. package/dist/entities.d.ts +5 -3
  52. package/dist/entities.js +4679 -3202
  53. package/dist/entities.js.map +1 -1
  54. package/dist/entity-vj-HTjzU.d.ts +1169 -0
  55. package/dist/global-change-2JvMaz44.d.ts +25 -0
  56. package/dist/main.d.ts +1118 -16
  57. package/dist/main.js +17538 -8499
  58. package/dist/main.js.map +1 -1
  59. package/dist/physics-pose-DCc4oE44.d.ts +25 -0
  60. package/dist/physics-protocol-BDD3P5W2.d.ts +200 -0
  61. package/dist/physics-worker.d.ts +21 -0
  62. package/dist/physics-worker.js +306 -0
  63. package/dist/physics-worker.js.map +1 -0
  64. package/dist/physics.d.ts +205 -0
  65. package/dist/physics.js +577 -0
  66. package/dist/physics.js.map +1 -0
  67. package/dist/stage-types-C19IhuzA.d.ts +731 -0
  68. package/dist/stage.d.ts +11 -7
  69. package/dist/stage.js +8024 -3852
  70. package/dist/stage.js.map +1 -1
  71. package/dist/sync-state-machine-CZyspBpj.d.ts +16 -0
  72. package/dist/thruster-23lzoPZd.d.ts +180 -0
  73. package/dist/world-DfgxoNMt.d.ts +105 -0
  74. package/package.json +53 -13
  75. package/dist/behaviors.d.ts +0 -854
  76. package/dist/behaviors.js +0 -1209
  77. package/dist/behaviors.js.map +0 -1
  78. package/dist/camera-CeJPAgGg.d.ts +0 -116
  79. package/dist/moveable-B_vyA6cw.d.ts +0 -67
  80. package/dist/stage-types-Bd-KtcYT.d.ts +0 -375
  81. package/dist/transformable-CUhvyuYO.d.ts +0 -67
  82. package/dist/world-C8tQ7Plj.d.ts +0 -774
@@ -0,0 +1,731 @@
1
+ import { J as UpdateFunction, S as SetupFunction, Z as ZylemShader, I as GameEntity, K as DestroyFunction, L as SetupContext, U as UpdateContext, M as DestroyContext, N as LoadingEvent, O as BaseNode, P as GameEntityOptions, Q as StageEvents } from './entity-vj-HTjzU.js';
2
+ import * as bitecs from 'bitecs';
3
+ import { defineSystem, IWorld } from 'bitecs';
4
+ import { Scene, Color, Object3D, Vector3, BufferGeometry, Material } from 'three';
5
+ import { Z as ZylemWorld } from './world-DfgxoNMt.js';
6
+ import { E as Entity, L as LifecycleFunction, S as StageEntity } from './entity-Bq_eNEDI.js';
7
+ import { Z as ZylemCamera, C as CameraManager, R as RendererManager, a as CameraWrapper } from './camera-4XO5gbQH.js';
8
+ import { B as BaseEntityInterface, G as GameEntityInterface } from './entity-types-DAu8sGJH.js';
9
+ import { b as PhysicsPoseReadable } from './physics-pose-DCc4oE44.js';
10
+ import { S as SPRITE_TYPE, Z as ZylemSprite, a as SPHERE_TYPE, b as ZylemSphere, R as RECT_TYPE, c as ZylemRect, T as TEXT_TYPE, d as ZylemText, B as BOX_TYPE, e as ZylemBox, P as PLANE_TYPE, f as ZylemPlane, g as ZONE_TYPE, h as ZylemZone, A as ACTOR_TYPE, i as ZylemActor, C as CONE_TYPE, j as ZylemCone, k as PYRAMID_TYPE, l as ZylemPyramid, m as CYLINDER_TYPE, n as ZylemCylinder, o as PILL_TYPE, p as ZylemPill } from './entities-ChFirVL9.js';
11
+ import { B as BehaviorSystem, a as BehaviorEntityLink, b as BehaviorSystemFactory } from './behavior-descriptor-BXnVR8Ki.js';
12
+
13
+ type BasicTypes = number | string | boolean;
14
+ type BaseGlobals = Record<string, BasicTypes>;
15
+ type KeyboardMapping = Record<string, string[]>;
16
+ type MouseMapping = Record<string, string[]>;
17
+ interface MouseConfig {
18
+ /** Custom mapping from mouse actions to input properties. */
19
+ mapping?: MouseMapping;
20
+ /** Whether to capture the cursor via Pointer Lock API. */
21
+ pointerLock?: boolean;
22
+ /** Sensitivity multiplier for mouse movement (default 0.002). */
23
+ sensitivity?: number;
24
+ }
25
+ interface GameInputPlayerConfig {
26
+ key?: KeyboardMapping;
27
+ mouse?: MouseConfig;
28
+ includeDefaults?: boolean;
29
+ }
30
+ interface GameInputConfig {
31
+ p1?: GameInputPlayerConfig;
32
+ p2?: GameInputPlayerConfig;
33
+ p3?: GameInputPlayerConfig;
34
+ p4?: GameInputPlayerConfig;
35
+ p5?: GameInputPlayerConfig;
36
+ p6?: GameInputPlayerConfig;
37
+ p7?: GameInputPlayerConfig;
38
+ p8?: GameInputPlayerConfig;
39
+ }
40
+ interface ZylemGameConfig<StageInterface, GameInterface, TGlobals extends BaseGlobals> {
41
+ id: string;
42
+ globals?: TGlobals;
43
+ stages?: StageInterface[];
44
+ update?: UpdateFunction<GameInterface>;
45
+ debug?: boolean;
46
+ time?: number;
47
+ input?: GameInputConfig;
48
+ }
49
+
50
+ interface SceneState {
51
+ backgroundColor: Color | string;
52
+ backgroundImage: string | null;
53
+ backgroundShader?: ZylemShader | null;
54
+ }
55
+ declare class ZylemScene implements Entity<ZylemScene> {
56
+ type: string;
57
+ _setup?: SetupFunction<ZylemScene>;
58
+ scene: Scene;
59
+ /** @deprecated Use cameraManager instead */
60
+ zylemCamera: ZylemCamera;
61
+ cameraManager: CameraManager | null;
62
+ containerElement: HTMLElement | null;
63
+ update: LifecycleFunction<ZylemScene>;
64
+ _collision?: ((entity: any, other: any, globals?: any) => void) | undefined;
65
+ _destroy?: ((globals?: any) => void) | undefined;
66
+ name?: string | undefined;
67
+ tag?: Set<string> | undefined;
68
+ private skyboxMaterial;
69
+ constructor(id: string, camera: ZylemCamera, state: SceneState);
70
+ /**
71
+ * Create a large inverted box with the shader for skybox effect
72
+ * Supports both GLSL (ShaderMaterial) and TSL (MeshBasicNodeMaterial) shaders
73
+ */
74
+ private setupBackgroundShader;
75
+ setup(): void;
76
+ destroy(): void;
77
+ /**
78
+ * Setup camera with the scene.
79
+ * Supports both legacy single camera and CameraManager modes.
80
+ */
81
+ setupCamera(scene: Scene, camera: ZylemCamera, rendererManager?: RendererManager): void;
82
+ /**
83
+ * Setup with a CameraManager (multi-camera support).
84
+ */
85
+ setupCameraManager(scene: Scene, cameraManager: CameraManager, rendererManager: RendererManager): Promise<void>;
86
+ /**
87
+ * Add a camera (rig or direct) to the scene graph.
88
+ */
89
+ private addCameraToScene;
90
+ /**
91
+ * Setup scene lighting
92
+ */
93
+ setupLighting(scene: Scene): void;
94
+ /**
95
+ * Update renderer size - delegates to camera manager or camera
96
+ */
97
+ updateRenderer(width: number, height: number): void;
98
+ /**
99
+ * Add object to scene
100
+ */
101
+ add(object: Object3D, position?: Vector3): void;
102
+ /**
103
+ * Add game entity to scene
104
+ */
105
+ addEntity(entity: GameEntity<any>): void;
106
+ /**
107
+ * Add an entity's group or mesh to the scene (for late-loaded models).
108
+ * Uses entity's current body position if physics is active.
109
+ */
110
+ addEntityGroup(entity: GameEntity<any>): void;
111
+ private isAttachedOutsideScene;
112
+ /**
113
+ * Add debug helpers to scene
114
+ */
115
+ debugScene(): void;
116
+ /**
117
+ * Update skybox shader uniforms (only applies to GLSL ShaderMaterial)
118
+ * TSL shaders use the time node which auto-updates
119
+ */
120
+ updateSkybox(delta: number): void;
121
+ }
122
+
123
+ /**
124
+ * Configuration for batch key generation
125
+ */
126
+ interface BatchKeyConfig {
127
+ geometryType: string;
128
+ dimensions: Record<string, number>;
129
+ materialPath?: string | null;
130
+ shaderType?: 'standard' | 'custom';
131
+ colorHex?: number;
132
+ }
133
+ /**
134
+ * Manages instanced mesh batching for entities
135
+ */
136
+ declare class InstanceManager {
137
+ private batches;
138
+ private entityToBatch;
139
+ private scene;
140
+ /** Default initial capacity for new batches */
141
+ static DEFAULT_CAPACITY: number;
142
+ /** Factor to grow batch when full */
143
+ static GROWTH_FACTOR: number;
144
+ /**
145
+ * Set the scene to add instanced meshes to
146
+ */
147
+ setScene(scene: Object3D): void;
148
+ /**
149
+ * Generate a batch key from configuration
150
+ */
151
+ static generateBatchKey(config: BatchKeyConfig): string;
152
+ /**
153
+ * Register an entity with the instance manager
154
+ * @returns The instance index, or -1 if registration failed
155
+ */
156
+ register(entity: GameEntity<any>, geometry: BufferGeometry, material: Material, batchKey: string): number;
157
+ /**
158
+ * Unregister an entity from the instance manager
159
+ */
160
+ unregister(entity: GameEntity<any>): void;
161
+ /**
162
+ * Mark an entity's transform as dirty (needs syncing)
163
+ */
164
+ markDirty(entity: GameEntity<any>): void;
165
+ /**
166
+ * Update all dirty instance transforms
167
+ * Call this once per frame
168
+ */
169
+ /**
170
+ * Update all active instance transforms
171
+ * Call this once per frame
172
+ */
173
+ update(): void;
174
+ private updateInstanceMatrix;
175
+ /**
176
+ * Get batch info for an entity
177
+ */
178
+ getBatchInfo(entity: GameEntity<any>): {
179
+ batchKey: string;
180
+ instanceId: number;
181
+ } | null;
182
+ /**
183
+ * Get statistics about current batching
184
+ */
185
+ getStats(): {
186
+ batchCount: number;
187
+ totalInstances: number;
188
+ batches: {
189
+ key: string;
190
+ count: number;
191
+ capacity: number;
192
+ }[];
193
+ };
194
+ /**
195
+ * Dispose all batches and release resources
196
+ */
197
+ dispose(): void;
198
+ /**
199
+ * Create a new batch group
200
+ */
201
+ private createBatch;
202
+ /**
203
+ * Grow a batch's capacity
204
+ */
205
+ private growBatch;
206
+ }
207
+
208
+ /**
209
+ * Provides BaseNode-like lifecycle without ECS/children. Consumers implement
210
+ * the protected hooks and may assign public setup/update/destroy callbacks.
211
+ */
212
+ declare abstract class LifeCycleBase<TSelf> {
213
+ update: UpdateFunction<TSelf>;
214
+ setup: SetupFunction<TSelf>;
215
+ destroy: DestroyFunction<TSelf>;
216
+ protected abstract _setup(context: SetupContext<TSelf>): void;
217
+ protected abstract _update(context: UpdateContext<TSelf>): void;
218
+ protected abstract _destroy(context: DestroyContext<TSelf>): void;
219
+ nodeSetup(context: SetupContext<TSelf>): void;
220
+ nodeUpdate(context: UpdateContext<TSelf>): void;
221
+ nodeDestroy(context: DestroyContext<TSelf>): void;
222
+ }
223
+
224
+ type StageSystem = {
225
+ _childrenMap: Map<number, StageEntity & {
226
+ body: PhysicsPoseReadable | null;
227
+ }>;
228
+ _world: {
229
+ interpolationAlpha: number;
230
+ } | null;
231
+ };
232
+ type TransformSystemResult = {
233
+ system: ReturnType<typeof defineSystem>;
234
+ destroy: (world: IWorld) => void;
235
+ };
236
+ declare function createTransformSystem(stage: StageSystem): TransformSystemResult;
237
+
238
+ type AddEntityFactory = (params: {
239
+ position: Vector3;
240
+ normal?: Vector3;
241
+ }) => Promise<any> | any;
242
+ interface StageDebugDelegateOptions {
243
+ maxRayDistance?: number;
244
+ addEntityFactory?: AddEntityFactory | null;
245
+ }
246
+ /**
247
+ * Self-managing debug delegate that subscribes to `debugState` internally.
248
+ *
249
+ * When debug is enabled it lazily initializes visuals and DOM listeners.
250
+ * When debug is disabled it tears down visuals but stays alive so it can
251
+ * re-activate without being recreated. Call `dispose()` to fully tear down.
252
+ */
253
+ declare class StageDebugDelegate {
254
+ private stage;
255
+ private options;
256
+ private mouseNdc;
257
+ private raycaster;
258
+ private isMouseDown;
259
+ private domDisposeFns;
260
+ private domListenersAttached;
261
+ private debugCursor;
262
+ private debugLines;
263
+ private cameraDebugDelegate;
264
+ private debugStateUnsubscribe;
265
+ constructor(stage: ZylemStage, options?: StageDebugDelegateOptions);
266
+ private syncWithDebugState;
267
+ /** Initialize DOM listeners and camera debug delegate when debug is turned on. */
268
+ private activate;
269
+ /** Tear down visuals and camera debug delegate when debug is turned off. */
270
+ private deactivate;
271
+ private initDebugVisuals;
272
+ private disposeDebugVisuals;
273
+ update(): void;
274
+ /** Full teardown — unsubscribes from debugState and cleans up all resources. */
275
+ dispose(): void;
276
+ private handleActionOnHit;
277
+ private attachDomListeners;
278
+ }
279
+
280
+ /**
281
+ * Delegate for managing loading events and progress within a stage.
282
+ * Handles subscription to loading events and broadcasting progress.
283
+ * Emits to game event bus for game-level observation.
284
+ */
285
+ declare class StageLoadingDelegate {
286
+ private loadingHandlers;
287
+ private stageName?;
288
+ private stageIndex?;
289
+ /**
290
+ * Set stage context for event bus emissions.
291
+ */
292
+ setStageContext(stageName: string, stageIndex: number): void;
293
+ /**
294
+ * Subscribe to loading events.
295
+ *
296
+ * @param callback Invoked for each loading event (start, progress, complete)
297
+ * @returns Unsubscribe function
298
+ */
299
+ onLoading(callback: (event: LoadingEvent) => void): () => void;
300
+ /**
301
+ * Emit a loading event to all subscribers and to the game event bus.
302
+ *
303
+ * @param event The loading event to broadcast
304
+ */
305
+ emit(event: LoadingEvent): void;
306
+ /**
307
+ * Emit a start loading event.
308
+ */
309
+ emitStart(message?: string): void;
310
+ /**
311
+ * Emit a progress loading event.
312
+ */
313
+ emitProgress(message: string, current: number, total: number): void;
314
+ /**
315
+ * Emit a complete loading event.
316
+ */
317
+ emitComplete(message?: string): void;
318
+ /**
319
+ * Clear all loading handlers.
320
+ */
321
+ dispose(): void;
322
+ }
323
+
324
+ /**
325
+ * Delegate for handling deferred model loading in entities.
326
+ * Subscribes to model:loaded events and adds entity groups to the scene
327
+ * when they become available after async loading completes.
328
+ */
329
+ declare class StageEntityModelDelegate {
330
+ private scene;
331
+ private onEntityReady;
332
+ private pendingEntities;
333
+ private modelLoadedHandler;
334
+ /**
335
+ * Initialize the delegate with the scene reference and start listening.
336
+ */
337
+ attach(scene: ZylemScene, onEntityReady?: (entity: GameEntity<any>) => void): void;
338
+ /**
339
+ * Register an entity for observation.
340
+ * When its model loads, the group will be added to the scene.
341
+ */
342
+ observe(entity: GameEntity<any>): void;
343
+ /**
344
+ * Unregister an entity (e.g., when removed before model loads).
345
+ */
346
+ unobserve(entityId: string): void;
347
+ /**
348
+ * Handle model loaded event - add group to scene if entity is pending.
349
+ */
350
+ private handleModelLoaded;
351
+ /**
352
+ * Cleanup all subscriptions and pending entities.
353
+ */
354
+ dispose(): void;
355
+ }
356
+
357
+ type NodeLike$1 = {
358
+ create: Function;
359
+ };
360
+ type StageEntityInput = NodeLike$1 | Promise<any> | (() => NodeLike$1 | Promise<any>);
361
+ /**
362
+ * Runtime context provided by ZylemStage after scene and world are initialized.
363
+ */
364
+ interface EntityDelegateContext {
365
+ scene: ZylemScene;
366
+ world: ZylemWorld;
367
+ ecs: ReturnType<typeof bitecs.createWorld>;
368
+ instanceManager: InstanceManager | null;
369
+ /** Resolved camera for entity setup contexts. */
370
+ camera: ZylemCamera;
371
+ }
372
+ /**
373
+ * Delegate responsible for entity spawning, tracking, queuing, removal, and lookup.
374
+ *
375
+ * Owns all entity-related state and exposes it to ZylemStage for orchestration
376
+ * and to external consumers (debug delegate, transform system) via public getters.
377
+ */
378
+ declare class StageEntityDelegate {
379
+ private static readonly EMPTY_BEHAVIOR_LINKS;
380
+ /** Entities queued before load completes. */
381
+ children: BaseNode[];
382
+ /** EID → BaseNode map of all live entities. */
383
+ readonly childrenMap: Map<number, BaseNode>;
384
+ /** UUID → BaseNode map populated when debug mode is active. */
385
+ readonly debugMap: Map<string, BaseNode>;
386
+ /** UUID → EID reverse lookup for O(1) removal. */
387
+ private readonly uuidToEid;
388
+ private pendingEntities;
389
+ private pendingPromises;
390
+ private _isLoaded;
391
+ private entityAddedHandlers;
392
+ /** ECS behavior systems auto-registered from entity refs or manually added. */
393
+ readonly behaviorSystems: BehaviorSystem[];
394
+ readonly registeredSystemKeys: Set<symbol>;
395
+ readonly behaviorEntityIndex: Map<symbol, Set<BehaviorEntityLink>>;
396
+ private readonly behaviorLinksByUuid;
397
+ private scene;
398
+ private world;
399
+ private ecs;
400
+ private instanceManager;
401
+ private camera;
402
+ private loadingDelegate;
403
+ private entityModelDelegate;
404
+ constructor(loadingDelegate: StageLoadingDelegate, entityModelDelegate: StageEntityModelDelegate);
405
+ get isLoaded(): boolean;
406
+ set isLoaded(value: boolean);
407
+ /**
408
+ * Bind runtime context after scene and world are initialized.
409
+ * Must be called before any spawn/enqueue operations.
410
+ */
411
+ attach(context: EntityDelegateContext): void;
412
+ /**
413
+ * Create, register, and add an entity to the scene/world.
414
+ * Safe to call only after `attach` when scene/world exist.
415
+ */
416
+ spawnEntity(child: BaseNode): Promise<void>;
417
+ handleLateModelReady(entity: GameEntity<any>): void;
418
+ /**
419
+ * Register an entity for instanced rendering if opted in with `batched: true`.
420
+ */
421
+ private tryRegisterInstance;
422
+ private maybeAttachEntityPhysics;
423
+ /** Add the entity to internal maps and notify listeners. */
424
+ addEntityToStage(entity: BaseNode): void;
425
+ /**
426
+ * Remove an entity and its resources by its UUID.
427
+ * Uses a uuid→eid reverse map for O(1) lookup.
428
+ * @returns true if removed, false if not found or stage not ready
429
+ */
430
+ removeEntityByUuid(uuid: string): boolean;
431
+ /** Get an entity by its name; returns null if not found. */
432
+ getEntityByName(name: string): BaseNode | null;
433
+ /** Build a serializable state snapshot for an entity. */
434
+ buildEntityState(child: BaseNode): Partial<BaseEntityInterface>;
435
+ /**
436
+ * Subscribe to entity-added events.
437
+ * @param callback Invoked for each entity when added
438
+ * @param options.replayExisting If true and stage already loaded, replays existing entities
439
+ * @returns Unsubscribe function
440
+ */
441
+ onEntityAdded(callback: (entity: BaseNode) => void, options?: {
442
+ replayExisting?: boolean;
443
+ }): () => void;
444
+ /**
445
+ * Enqueue items to be spawned. Items can be:
446
+ * - BaseNode instances (immediate or deferred until load)
447
+ * - Factory functions returning BaseNode or Promise<BaseNode>
448
+ * - Promises resolving to BaseNode
449
+ */
450
+ enqueue(...items: StageEntityInput[]): void;
451
+ private handleEntityImmediatelyOrQueue;
452
+ private handlePromiseWithSpawnOnResolve;
453
+ /**
454
+ * Generator that yields between entity loads for real-time progress updates.
455
+ */
456
+ private entityLoadGenerator;
457
+ /** Yields to the event loop via MessageChannel (~0.1ms vs ~4ms for setTimeout). */
458
+ private yieldToEventLoop;
459
+ /**
460
+ * Runs the entity load generator, yielding to the event loop in batches.
461
+ * Emits progress events through the loading delegate.
462
+ */
463
+ runEntityLoadGenerator(): Promise<void>;
464
+ /**
465
+ * Register an ECS behavior system to run each frame.
466
+ * @param systemOrFactory A BehaviorSystem instance or factory function
467
+ */
468
+ registerSystem(systemOrFactory: BehaviorSystem | BehaviorSystemFactory): void;
469
+ /**
470
+ * Destroy all entities and clear internal state.
471
+ * Called by ZylemStage._destroy().
472
+ */
473
+ destroyAll(): void;
474
+ private registerBehaviorLinks;
475
+ private unregisterBehaviorLinks;
476
+ }
477
+
478
+ interface ZylemStageConfig {
479
+ inputs: Record<string, string[]>;
480
+ backgroundColor: Color | string;
481
+ backgroundImage: string | null;
482
+ backgroundShader: any | null;
483
+ gravity: Vector3;
484
+ variables: Record<string, any>;
485
+ /** Physics update rate in Hz (default 60). */
486
+ physicsRate: number;
487
+ /** Run physics in a Web Worker for true parallelism (default false). */
488
+ usePhysicsWorker: boolean;
489
+ /** URL to the physics worker script (required when usePhysicsWorker is true). */
490
+ physicsWorkerUrl?: URL | string;
491
+ stageRef?: Stage;
492
+ }
493
+ type StageOptionItem = Partial<ZylemStageConfig> | CameraWrapper | StageEntityInput;
494
+ type StageOptions = [] | [Partial<ZylemStageConfig>, ...StageOptionItem[]];
495
+ type StageState = ZylemStageConfig & {
496
+ entities: GameEntityInterface[];
497
+ };
498
+ /**
499
+ * ZylemStage orchestrates scene, physics world, entities, and lifecycle.
500
+ *
501
+ * Responsibilities:
502
+ * - Manage stage configuration (background, inputs, gravity, variables)
503
+ * - Initialize and own `ZylemScene` and `ZylemWorld`
504
+ * - Coordinate delegates for entities, camera, loading, debug, and models
505
+ * - Drive per-frame updates and transform system
506
+ */
507
+ declare class ZylemStage extends LifeCycleBase<ZylemStage> {
508
+ type: string;
509
+ state: StageState;
510
+ gravity: Vector3;
511
+ world: ZylemWorld | null;
512
+ scene: ZylemScene | null;
513
+ instanceManager: InstanceManager | null;
514
+ ecs: bitecs.IWorld;
515
+ transformSystem: ReturnType<typeof createTransformSystem> | null;
516
+ debugDelegate: StageDebugDelegate | null;
517
+ uuid: string;
518
+ wrapperRef: Stage | null;
519
+ camera?: CameraWrapper;
520
+ cameras: CameraWrapper[];
521
+ cameraRef?: ZylemCamera | null;
522
+ /** Camera manager for multi-camera support */
523
+ cameraManagerRef: CameraManager | null;
524
+ /** Shared renderer manager (injected by the game) */
525
+ rendererManager: RendererManager | null;
526
+ private cameraDelegate;
527
+ private loadingDelegate;
528
+ private entityModelDelegate;
529
+ private readonly childUpdateParams;
530
+ /** Entity management delegate — public for external consumers (debug, transform system). */
531
+ readonly entityDelegate: StageEntityDelegate;
532
+ /**
533
+ * Create a new stage.
534
+ * @param options Stage options: partial config, camera, and initial entities or factories
535
+ */
536
+ constructor(options?: StageOptions);
537
+ private setState;
538
+ /**
539
+ * Load and initialize the stage's scene and world.
540
+ * Uses generator pattern to yield control to event loop for real-time progress.
541
+ * @param id DOM element id for the renderer container
542
+ * @param camera Optional camera override
543
+ */
544
+ load(id: string, camera?: ZylemCamera | null, rendererManager?: RendererManager | null): Promise<void>;
545
+ protected _setup(params: SetupContext<ZylemStage>): void;
546
+ protected _update(params: UpdateContext<ZylemStage>): void;
547
+ outOfLoop(): void;
548
+ /** Update debug overlays and helpers if enabled. */
549
+ debugUpdate(): void;
550
+ /** Cleanup owned resources when the stage is destroyed. */
551
+ protected _destroy(params: DestroyContext<ZylemStage>): void;
552
+ /** Forward to entity delegate. */
553
+ spawnEntity(child: BaseNode): Promise<void>;
554
+ /** Forward to entity delegate. */
555
+ buildEntityState(child: BaseNode): Partial<BaseEntityInterface>;
556
+ /** Forward to entity delegate. */
557
+ onEntityAdded(callback: (entity: BaseNode) => void, options?: {
558
+ replayExisting?: boolean;
559
+ }): () => void;
560
+ onLoading(callback: (event: LoadingEvent) => void): () => void;
561
+ /**
562
+ * Register an ECS behavior system to run each frame.
563
+ * @param systemOrFactory A BehaviorSystem instance or factory function
564
+ * @returns this for chaining
565
+ */
566
+ registerSystem(systemOrFactory: BehaviorSystem | BehaviorSystemFactory): this;
567
+ /** Forward to entity delegate. */
568
+ removeEntityByUuid(uuid: string): boolean;
569
+ /** Forward to entity delegate. */
570
+ getEntityByName(name: string): BaseNode<any, any> | null;
571
+ /** Forward to entity delegate. */
572
+ enqueue(...items: StageEntityInput[]): void;
573
+ logMissingEntities(): void;
574
+ /** Add a camera to this stage's camera manager. */
575
+ addCamera(camera: ZylemCamera, name?: string): string | null;
576
+ /** Remove a camera from this stage's camera manager. */
577
+ removeCamera(nameOrRef: string | ZylemCamera): boolean;
578
+ /** Set the active camera by name or reference. */
579
+ setActiveCamera(nameOrRef: string | ZylemCamera): boolean;
580
+ /** Get a camera by name from the camera manager. */
581
+ getCamera(name: string): ZylemCamera | null;
582
+ /** Resize renderer viewport. */
583
+ resize(width: number, height: number): void;
584
+ }
585
+
586
+ type ZylemDiskOptions = GameEntityOptions & {
587
+ innerRadius?: number;
588
+ outerRadius?: number;
589
+ thetaSegments?: number;
590
+ };
591
+ declare const DISK_TYPE: unique symbol;
592
+ declare class ZylemDisk extends GameEntity<ZylemDiskOptions> {
593
+ static type: symbol;
594
+ constructor(options?: ZylemDiskOptions);
595
+ buildInfo(): Record<string, any>;
596
+ }
597
+ type DiskOptions = BaseNode | Partial<ZylemDiskOptions>;
598
+ declare function createDisk(...args: Array<DiskOptions>): ZylemDisk;
599
+
600
+ /**
601
+ * Maps entity type symbols to their class types.
602
+ * Used by getEntityByName to infer return types.
603
+ */
604
+ interface EntityTypeMap {
605
+ [SPRITE_TYPE]: ZylemSprite;
606
+ [SPHERE_TYPE]: ZylemSphere;
607
+ [RECT_TYPE]: ZylemRect;
608
+ [TEXT_TYPE]: ZylemText;
609
+ [BOX_TYPE]: ZylemBox;
610
+ [PLANE_TYPE]: ZylemPlane;
611
+ [ZONE_TYPE]: ZylemZone;
612
+ [ACTOR_TYPE]: ZylemActor;
613
+ [DISK_TYPE]: ZylemDisk;
614
+ [CONE_TYPE]: ZylemCone;
615
+ [PYRAMID_TYPE]: ZylemPyramid;
616
+ [CYLINDER_TYPE]: ZylemCylinder;
617
+ [PILL_TYPE]: ZylemPill;
618
+ }
619
+
620
+ type NodeLike = {
621
+ create: Function;
622
+ };
623
+ type AnyNode = NodeLike | Promise<NodeLike>;
624
+ type EntityInput = AnyNode | (() => AnyNode) | (() => Promise<any>);
625
+ declare class Stage {
626
+ wrappedStage: ZylemStage | null;
627
+ options: StageOptionItem[];
628
+ private _pendingEntities;
629
+ private setupCallbacks;
630
+ private updateCallbacks;
631
+ private destroyCallbacks;
632
+ private pendingLoadingCallbacks;
633
+ private eventDelegate;
634
+ /** Per-stage input configuration overrides. Merged with game-level defaults on stage load. */
635
+ inputConfig: GameInputConfig | null;
636
+ /**
637
+ * Callback set by the game to trigger input reconfiguration
638
+ * when this stage's input config changes at runtime.
639
+ * @internal
640
+ */
641
+ onInputConfigChanged: (() => void) | null;
642
+ constructor(options: StageOptions);
643
+ /**
644
+ * Set composable input configuration for this stage.
645
+ * Multiple configs are deep-merged (later configs win on key conflicts).
646
+ * If this stage is currently active, the change takes effect immediately.
647
+ * @example stage.setInputConfiguration(useArrowsForAxes('p1'), useWASDForDirections('p2'));
648
+ */
649
+ setInputConfiguration(...configs: GameInputConfig[]): this;
650
+ load(id: string, camera?: ZylemCamera | CameraWrapper | null, rendererManager?: RendererManager | null): Promise<void>;
651
+ private applyLifecycleCallbacks;
652
+ addEntities(entities: BaseNode[]): Promise<void>;
653
+ add(...inputs: Array<EntityInput>): void;
654
+ private addToBlueprints;
655
+ private addToStage;
656
+ start(params: SetupContext<ZylemStage>): void;
657
+ onUpdate(...callbacks: UpdateFunction<ZylemStage>[]): this;
658
+ onSetup(...callbacks: SetupFunction<ZylemStage>[]): this;
659
+ onDestroy(...callbacks: DestroyFunction<ZylemStage>[]): this;
660
+ onLoading(callback: (event: LoadingEvent) => void): () => void;
661
+ /**
662
+ * Find an entity by name on the current stage.
663
+ * @param name The name of the entity to find
664
+ * @param type Optional type symbol for type inference (e.g., TEXT_TYPE, SPRITE_TYPE)
665
+ * @returns The entity if found, or undefined
666
+ * @example stage.getEntityByName('scoreText', TEXT_TYPE)
667
+ */
668
+ getEntityByName<T extends symbol | void = void>(name: string, type?: T): T extends keyof EntityTypeMap ? EntityTypeMap[T] | undefined : BaseNode | undefined;
669
+ /**
670
+ * Add a camera to this stage.
671
+ * @param camera The ZylemCamera or CameraWrapper to add
672
+ * @param name Optional name for lookup
673
+ */
674
+ addCamera(camera: ZylemCamera | CameraWrapper, name?: string): string | null;
675
+ /**
676
+ * Remove a camera from this stage by name or reference.
677
+ */
678
+ removeCamera(nameOrRef: string | ZylemCamera | CameraWrapper): boolean;
679
+ /**
680
+ * Set the active camera by name or reference.
681
+ */
682
+ setActiveCamera(nameOrRef: string | ZylemCamera | CameraWrapper): boolean;
683
+ /**
684
+ * Get a camera by name from the camera manager.
685
+ */
686
+ getCamera(name: string): ZylemCamera | null;
687
+ /**
688
+ * Dispatch an event from the stage.
689
+ * Events are emitted both locally and to the global event bus.
690
+ */
691
+ dispatch<K extends keyof StageEvents>(event: K, payload: StageEvents[K]): void;
692
+ /**
693
+ * Listen for events on this stage instance.
694
+ * @returns Unsubscribe function
695
+ */
696
+ listen<K extends keyof StageEvents>(event: K, handler: (payload: StageEvents[K]) => void): () => void;
697
+ /**
698
+ * Clean up stage resources including event subscriptions.
699
+ */
700
+ dispose(): void;
701
+ }
702
+ /**
703
+ * Create a stage with optional camera
704
+ */
705
+ declare function createStage(...options: StageOptions): Stage;
706
+
707
+ /**
708
+ * Stage state interface - minimal to prevent circular dependencies
709
+ */
710
+ interface StageStateInterface {
711
+ backgroundColor: Color;
712
+ backgroundImage: string | null;
713
+ inputs: {
714
+ p1: string[];
715
+ p2: string[];
716
+ };
717
+ variables: Record<string, any>;
718
+ gravity: Vector3;
719
+ entities: Partial<BaseEntityInterface>[];
720
+ stageRef?: any;
721
+ }
722
+ /**
723
+ * Minimal stage interface to break circular dependencies
724
+ */
725
+ interface StageInterface {
726
+ uuid: string;
727
+ children: any[];
728
+ state: StageStateInterface;
729
+ }
730
+
731
+ export { type BaseGlobals as B, type GameInputConfig as G, type StageStateInterface as S, type ZylemGameConfig as Z, type StageOptions as a, Stage as b, createStage as c, createDisk as d, type StageInterface as e };