@zylem/game-lib 0.5.1 → 0.6.2

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.
@@ -1,30 +1,17 @@
1
- import { G as GameEntity, U as UpdateContext, S as SetupFunction, b as UpdateFunction, D as DestroyFunction, c as SetupContext, d as DestroyContext, e as BaseNode, L as LoadingEvent } from './entity-bQElAdpo.js';
1
+ import { S as SetupFunction, Z as ZylemShaderObject, G as GameEntity, U as UpdateFunction, D as DestroyFunction, a as SetupContext, b as UpdateContext, c as DestroyContext, d as ZylemWorld, B as BaseNode, L as LoadingEvent, e as BehaviorSystem, f as BehaviorSystemFactory, g as GameEntityOptions, h as StageEvents } from './world-C8tQ7Plj.js';
2
2
  import * as bitecs from 'bitecs';
3
- import { Vector3, Scene, Color, Object3D, Group } from 'three';
4
- import RAPIER__default, { World, RigidBody, Collider } from '@dimforge/rapier3d-compat';
5
- import { E as Entity, Z as ZylemCamera, L as LifecycleFunction, C as CameraDebugDelegate, b as CameraDebugState, d as CameraWrapper } from './camera-Dk-fOVZE.js';
6
-
7
- declare class ZylemWorld implements Entity<ZylemWorld> {
8
- type: string;
9
- world: World;
10
- collisionMap: Map<string, GameEntity<any>>;
11
- collisionBehaviorMap: Map<string, GameEntity<any>>;
12
- _removalMap: Map<string, GameEntity<any>>;
13
- static loadPhysics(gravity: Vector3): Promise<RAPIER__default.World>;
14
- constructor(world: World);
15
- addEntity(entity: any): void;
16
- setForRemoval(entity: any): void;
17
- destroyEntity(entity: GameEntity<any>): void;
18
- setup(): void;
19
- update(params: UpdateContext<any>): void;
20
- updatePostCollisionBehaviors(delta: number): void;
21
- updateColliders(delta: number): void;
22
- destroy(): void;
23
- }
3
+ import { defineSystem, IWorld } from 'bitecs';
4
+ import { Scene, Color, Object3D, Vector3 } from 'three';
5
+ import { E as Entity, L as LifecycleFunction, S as StageEntity } from './entity-Bq_eNEDI.js';
6
+ import { Z as ZylemCamera, C as CameraDebugDelegate, a as CameraDebugState, b as CameraWrapper } from './camera-CeJPAgGg.js';
7
+ import { G as GameEntityInterface, B as BaseEntityInterface } from './entity-types-DAu8sGJH.js';
8
+ import RAPIER__default from '@dimforge/rapier3d-compat';
9
+ 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 } from './entities-DvByhMGU.js';
24
10
 
25
11
  interface SceneState {
26
12
  backgroundColor: Color | string;
27
13
  backgroundImage: string | null;
14
+ backgroundShader?: ZylemShaderObject | null;
28
15
  }
29
16
  declare class ZylemScene implements Entity<ZylemScene> {
30
17
  type: string;
@@ -37,7 +24,13 @@ declare class ZylemScene implements Entity<ZylemScene> {
37
24
  _destroy?: ((globals?: any) => void) | undefined;
38
25
  name?: string | undefined;
39
26
  tag?: Set<string> | undefined;
27
+ private skyboxMaterial;
40
28
  constructor(id: string, camera: ZylemCamera, state: SceneState);
29
+ /**
30
+ * Create a large inverted box with the shader for skybox effect
31
+ * Uses the pos.xyww trick to ensure skybox is always at maximum depth
32
+ */
33
+ private setupBackgroundShader;
41
34
  setup(): void;
42
35
  destroy(): void;
43
36
  /**
@@ -60,32 +53,19 @@ declare class ZylemScene implements Entity<ZylemScene> {
60
53
  * Add game entity to scene
61
54
  */
62
55
  addEntity(entity: GameEntity<any>): void;
56
+ /**
57
+ * Add an entity's group or mesh to the scene (for late-loaded models).
58
+ * Uses entity's current body position if physics is active.
59
+ */
60
+ addEntityGroup(entity: GameEntity<any>): void;
63
61
  /**
64
62
  * Add debug helpers to scene
65
63
  */
66
64
  debugScene(): void;
67
- }
68
-
69
- /**
70
- * Base entity interface - shared across modules to prevent circular dependencies
71
- */
72
- interface BaseEntityInterface {
73
- uuid: string;
74
- name: string;
75
- eid: number;
76
- group: Group | null;
77
- body: RigidBody | null;
78
- collider: Collider | null;
79
- }
80
- /**
81
- * Game entity interface - minimal interface to break circular dependencies
82
- */
83
- interface GameEntityInterface extends BaseEntityInterface {
84
- type: string;
85
- isStatic: boolean;
86
- setPosition(x: number, y: number, z: number): void;
87
- setRotation(x: number, y: number, z: number): void;
88
- setScale(x: number, y: number, z: number): void;
65
+ /**
66
+ * Update skybox shader uniforms
67
+ */
68
+ updateSkybox(delta: number): void;
89
69
  }
90
70
 
91
71
  /**
@@ -104,6 +84,17 @@ declare abstract class LifeCycleBase<TSelf> {
104
84
  nodeDestroy(context: DestroyContext<TSelf>): void;
105
85
  }
106
86
 
87
+ type StageSystem = {
88
+ _childrenMap: Map<number, StageEntity & {
89
+ body: RAPIER__default.RigidBody;
90
+ }>;
91
+ };
92
+ type TransformSystemResult = {
93
+ system: ReturnType<typeof defineSystem>;
94
+ destroy: (world: IWorld) => void;
95
+ };
96
+ declare function createTransformSystem(stage: StageSystem): TransformSystemResult;
97
+
107
98
  type AddEntityFactory = (params: {
108
99
  position: Vector3;
109
100
  normal?: Vector3;
@@ -122,6 +113,8 @@ declare class StageDebugDelegate {
122
113
  private debugCursor;
123
114
  private debugLines;
124
115
  constructor(stage: ZylemStage, options?: StageDebugDelegateOptions);
116
+ private initDebugVisuals;
117
+ private disposeDebugVisuals;
125
118
  update(): void;
126
119
  dispose(): void;
127
120
  private handleActionOnHit;
@@ -143,6 +136,7 @@ interface ZylemStageConfig {
143
136
  inputs: Record<string, string[]>;
144
137
  backgroundColor: Color | string;
145
138
  backgroundImage: string | null;
139
+ backgroundShader: any | null;
146
140
  gravity: Vector3;
147
141
  variables: Record<string, any>;
148
142
  stageRef?: Stage;
@@ -179,39 +173,48 @@ declare class ZylemStage extends LifeCycleBase<ZylemStage> {
179
173
  private isLoaded;
180
174
  _debugMap: Map<string, BaseNode>;
181
175
  private entityAddedHandlers;
182
- private loadingHandlers;
183
176
  ecs: bitecs.IWorld;
184
177
  testSystem: any;
185
- transformSystem: any;
178
+ transformSystem: ReturnType<typeof createTransformSystem> | null;
179
+ private behaviorSystems;
180
+ private registeredSystemKeys;
186
181
  debugDelegate: StageDebugDelegate | null;
187
182
  cameraDebugDelegate: StageCameraDebugDelegate | null;
183
+ private debugStateUnsubscribe;
188
184
  uuid: string;
189
185
  wrapperRef: Stage | null;
190
186
  camera?: CameraWrapper;
191
187
  cameraRef?: ZylemCamera | null;
188
+ private cameraDelegate;
189
+ private loadingDelegate;
190
+ private entityModelDelegate;
192
191
  /**
193
192
  * Create a new stage.
194
193
  * @param options Stage options: partial config, camera, and initial entities or factories
195
194
  */
196
195
  constructor(options?: StageOptions);
197
- private parseOptions;
198
- private isZylemStageConfig;
199
- private isBaseNode;
200
- private isCameraWrapper;
201
- private isEntityInput;
202
- private isThenable;
203
196
  private handleEntityImmediatelyOrQueue;
204
197
  private handlePromiseWithSpawnOnResolve;
205
198
  private saveState;
206
199
  private setState;
207
200
  /**
208
201
  * Load and initialize the stage's scene and world.
202
+ * Uses generator pattern to yield control to event loop for real-time progress.
209
203
  * @param id DOM element id for the renderer container
210
204
  * @param camera Optional camera override
211
205
  */
212
206
  load(id: string, camera?: ZylemCamera | null): Promise<void>;
213
- private createDefaultCamera;
207
+ /**
208
+ * Generator that yields between entity loads for real-time progress updates.
209
+ */
210
+ private entityLoadGenerator;
211
+ /**
212
+ * Runs the entity load generator, yielding to the event loop between loads.
213
+ * This allows the browser to process events and update the UI in real-time.
214
+ */
215
+ private runEntityLoadGenerator;
214
216
  protected _setup(params: SetupContext<ZylemStage>): void;
217
+ private updateDebugDelegate;
215
218
  protected _update(params: UpdateContext<ZylemStage>): void;
216
219
  outOfLoop(): void;
217
220
  /** Update debug overlays and helpers if enabled. */
@@ -236,7 +239,12 @@ declare class ZylemStage extends LifeCycleBase<ZylemStage> {
236
239
  replayExisting?: boolean;
237
240
  }): () => void;
238
241
  onLoading(callback: (event: LoadingEvent) => void): () => void;
239
- private emitLoading;
242
+ /**
243
+ * Register an ECS behavior system to run each frame.
244
+ * @param systemOrFactory A BehaviorSystem instance or factory function
245
+ * @returns this for chaining
246
+ */
247
+ registerSystem(systemOrFactory: BehaviorSystem | BehaviorSystemFactory): this;
240
248
  /**
241
249
  * Remove an entity and its resources by its UUID.
242
250
  * @returns true if removed, false if not found or stage not ready
@@ -256,6 +264,36 @@ declare class ZylemStage extends LifeCycleBase<ZylemStage> {
256
264
  enqueue(...items: StageEntityInput[]): void;
257
265
  }
258
266
 
267
+ type ZylemDiskOptions = GameEntityOptions & {
268
+ innerRadius?: number;
269
+ outerRadius?: number;
270
+ thetaSegments?: number;
271
+ };
272
+ declare const DISK_TYPE: unique symbol;
273
+ declare class ZylemDisk extends GameEntity<ZylemDiskOptions> {
274
+ static type: symbol;
275
+ constructor(options?: ZylemDiskOptions);
276
+ buildInfo(): Record<string, any>;
277
+ }
278
+ type DiskOptions = BaseNode | Partial<ZylemDiskOptions>;
279
+ declare function createDisk(...args: Array<DiskOptions>): ZylemDisk;
280
+
281
+ /**
282
+ * Maps entity type symbols to their class types.
283
+ * Used by getEntityByName to infer return types.
284
+ */
285
+ interface EntityTypeMap {
286
+ [SPRITE_TYPE]: ZylemSprite;
287
+ [SPHERE_TYPE]: ZylemSphere;
288
+ [RECT_TYPE]: ZylemRect;
289
+ [TEXT_TYPE]: ZylemText;
290
+ [BOX_TYPE]: ZylemBox;
291
+ [PLANE_TYPE]: ZylemPlane;
292
+ [ZONE_TYPE]: ZylemZone;
293
+ [ACTOR_TYPE]: ZylemActor;
294
+ [DISK_TYPE]: ZylemDisk;
295
+ }
296
+
259
297
  type NodeLike = {
260
298
  create: Function;
261
299
  };
@@ -264,24 +302,74 @@ type EntityInput = AnyNode | (() => AnyNode) | (() => Promise<any>);
264
302
  declare class Stage {
265
303
  wrappedStage: ZylemStage | null;
266
304
  options: StageOptionItem[];
267
- update: UpdateFunction<ZylemStage>;
268
- setup: SetupFunction<ZylemStage>;
269
- destroy: DestroyFunction<ZylemStage>;
305
+ private _pendingEntities;
306
+ private setupCallbacks;
307
+ private updateCallbacks;
308
+ private destroyCallbacks;
309
+ private pendingLoadingCallbacks;
310
+ private eventDelegate;
270
311
  constructor(options: StageOptions);
271
312
  load(id: string, camera?: ZylemCamera | CameraWrapper | null): Promise<void>;
313
+ private applyLifecycleCallbacks;
272
314
  addEntities(entities: BaseNode[]): Promise<void>;
273
315
  add(...inputs: Array<EntityInput>): void;
274
316
  private addToBlueprints;
275
317
  private addToStage;
276
318
  start(params: SetupContext<ZylemStage>): void;
277
- onUpdate(...callbacks: UpdateFunction<ZylemStage>[]): void;
278
- onSetup(callback: SetupFunction<ZylemStage>): void;
279
- onDestroy(callback: DestroyFunction<ZylemStage>): void;
319
+ onUpdate(...callbacks: UpdateFunction<ZylemStage>[]): this;
320
+ onSetup(...callbacks: SetupFunction<ZylemStage>[]): this;
321
+ onDestroy(...callbacks: DestroyFunction<ZylemStage>[]): this;
280
322
  onLoading(callback: (event: LoadingEvent) => void): () => void;
323
+ /**
324
+ * Find an entity by name on the current stage.
325
+ * @param name The name of the entity to find
326
+ * @param type Optional type symbol for type inference (e.g., TEXT_TYPE, SPRITE_TYPE)
327
+ * @returns The entity if found, or undefined
328
+ * @example stage.getEntityByName('scoreText', TEXT_TYPE)
329
+ */
330
+ getEntityByName<T extends symbol | void = void>(name: string, type?: T): T extends keyof EntityTypeMap ? EntityTypeMap[T] | undefined : BaseNode | undefined;
331
+ /**
332
+ * Dispatch an event from the stage.
333
+ * Events are emitted both locally and to the global event bus.
334
+ */
335
+ dispatch<K extends keyof StageEvents>(event: K, payload: StageEvents[K]): void;
336
+ /**
337
+ * Listen for events on this stage instance.
338
+ * @returns Unsubscribe function
339
+ */
340
+ listen<K extends keyof StageEvents>(event: K, handler: (payload: StageEvents[K]) => void): () => void;
341
+ /**
342
+ * Clean up stage resources including event subscriptions.
343
+ */
344
+ dispose(): void;
281
345
  }
282
346
  /**
283
347
  * Create a stage with optional camera
284
348
  */
285
349
  declare function createStage(...options: StageOptions): Stage;
286
350
 
287
- export { type BaseEntityInterface as B, type StageOptions as S, Stage as a, createStage as c };
351
+ /**
352
+ * Stage state interface - minimal to prevent circular dependencies
353
+ */
354
+ interface StageStateInterface {
355
+ backgroundColor: Color;
356
+ backgroundImage: string | null;
357
+ inputs: {
358
+ p1: string[];
359
+ p2: string[];
360
+ };
361
+ variables: Record<string, any>;
362
+ gravity: Vector3;
363
+ entities: Partial<BaseEntityInterface>[];
364
+ stageRef?: any;
365
+ }
366
+ /**
367
+ * Minimal stage interface to break circular dependencies
368
+ */
369
+ interface StageInterface {
370
+ uuid: string;
371
+ children: any[];
372
+ state: StageStateInterface;
373
+ }
374
+
375
+ export { type StageStateInterface as S, type StageOptions as a, Stage as b, createStage as c, createDisk as d, type StageInterface as e };
package/dist/stage.d.ts CHANGED
@@ -1,26 +1,48 @@
1
- export { S as StageOptions, c as createStage } from './stage-CrmY7V0i.js';
2
- export { e as entitySpawner } from './entity-spawner-DNnLYnZq.js';
3
- import * as _sinclair_typebox from '@sinclair/typebox';
4
- import { Static } from '@sinclair/typebox';
5
- import './entity-bQElAdpo.js';
1
+ import { S as StageStateInterface } from './stage-types-Bd-KtcYT.js';
2
+ export { a as StageOptions, c as createStage } from './stage-types-Bd-KtcYT.js';
3
+ export { S as StageBlueprint, e as entitySpawner } from './blueprints-Cq3Ko6_G.js';
4
+ import './world-C8tQ7Plj.js';
6
5
  import 'three';
7
6
  import '@dimforge/rapier3d-compat';
7
+ import './entity-Bq_eNEDI.js';
8
8
  import 'bitecs';
9
- import './camera-Dk-fOVZE.js';
10
- import 'three/addons/controls/OrbitControls.js';
9
+ import 'mitt';
10
+ import './camera-CeJPAgGg.js';
11
11
  import 'three/examples/jsm/postprocessing/EffectComposer.js';
12
+ import './entity-types-DAu8sGJH.js';
13
+ import './entities-DvByhMGU.js';
14
+ import '@sinclair/typebox';
12
15
 
13
- declare const StageSchema: _sinclair_typebox.TObject<{
14
- id: _sinclair_typebox.TString;
15
- name: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
16
- entities: _sinclair_typebox.TArray<_sinclair_typebox.TObject<{
17
- id: _sinclair_typebox.TString;
18
- type: _sinclair_typebox.TString;
19
- position: _sinclair_typebox.TOptional<_sinclair_typebox.TTuple<[_sinclair_typebox.TNumber, _sinclair_typebox.TNumber]>>;
20
- data: _sinclair_typebox.TOptional<_sinclair_typebox.TRecord<_sinclair_typebox.TString, _sinclair_typebox.TAny>>;
21
- }>>;
22
- assets: _sinclair_typebox.TOptional<_sinclair_typebox.TArray<_sinclair_typebox.TString>>;
23
- }>;
24
- type StageBlueprint = Static<typeof StageSchema>;
16
+ /**
17
+ * Event name for stage state changes.
18
+ * Dispatched when the stage state proxy is updated.
19
+ */
20
+ declare const STAGE_STATE_CHANGE = "STAGE_STATE_CHANGE";
21
+ /**
22
+ * Event detail payload for STAGE_STATE_CHANGE events.
23
+ */
24
+ interface StageStateChangeEvent {
25
+ entities: StageStateInterface['entities'];
26
+ variables: StageStateInterface['variables'];
27
+ }
28
+ /**
29
+ * Initialize the stage state dispatcher.
30
+ * Subscribes to stageState changes and dispatches STAGE_STATE_CHANGE events to the window.
31
+ *
32
+ * @returns Unsubscribe function to stop dispatching events.
33
+ *
34
+ * @example
35
+ * // Start dispatching stage state changes
36
+ * const unsubscribe = initStageStateDispatcher();
37
+ *
38
+ * // Later, stop dispatching
39
+ * unsubscribe();
40
+ */
41
+ declare function initStageStateDispatcher(): () => void;
42
+ /**
43
+ * Manually dispatch the current stage state.
44
+ * Useful for initial sync when a listener is added.
45
+ */
46
+ declare function dispatchStageState(): void;
25
47
 
26
- export type { StageBlueprint };
48
+ export { STAGE_STATE_CHANGE, type StageStateChangeEvent, dispatchStageState, initStageStateDispatcher };