ecspresso 0.4.3 → 0.6.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.
- package/README.md +571 -9
- package/dist/asset-manager.d.ts +111 -0
- package/dist/asset-types.d.ts +104 -0
- package/dist/bundle.d.ts +65 -6
- package/dist/bundles/renderers/pixi.d.ts +248 -0
- package/dist/bundles/renderers/pixi.js +4 -0
- package/dist/bundles/renderers/pixi.js.map +12 -0
- package/dist/bundles/utils/timers.d.ts +113 -0
- package/dist/bundles/utils/timers.js +4 -0
- package/dist/bundles/utils/timers.js.map +12 -0
- package/dist/ecspresso.d.ts +402 -15
- package/dist/entity-manager.d.ts +118 -4
- package/dist/event-bus.d.ts +5 -0
- package/dist/hierarchy-manager.d.ts +122 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +15 -11
- package/dist/reactive-query-manager.d.ts +59 -0
- package/dist/resource-manager.d.ts +37 -5
- package/dist/screen-manager.d.ts +116 -0
- package/dist/screen-types.d.ts +119 -0
- package/dist/system-builder.d.ts +37 -2
- package/dist/types.d.ts +62 -5
- package/package.json +23 -3
package/dist/ecspresso.d.ts
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
import EntityManager from "./entity-manager";
|
|
2
2
|
import EventBus from "./event-bus";
|
|
3
|
-
import
|
|
3
|
+
import AssetManager from "./asset-manager";
|
|
4
|
+
import ScreenManager from "./screen-manager";
|
|
5
|
+
import { type ReactiveQueryDefinition } from "./reactive-query-manager";
|
|
6
|
+
import type { System, FilteredEntity, Entity, RemoveEntityOptions, HierarchyEntry, HierarchyIteratorOptions } from "./types";
|
|
4
7
|
import type Bundle from "./bundle";
|
|
5
8
|
import type { BundlesAreCompatible } from "./type-utils";
|
|
9
|
+
import type { AssetHandle, AssetConfigurator } from "./asset-types";
|
|
10
|
+
import type { ScreenDefinition, ScreenConfigurator } from "./screen-types";
|
|
6
11
|
/**
|
|
7
12
|
* Interface declaration for ECSpresso constructor to ensure type augmentation works properly.
|
|
8
13
|
* This merges with the class declaration below.
|
|
9
14
|
*/
|
|
10
|
-
export default interface ECSpresso<ComponentTypes extends Record<string, any> = {}, EventTypes extends Record<string, any> = {}, ResourceTypes extends Record<string, any> = {}> {
|
|
15
|
+
export default interface ECSpresso<ComponentTypes extends Record<string, any> = {}, EventTypes extends Record<string, any> = {}, ResourceTypes extends Record<string, any> = {}, AssetTypes extends Record<string, unknown> = {}, ScreenStates extends Record<string, ScreenDefinition<any, any>> = {}> {
|
|
11
16
|
/**
|
|
12
17
|
* Default constructor
|
|
13
18
|
*/
|
|
14
|
-
new (): ECSpresso<ComponentTypes, EventTypes, ResourceTypes>;
|
|
19
|
+
new (): ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>;
|
|
15
20
|
}
|
|
16
21
|
/**
|
|
17
22
|
* ECSpresso is the central ECS framework class that connects all features.
|
|
18
23
|
* It handles creation and management of entities, components, and systems, and provides lifecycle hooks.
|
|
19
24
|
*/
|
|
20
|
-
export default class ECSpresso<ComponentTypes extends Record<string, any> = {}, EventTypes extends Record<string, any> = {}, ResourceTypes extends Record<string, any> = {}> {
|
|
25
|
+
export default class ECSpresso<ComponentTypes extends Record<string, any> = {}, EventTypes extends Record<string, any> = {}, ResourceTypes extends Record<string, any> = {}, AssetTypes extends Record<string, unknown> = {}, ScreenStates extends Record<string, ScreenDefinition<any, any>> = {}> {
|
|
21
26
|
/** Library version*/
|
|
22
27
|
static readonly VERSION: string;
|
|
23
28
|
/** Access/modify stored components and entities*/
|
|
@@ -32,10 +37,25 @@ export default class ECSpresso<ComponentTypes extends Record<string, any> = {},
|
|
|
32
37
|
private _sortedSystems;
|
|
33
38
|
/** Track installed bundles to prevent duplicates*/
|
|
34
39
|
private _installedBundles;
|
|
40
|
+
/** Disabled system groups */
|
|
41
|
+
private _disabledGroups;
|
|
42
|
+
/** Asset manager for loading and accessing assets */
|
|
43
|
+
private _assetManager;
|
|
44
|
+
/** Screen manager for state/screen transitions */
|
|
45
|
+
private _screenManager;
|
|
46
|
+
/** Reactive query manager for enter/exit callbacks */
|
|
47
|
+
private _reactiveQueryManager;
|
|
48
|
+
/** Post-update hooks to be called after all systems in update() */
|
|
49
|
+
private _postUpdateHooks;
|
|
35
50
|
/**
|
|
36
51
|
* Creates a new ECSpresso instance.
|
|
37
52
|
*/
|
|
38
53
|
constructor();
|
|
54
|
+
/**
|
|
55
|
+
* Sets up component lifecycle hooks for reactive query tracking
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
private _setupReactiveQueryHooks;
|
|
39
59
|
/**
|
|
40
60
|
* Creates a new ECSpresso builder for type-safe bundle installation.
|
|
41
61
|
* This is the preferred way to create an ECSpresso instance with bundles.
|
|
@@ -50,7 +70,7 @@ export default class ECSpresso<ComponentTypes extends Record<string, any> = {},
|
|
|
50
70
|
* .build();
|
|
51
71
|
* ```
|
|
52
72
|
*/
|
|
53
|
-
static create<C extends Record<string, any> = {}, E extends Record<string, any> = {}, R extends Record<string, any> = {}>(): ECSpressoBuilder<C, E, R>;
|
|
73
|
+
static create<C extends Record<string, any> = {}, E extends Record<string, any> = {}, R extends Record<string, any> = {}, A extends Record<string, unknown> = {}, S extends Record<string, ScreenDefinition<any, any>> = {}>(): ECSpressoBuilder<C, E, R, A, S>;
|
|
54
74
|
/**
|
|
55
75
|
* Adds a system directly to this ECSpresso instance
|
|
56
76
|
* @param label Unique name to identify the system
|
|
@@ -66,7 +86,9 @@ export default class ECSpresso<ComponentTypes extends Record<string, any> = {},
|
|
|
66
86
|
* Initialize all resources and systems
|
|
67
87
|
* This method:
|
|
68
88
|
* 1. Initializes all resources that were added as factory functions
|
|
69
|
-
* 2.
|
|
89
|
+
* 2. Sets up asset manager and loads eager assets
|
|
90
|
+
* 3. Sets up screen manager
|
|
91
|
+
* 4. Calls the onInitialize lifecycle hook on all systems
|
|
70
92
|
*
|
|
71
93
|
* This is useful for game startup to ensure all resources are ready
|
|
72
94
|
* and systems are properly initialized before the game loop begins.
|
|
@@ -95,6 +117,28 @@ export default class ECSpresso<ComponentTypes extends Record<string, any> = {},
|
|
|
95
117
|
* @returns true if the system was found and updated, false otherwise
|
|
96
118
|
*/
|
|
97
119
|
updateSystemPriority(label: string, priority: number): boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Disable a system group. Systems in this group will be skipped during update().
|
|
122
|
+
* @param groupName The name of the group to disable
|
|
123
|
+
*/
|
|
124
|
+
disableSystemGroup(groupName: string): void;
|
|
125
|
+
/**
|
|
126
|
+
* Enable a system group. Systems in this group will run during update().
|
|
127
|
+
* @param groupName The name of the group to enable
|
|
128
|
+
*/
|
|
129
|
+
enableSystemGroup(groupName: string): void;
|
|
130
|
+
/**
|
|
131
|
+
* Check if a system group is enabled.
|
|
132
|
+
* @param groupName The name of the group to check
|
|
133
|
+
* @returns true if the group is enabled (or doesn't exist), false if disabled
|
|
134
|
+
*/
|
|
135
|
+
isSystemGroupEnabled(groupName: string): boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Get all system labels that belong to a specific group.
|
|
138
|
+
* @param groupName The name of the group
|
|
139
|
+
* @returns Array of system labels in the group
|
|
140
|
+
*/
|
|
141
|
+
getSystemsInGroup(groupName: string): string[];
|
|
98
142
|
/**
|
|
99
143
|
* Remove a system by its label
|
|
100
144
|
* Calls the system's onDetach method with this ECSpresso instance if defined
|
|
@@ -106,7 +150,7 @@ export default class ECSpresso<ComponentTypes extends Record<string, any> = {},
|
|
|
106
150
|
* Internal method to register a system with this ECSpresso instance
|
|
107
151
|
* @internal Used by SystemBuilder - replaces direct private property access
|
|
108
152
|
*/
|
|
109
|
-
_registerSystem(system: System<ComponentTypes, any, any, EventTypes, ResourceTypes>): void;
|
|
153
|
+
_registerSystem(system: System<ComponentTypes, any, any, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): void;
|
|
110
154
|
/**
|
|
111
155
|
* Check if a resource exists
|
|
112
156
|
*/
|
|
@@ -118,13 +162,29 @@ export default class ECSpresso<ComponentTypes extends Record<string, any> = {},
|
|
|
118
162
|
/**
|
|
119
163
|
* Add a resource to the ECS instance
|
|
120
164
|
*/
|
|
121
|
-
addResource<K extends keyof ResourceTypes>(key: K, resource: ResourceTypes[K] | ((ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]>)
|
|
165
|
+
addResource<K extends keyof ResourceTypes>(key: K, resource: ResourceTypes[K] | ((ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]>) | {
|
|
166
|
+
dependsOn?: readonly string[];
|
|
167
|
+
factory: (ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]>;
|
|
168
|
+
onDispose?: (resource: ResourceTypes[K], ecs?: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => void | Promise<void>;
|
|
169
|
+
}): this;
|
|
122
170
|
/**
|
|
123
|
-
* Remove a resource from the ECS instance
|
|
171
|
+
* Remove a resource from the ECS instance (without calling onDispose)
|
|
124
172
|
* @param key The resource key to remove
|
|
125
173
|
* @returns True if the resource was removed, false if it didn't exist
|
|
126
174
|
*/
|
|
127
175
|
removeResource<K extends keyof ResourceTypes>(key: K): boolean;
|
|
176
|
+
/**
|
|
177
|
+
* Dispose a single resource, calling its onDispose callback if defined
|
|
178
|
+
* @param key The resource key to dispose
|
|
179
|
+
* @returns True if the resource existed and was disposed, false if it didn't exist
|
|
180
|
+
*/
|
|
181
|
+
disposeResource<K extends keyof ResourceTypes>(key: K): Promise<boolean>;
|
|
182
|
+
/**
|
|
183
|
+
* Dispose all initialized resources in reverse dependency order.
|
|
184
|
+
* Resources that depend on others are disposed first.
|
|
185
|
+
* Calls each resource's onDispose callback if defined.
|
|
186
|
+
*/
|
|
187
|
+
disposeResources(): Promise<void>;
|
|
128
188
|
/**
|
|
129
189
|
* Update an existing resource using an updater function
|
|
130
190
|
* @param key The resource key to update
|
|
@@ -155,44 +215,371 @@ export default class ECSpresso<ComponentTypes extends Record<string, any> = {},
|
|
|
155
215
|
*/
|
|
156
216
|
spawn<T extends {
|
|
157
217
|
[K in keyof ComponentTypes]?: ComponentTypes[K];
|
|
158
|
-
}>(components: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>):
|
|
218
|
+
}>(components: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>): FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never>;
|
|
159
219
|
/**
|
|
160
220
|
* Get all entities with specific components
|
|
161
221
|
*/
|
|
162
222
|
getEntitiesWithQuery<WithComponents extends keyof ComponentTypes, WithoutComponents extends keyof ComponentTypes = never>(withComponents: ReadonlyArray<WithComponents>, withoutComponents?: ReadonlyArray<WithoutComponents>): Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>;
|
|
223
|
+
/**
|
|
224
|
+
* Remove an entity (and optionally its descendants)
|
|
225
|
+
* @param entityOrId Entity or entity ID to remove
|
|
226
|
+
* @param options Options for removal (cascade: true by default)
|
|
227
|
+
* @returns true if entity was removed
|
|
228
|
+
*/
|
|
229
|
+
removeEntity(entityOrId: number | Entity<ComponentTypes>, options?: RemoveEntityOptions): boolean;
|
|
230
|
+
/**
|
|
231
|
+
* Create an entity as a child of another entity with initial components
|
|
232
|
+
* @param parentId The parent entity ID
|
|
233
|
+
* @param components Initial components to add
|
|
234
|
+
* @returns The created child entity
|
|
235
|
+
*/
|
|
236
|
+
spawnChild<T extends {
|
|
237
|
+
[K in keyof ComponentTypes]?: ComponentTypes[K];
|
|
238
|
+
}>(parentId: number, components: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>): FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never>;
|
|
239
|
+
/**
|
|
240
|
+
* Set the parent of an entity
|
|
241
|
+
* @param childId The entity to set as a child
|
|
242
|
+
* @param parentId The entity to set as the parent
|
|
243
|
+
*/
|
|
244
|
+
setParent(childId: number, parentId: number): this;
|
|
245
|
+
/**
|
|
246
|
+
* Remove the parent relationship for an entity (orphan it)
|
|
247
|
+
* @param childId The entity to orphan
|
|
248
|
+
* @returns true if a parent was removed, false if entity had no parent
|
|
249
|
+
*/
|
|
250
|
+
removeParent(childId: number): boolean;
|
|
251
|
+
/**
|
|
252
|
+
* Get the parent of an entity
|
|
253
|
+
* @param entityId The entity to get the parent of
|
|
254
|
+
* @returns The parent entity ID, or null if no parent
|
|
255
|
+
*/
|
|
256
|
+
getParent(entityId: number): number | null;
|
|
257
|
+
/**
|
|
258
|
+
* Get all children of an entity in insertion order
|
|
259
|
+
* @param parentId The parent entity
|
|
260
|
+
* @returns Readonly array of child entity IDs
|
|
261
|
+
*/
|
|
262
|
+
getChildren(parentId: number): readonly number[];
|
|
263
|
+
/**
|
|
264
|
+
* Get a child at a specific index
|
|
265
|
+
* @param parentId The parent entity
|
|
266
|
+
* @param index The index of the child
|
|
267
|
+
* @returns The child entity ID, or null if index is out of bounds
|
|
268
|
+
*/
|
|
269
|
+
getChildAt(parentId: number, index: number): number | null;
|
|
270
|
+
/**
|
|
271
|
+
* Get the index of a child within its parent's children list
|
|
272
|
+
* @param parentId The parent entity
|
|
273
|
+
* @param childId The child entity to find
|
|
274
|
+
* @returns The index of the child, or -1 if not found
|
|
275
|
+
*/
|
|
276
|
+
getChildIndex(parentId: number, childId: number): number;
|
|
277
|
+
/**
|
|
278
|
+
* Get all ancestors of an entity in order [parent, grandparent, ...]
|
|
279
|
+
* @param entityId The entity to get ancestors of
|
|
280
|
+
* @returns Readonly array of ancestor entity IDs
|
|
281
|
+
*/
|
|
282
|
+
getAncestors(entityId: number): readonly number[];
|
|
283
|
+
/**
|
|
284
|
+
* Get all descendants of an entity in depth-first order
|
|
285
|
+
* @param entityId The entity to get descendants of
|
|
286
|
+
* @returns Readonly array of descendant entity IDs
|
|
287
|
+
*/
|
|
288
|
+
getDescendants(entityId: number): readonly number[];
|
|
289
|
+
/**
|
|
290
|
+
* Get the root ancestor of an entity (topmost parent), or self if no parent
|
|
291
|
+
* @param entityId The entity to get the root of
|
|
292
|
+
* @returns The root entity ID
|
|
293
|
+
*/
|
|
294
|
+
getRoot(entityId: number): number;
|
|
295
|
+
/**
|
|
296
|
+
* Get siblings of an entity (other children of the same parent)
|
|
297
|
+
* @param entityId The entity to get siblings of
|
|
298
|
+
* @returns Readonly array of sibling entity IDs
|
|
299
|
+
*/
|
|
300
|
+
getSiblings(entityId: number): readonly number[];
|
|
301
|
+
/**
|
|
302
|
+
* Check if an entity is a descendant of another entity
|
|
303
|
+
* @param entityId The potential descendant
|
|
304
|
+
* @param ancestorId The potential ancestor
|
|
305
|
+
* @returns true if entityId is a descendant of ancestorId
|
|
306
|
+
*/
|
|
307
|
+
isDescendantOf(entityId: number, ancestorId: number): boolean;
|
|
308
|
+
/**
|
|
309
|
+
* Check if an entity is an ancestor of another entity
|
|
310
|
+
* @param entityId The potential ancestor
|
|
311
|
+
* @param descendantId The potential descendant
|
|
312
|
+
* @returns true if entityId is an ancestor of descendantId
|
|
313
|
+
*/
|
|
314
|
+
isAncestorOf(entityId: number, descendantId: number): boolean;
|
|
315
|
+
/**
|
|
316
|
+
* Get all root entities (entities that have children but no parent)
|
|
317
|
+
* @returns Readonly array of root entity IDs
|
|
318
|
+
*/
|
|
319
|
+
getRootEntities(): readonly number[];
|
|
320
|
+
/**
|
|
321
|
+
* Traverse the hierarchy in parent-first (breadth-first) order.
|
|
322
|
+
* Parents are guaranteed to be visited before their children.
|
|
323
|
+
* @param callback Function called for each entity with (entityId, parentId, depth)
|
|
324
|
+
* @param options Optional traversal options (roots to filter to specific subtrees)
|
|
325
|
+
*/
|
|
326
|
+
forEachInHierarchy(callback: (entityId: number, parentId: number | null, depth: number) => void, options?: HierarchyIteratorOptions): void;
|
|
327
|
+
/**
|
|
328
|
+
* Generator-based hierarchy traversal in parent-first (breadth-first) order.
|
|
329
|
+
* Supports early termination via break.
|
|
330
|
+
* @param options Optional traversal options (roots to filter to specific subtrees)
|
|
331
|
+
* @yields HierarchyEntry for each entity in parent-first order
|
|
332
|
+
*/
|
|
333
|
+
hierarchyIterator(options?: HierarchyIteratorOptions): Generator<HierarchyEntry, void, unknown>;
|
|
334
|
+
/**
|
|
335
|
+
* Emit a hierarchy changed event
|
|
336
|
+
* @internal
|
|
337
|
+
*/
|
|
338
|
+
private _emitHierarchyChanged;
|
|
163
339
|
/**
|
|
164
340
|
* Get all installed bundle IDs
|
|
165
341
|
*/
|
|
166
342
|
get installedBundles(): string[];
|
|
167
343
|
get entityManager(): EntityManager<ComponentTypes>;
|
|
168
344
|
get eventBus(): EventBus<EventTypes>;
|
|
345
|
+
/**
|
|
346
|
+
* Register a callback when a specific component is added to any entity
|
|
347
|
+
* @param componentName The component key
|
|
348
|
+
* @param handler Function receiving the new component value and the entity
|
|
349
|
+
* @returns Unsubscribe function to remove the callback
|
|
350
|
+
*/
|
|
351
|
+
onComponentAdded<K extends keyof ComponentTypes>(componentName: K, handler: (value: ComponentTypes[K], entity: Entity<ComponentTypes>) => void): () => void;
|
|
352
|
+
/**
|
|
353
|
+
* Register a callback when a specific component is removed from any entity
|
|
354
|
+
* @param componentName The component key
|
|
355
|
+
* @param handler Function receiving the old component value and the entity
|
|
356
|
+
* @returns Unsubscribe function to remove the callback
|
|
357
|
+
*/
|
|
358
|
+
onComponentRemoved<K extends keyof ComponentTypes>(componentName: K, handler: (oldValue: ComponentTypes[K], entity: Entity<ComponentTypes>) => void): () => void;
|
|
359
|
+
/**
|
|
360
|
+
* Add a reactive query that triggers callbacks when entities enter/exit the query match.
|
|
361
|
+
* @param name Unique name for the query
|
|
362
|
+
* @param definition Query definition with with/without arrays and onEnter/onExit callbacks
|
|
363
|
+
*/
|
|
364
|
+
addReactiveQuery<WithComponents extends keyof ComponentTypes, WithoutComponents extends keyof ComponentTypes = never>(name: string, definition: ReactiveQueryDefinition<ComponentTypes, WithComponents, WithoutComponents>): void;
|
|
365
|
+
/**
|
|
366
|
+
* Remove a reactive query by name.
|
|
367
|
+
* @param name Name of the query to remove
|
|
368
|
+
* @returns true if the query existed and was removed, false otherwise
|
|
369
|
+
*/
|
|
370
|
+
removeReactiveQuery(name: string): boolean;
|
|
371
|
+
/**
|
|
372
|
+
* Subscribe to an event (convenience wrapper for eventBus.subscribe)
|
|
373
|
+
* @param eventType The event type to subscribe to
|
|
374
|
+
* @param callback The callback to invoke when the event is published
|
|
375
|
+
* @returns An unsubscribe function
|
|
376
|
+
*/
|
|
377
|
+
on<E extends keyof EventTypes>(eventType: E, callback: (data: EventTypes[E]) => void): () => void;
|
|
378
|
+
/**
|
|
379
|
+
* Unsubscribe from an event by callback reference (convenience wrapper for eventBus.unsubscribe)
|
|
380
|
+
* @param eventType The event type to unsubscribe from
|
|
381
|
+
* @param callback The callback to remove
|
|
382
|
+
* @returns true if the callback was found and removed, false otherwise
|
|
383
|
+
*/
|
|
384
|
+
off<E extends keyof EventTypes>(eventType: E, callback: (data: EventTypes[E]) => void): boolean;
|
|
385
|
+
/**
|
|
386
|
+
* Register a hook that runs after all systems in update()
|
|
387
|
+
* @param callback The hook to call after all systems have processed
|
|
388
|
+
* @returns An unsubscribe function to remove the hook
|
|
389
|
+
*/
|
|
390
|
+
onPostUpdate(callback: (ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>, deltaTime: number) => void): () => void;
|
|
391
|
+
/**
|
|
392
|
+
* Get a loaded asset by key. Throws if not loaded.
|
|
393
|
+
*/
|
|
394
|
+
getAsset<K extends keyof AssetTypes>(key: K): AssetTypes[K];
|
|
395
|
+
/**
|
|
396
|
+
* Get a loaded asset or undefined if not loaded
|
|
397
|
+
*/
|
|
398
|
+
getAssetOrUndefined<K extends keyof AssetTypes>(key: K): AssetTypes[K] | undefined;
|
|
399
|
+
/**
|
|
400
|
+
* Get a handle to an asset with status information
|
|
401
|
+
*/
|
|
402
|
+
getAssetHandle<K extends keyof AssetTypes>(key: K): AssetHandle<AssetTypes[K]>;
|
|
403
|
+
/**
|
|
404
|
+
* Check if an asset is loaded
|
|
405
|
+
*/
|
|
406
|
+
isAssetLoaded<K extends keyof AssetTypes>(key: K): boolean;
|
|
407
|
+
/**
|
|
408
|
+
* Load a single asset
|
|
409
|
+
*/
|
|
410
|
+
loadAsset<K extends keyof AssetTypes>(key: K): Promise<AssetTypes[K]>;
|
|
411
|
+
/**
|
|
412
|
+
* Load all assets in a group
|
|
413
|
+
*/
|
|
414
|
+
loadAssetGroup(groupName: string): Promise<void>;
|
|
415
|
+
/**
|
|
416
|
+
* Check if all assets in a group are loaded
|
|
417
|
+
*/
|
|
418
|
+
isAssetGroupLoaded(groupName: string): boolean;
|
|
419
|
+
/**
|
|
420
|
+
* Get the loading progress of a group (0-1)
|
|
421
|
+
*/
|
|
422
|
+
getAssetGroupProgress(groupName: string): number;
|
|
423
|
+
/**
|
|
424
|
+
* Transition to a new screen, clearing the stack
|
|
425
|
+
*/
|
|
426
|
+
setScreen<K extends keyof ScreenStates>(name: K, config: ScreenStates[K] extends ScreenDefinition<infer C, any> ? C : never): Promise<void>;
|
|
427
|
+
/**
|
|
428
|
+
* Push a screen onto the stack (overlay)
|
|
429
|
+
*/
|
|
430
|
+
pushScreen<K extends keyof ScreenStates>(name: K, config: ScreenStates[K] extends ScreenDefinition<infer C, any> ? C : never): Promise<void>;
|
|
431
|
+
/**
|
|
432
|
+
* Pop the current screen and return to the previous one
|
|
433
|
+
*/
|
|
434
|
+
popScreen(): Promise<void>;
|
|
435
|
+
/**
|
|
436
|
+
* Get the current screen name
|
|
437
|
+
*/
|
|
438
|
+
getCurrentScreen(): keyof ScreenStates | null;
|
|
439
|
+
/**
|
|
440
|
+
* Get the current screen config (immutable)
|
|
441
|
+
*/
|
|
442
|
+
getScreenConfig<K extends keyof ScreenStates>(): ScreenStates[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never;
|
|
443
|
+
/**
|
|
444
|
+
* Get the current screen config or null
|
|
445
|
+
*/
|
|
446
|
+
getScreenConfigOrNull<K extends keyof ScreenStates>(): (ScreenStates[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never) | null;
|
|
447
|
+
/**
|
|
448
|
+
* Get the current screen state (mutable)
|
|
449
|
+
*/
|
|
450
|
+
getScreenState<K extends keyof ScreenStates>(): ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never;
|
|
451
|
+
/**
|
|
452
|
+
* Get the current screen state or null
|
|
453
|
+
*/
|
|
454
|
+
getScreenStateOrNull<K extends keyof ScreenStates>(): (ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never) | null;
|
|
455
|
+
/**
|
|
456
|
+
* Update the current screen state
|
|
457
|
+
*/
|
|
458
|
+
updateScreenState<K extends keyof ScreenStates>(update: Partial<ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never> | ((current: ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never) => Partial<ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never>)): void;
|
|
459
|
+
/**
|
|
460
|
+
* Check if a screen is the current screen
|
|
461
|
+
*/
|
|
462
|
+
isCurrentScreen(screenName: keyof ScreenStates): boolean;
|
|
463
|
+
/**
|
|
464
|
+
* Check if a screen is active (current or in stack)
|
|
465
|
+
*/
|
|
466
|
+
isScreenActive(screenName: keyof ScreenStates): boolean;
|
|
467
|
+
/**
|
|
468
|
+
* Get the screen stack depth
|
|
469
|
+
*/
|
|
470
|
+
getScreenStackDepth(): number;
|
|
471
|
+
/**
|
|
472
|
+
* Internal method to set the asset manager
|
|
473
|
+
* @internal Used by ECSpressoBuilder
|
|
474
|
+
*/
|
|
475
|
+
_setAssetManager(manager: AssetManager<AssetTypes>): void;
|
|
476
|
+
/**
|
|
477
|
+
* Internal method to set the screen manager
|
|
478
|
+
* @internal Used by ECSpressoBuilder
|
|
479
|
+
*/
|
|
480
|
+
_setScreenManager(manager: ScreenManager<ScreenStates>): void;
|
|
169
481
|
/**
|
|
170
482
|
* Internal method to install a bundle into this ECSpresso instance.
|
|
171
483
|
* Called by the ECSpressoBuilder during the build process.
|
|
172
484
|
* The type safety is guaranteed by the builder's type system.
|
|
173
485
|
*/
|
|
174
|
-
_installBundle<C extends Record<string, any>, E extends Record<string, any>, R extends Record<string, any>>(bundle: Bundle<C, E, R>): this;
|
|
486
|
+
_installBundle<C extends Record<string, any>, E extends Record<string, any>, R extends Record<string, any>, A extends Record<string, unknown> = {}, S extends Record<string, ScreenDefinition<any, any>> = {}>(bundle: Bundle<C, E, R, A, S>): this;
|
|
175
487
|
}
|
|
488
|
+
/**
|
|
489
|
+
* Resource factory with optional dependencies and disposal callback
|
|
490
|
+
*/
|
|
491
|
+
type ResourceFactoryWithDeps<T> = {
|
|
492
|
+
dependsOn?: readonly string[];
|
|
493
|
+
factory: (context?: any) => T | Promise<T>;
|
|
494
|
+
onDispose?: (resource: T, context?: any) => void | Promise<void>;
|
|
495
|
+
};
|
|
176
496
|
/**
|
|
177
497
|
* Builder class for ECSpresso that provides fluent type-safe bundle installation.
|
|
178
498
|
* Handles type checking during build process to ensure type safety.
|
|
179
499
|
*/
|
|
180
|
-
export declare class ECSpressoBuilder<C extends Record<string, any> = {}, E extends Record<string, any> = {}, R extends Record<string, any> = {}> {
|
|
500
|
+
export declare class ECSpressoBuilder<C extends Record<string, any> = {}, E extends Record<string, any> = {}, R extends Record<string, any> = {}, A extends Record<string, unknown> = {}, S extends Record<string, ScreenDefinition<any, any>> = {}> {
|
|
181
501
|
/** The ECSpresso instance being built*/
|
|
182
502
|
private ecspresso;
|
|
503
|
+
/** Asset configurator for collecting asset definitions */
|
|
504
|
+
private assetConfigurator;
|
|
505
|
+
/** Screen configurator for collecting screen definitions */
|
|
506
|
+
private screenConfigurator;
|
|
507
|
+
/** Pending resources to add during build */
|
|
508
|
+
private pendingResources;
|
|
183
509
|
constructor();
|
|
184
510
|
/**
|
|
185
511
|
* Add the first bundle when starting with empty types.
|
|
186
512
|
* This overload allows any bundle to be added to an empty ECSpresso instance.
|
|
187
513
|
*/
|
|
188
|
-
withBundle<BC extends Record<string, any>, BE extends Record<string, any>, BR extends Record<string, any>>(this: ECSpressoBuilder<{}, {}, {}>, bundle: Bundle<BC, BE, BR>): ECSpressoBuilder<BC, BE, BR>;
|
|
514
|
+
withBundle<BC extends Record<string, any>, BE extends Record<string, any>, BR extends Record<string, any>>(this: ECSpressoBuilder<{}, {}, {}, A, S>, bundle: Bundle<BC, BE, BR>): ECSpressoBuilder<BC, BE, BR, A, S>;
|
|
189
515
|
/**
|
|
190
516
|
* Add a subsequent bundle with type checking.
|
|
191
517
|
* This overload enforces bundle type compatibility.
|
|
192
518
|
*/
|
|
193
|
-
withBundle<BC extends Record<string, any>, BE extends Record<string, any>, BR extends Record<string, any>>(bundle: BundlesAreCompatible<C, BC, E, BE, R, BR> extends true ? Bundle<BC, BE, BR> : never): ECSpressoBuilder<C & BC, E & BE, R & BR>;
|
|
519
|
+
withBundle<BC extends Record<string, any>, BE extends Record<string, any>, BR extends Record<string, any>>(bundle: BundlesAreCompatible<C, BC, E, BE, R, BR> extends true ? Bundle<BC, BE, BR> : never): ECSpressoBuilder<C & BC, E & BE, R & BR, A, S>;
|
|
520
|
+
/**
|
|
521
|
+
* Add a resource during ECSpresso construction
|
|
522
|
+
* @param key The resource key
|
|
523
|
+
* @param resource The resource value, factory function, or factory with dependencies/disposal
|
|
524
|
+
* @returns This builder with updated resource types
|
|
525
|
+
*
|
|
526
|
+
* @example
|
|
527
|
+
* ```typescript
|
|
528
|
+
* ECSpresso.create<Components, Events, Resources>()
|
|
529
|
+
* .withResource('config', { debug: true })
|
|
530
|
+
* .withResource('counter', () => 42)
|
|
531
|
+
* .withResource('derived', {
|
|
532
|
+
* dependsOn: ['base'],
|
|
533
|
+
* factory: (ecs) => ecs.getResource('base') * 2,
|
|
534
|
+
* onDispose: (value) => console.log('Disposed:', value)
|
|
535
|
+
* })
|
|
536
|
+
* .build();
|
|
537
|
+
* ```
|
|
538
|
+
*/
|
|
539
|
+
withResource<K extends string, V>(key: K, resource: V | ((context?: any) => V | Promise<V>) | ResourceFactoryWithDeps<V>): ECSpressoBuilder<C, E, R & Record<K, V>, A, S>;
|
|
540
|
+
/**
|
|
541
|
+
* Configure assets for this ECSpresso instance
|
|
542
|
+
* @param configurator Function that receives an AssetConfigurator and returns it after adding assets
|
|
543
|
+
* @returns This builder with updated asset types
|
|
544
|
+
*
|
|
545
|
+
* @example
|
|
546
|
+
* ```typescript
|
|
547
|
+
* ECSpresso.create<Components, Events, Resources>()
|
|
548
|
+
* .withAssets(assets => assets
|
|
549
|
+
* .add('playerSprite', () => loadTexture('player.png'))
|
|
550
|
+
* .addGroup('level1', {
|
|
551
|
+
* background: () => loadTexture('level1-bg.png'),
|
|
552
|
+
* music: () => loadAudio('level1.mp3'),
|
|
553
|
+
* })
|
|
554
|
+
* )
|
|
555
|
+
* .build();
|
|
556
|
+
* ```
|
|
557
|
+
*/
|
|
558
|
+
withAssets<NewA extends Record<string, unknown>>(configurator: (assets: AssetConfigurator<{}>) => AssetConfigurator<NewA>): ECSpressoBuilder<C, E, R, A & NewA, S>;
|
|
559
|
+
/**
|
|
560
|
+
* Configure screens for this ECSpresso instance
|
|
561
|
+
* @param configurator Function that receives a ScreenConfigurator and returns it after adding screens
|
|
562
|
+
* @returns This builder with updated screen types
|
|
563
|
+
*
|
|
564
|
+
* @example
|
|
565
|
+
* ```typescript
|
|
566
|
+
* ECSpresso.create<Components, Events, Resources>()
|
|
567
|
+
* .withScreens(screens => screens
|
|
568
|
+
* .add('loading', {
|
|
569
|
+
* initialState: () => ({ progress: 0 }),
|
|
570
|
+
* })
|
|
571
|
+
* .add('gameplay', {
|
|
572
|
+
* initialState: ({ level }) => ({ score: 0, level }),
|
|
573
|
+
* requiredAssetGroups: ['level1'],
|
|
574
|
+
* })
|
|
575
|
+
* )
|
|
576
|
+
* .build();
|
|
577
|
+
* ```
|
|
578
|
+
*/
|
|
579
|
+
withScreens<NewS extends Record<string, ScreenDefinition<any, any>>>(configurator: (screens: ScreenConfigurator<{}>) => ScreenConfigurator<NewS>): ECSpressoBuilder<C, E, R, A, S & NewS>;
|
|
194
580
|
/**
|
|
195
581
|
* Complete the build process and return the built ECSpresso instance
|
|
196
582
|
*/
|
|
197
|
-
build(): ECSpresso<C, E, R>;
|
|
583
|
+
build(): ECSpresso<C, E, R, A, S>;
|
|
198
584
|
}
|
|
585
|
+
export {};
|
package/dist/entity-manager.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Entity, FilteredEntity } from "./types";
|
|
1
|
+
import type { Entity, FilteredEntity, RemoveEntityOptions, HierarchyEntry, HierarchyIteratorOptions } from "./types";
|
|
2
2
|
export default class EntityManager<ComponentTypes> {
|
|
3
3
|
private nextId;
|
|
4
4
|
private entities;
|
|
@@ -11,6 +11,10 @@ export default class EntityManager<ComponentTypes> {
|
|
|
11
11
|
* Callbacks registered for component removals
|
|
12
12
|
*/
|
|
13
13
|
private removedCallbacks;
|
|
14
|
+
/**
|
|
15
|
+
* Hierarchy manager for parent-child relationships
|
|
16
|
+
*/
|
|
17
|
+
private hierarchyManager;
|
|
14
18
|
createEntity(): Entity<ComponentTypes>;
|
|
15
19
|
addComponent<ComponentName extends keyof ComponentTypes>(entityOrId: number | Entity<ComponentTypes>, componentName: ComponentName, data: ComponentTypes[ComponentName]): this;
|
|
16
20
|
/**
|
|
@@ -24,18 +28,128 @@ export default class EntityManager<ComponentTypes> {
|
|
|
24
28
|
removeComponent<ComponentName extends keyof ComponentTypes>(entityOrId: number | Entity<ComponentTypes>, componentName: ComponentName): this;
|
|
25
29
|
getComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): ComponentTypes[ComponentName] | null;
|
|
26
30
|
getEntitiesWithQuery<WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never>(required?: ReadonlyArray<WithComponents>, excluded?: ReadonlyArray<WithoutComponents>): Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>>;
|
|
27
|
-
removeEntity(entityOrId: number | Entity<ComponentTypes
|
|
31
|
+
removeEntity(entityOrId: number | Entity<ComponentTypes>, options?: RemoveEntityOptions): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Internal method to remove a single entity without cascade logic
|
|
34
|
+
*/
|
|
35
|
+
private removeEntityInternal;
|
|
28
36
|
getEntity(entityId: number): Entity<ComponentTypes> | undefined;
|
|
29
37
|
/**
|
|
30
38
|
* Register a callback when a specific component is added to any entity
|
|
31
39
|
* @param componentName The component key
|
|
32
40
|
* @param handler Function receiving the new component value and the entity
|
|
41
|
+
* @returns Unsubscribe function to remove the callback
|
|
33
42
|
*/
|
|
34
|
-
onComponentAdded<ComponentName extends keyof ComponentTypes>(componentName: ComponentName, handler: (value: ComponentTypes[ComponentName], entity: Entity<ComponentTypes>) => void):
|
|
43
|
+
onComponentAdded<ComponentName extends keyof ComponentTypes>(componentName: ComponentName, handler: (value: ComponentTypes[ComponentName], entity: Entity<ComponentTypes>) => void): () => void;
|
|
35
44
|
/**
|
|
36
45
|
* Register a callback when a specific component is removed from any entity
|
|
37
46
|
* @param componentName The component key
|
|
38
47
|
* @param handler Function receiving the old component value and the entity
|
|
48
|
+
* @returns Unsubscribe function to remove the callback
|
|
49
|
+
*/
|
|
50
|
+
onComponentRemoved<ComponentName extends keyof ComponentTypes>(componentName: ComponentName, handler: (oldValue: ComponentTypes[ComponentName], entity: Entity<ComponentTypes>) => void): () => void;
|
|
51
|
+
/**
|
|
52
|
+
* Create an entity as a child of another entity with initial components
|
|
53
|
+
* @param parentId The parent entity ID
|
|
54
|
+
* @param components Initial components to add
|
|
55
|
+
* @returns The created child entity
|
|
56
|
+
*/
|
|
57
|
+
spawnChild<T extends {
|
|
58
|
+
[K in keyof ComponentTypes]?: ComponentTypes[K];
|
|
59
|
+
}>(parentId: number, components: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>): FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never>;
|
|
60
|
+
/**
|
|
61
|
+
* Set the parent of an entity
|
|
62
|
+
* @param childId The entity to set as a child
|
|
63
|
+
* @param parentId The entity to set as the parent
|
|
64
|
+
*/
|
|
65
|
+
setParent(childId: number, parentId: number): this;
|
|
66
|
+
/**
|
|
67
|
+
* Remove the parent relationship for an entity (orphan it)
|
|
68
|
+
* @param childId The entity to orphan
|
|
69
|
+
* @returns true if a parent was removed, false if entity had no parent
|
|
70
|
+
*/
|
|
71
|
+
removeParent(childId: number): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Get the parent of an entity
|
|
74
|
+
* @param entityId The entity to get the parent of
|
|
75
|
+
* @returns The parent entity ID, or null if no parent
|
|
76
|
+
*/
|
|
77
|
+
getParent(entityId: number): number | null;
|
|
78
|
+
/**
|
|
79
|
+
* Get all children of an entity in insertion order
|
|
80
|
+
* @param parentId The parent entity
|
|
81
|
+
* @returns Readonly array of child entity IDs
|
|
82
|
+
*/
|
|
83
|
+
getChildren(parentId: number): readonly number[];
|
|
84
|
+
/**
|
|
85
|
+
* Get a child at a specific index
|
|
86
|
+
* @param parentId The parent entity
|
|
87
|
+
* @param index The index of the child
|
|
88
|
+
* @returns The child entity ID, or null if index is out of bounds
|
|
89
|
+
*/
|
|
90
|
+
getChildAt(parentId: number, index: number): number | null;
|
|
91
|
+
/**
|
|
92
|
+
* Get the index of a child within its parent's children list
|
|
93
|
+
* @param parentId The parent entity
|
|
94
|
+
* @param childId The child entity to find
|
|
95
|
+
* @returns The index of the child, or -1 if not found
|
|
96
|
+
*/
|
|
97
|
+
getChildIndex(parentId: number, childId: number): number;
|
|
98
|
+
/**
|
|
99
|
+
* Get all ancestors of an entity in order [parent, grandparent, ...]
|
|
100
|
+
* @param entityId The entity to get ancestors of
|
|
101
|
+
* @returns Readonly array of ancestor entity IDs
|
|
102
|
+
*/
|
|
103
|
+
getAncestors(entityId: number): readonly number[];
|
|
104
|
+
/**
|
|
105
|
+
* Get all descendants of an entity in depth-first order
|
|
106
|
+
* @param entityId The entity to get descendants of
|
|
107
|
+
* @returns Readonly array of descendant entity IDs
|
|
108
|
+
*/
|
|
109
|
+
getDescendants(entityId: number): readonly number[];
|
|
110
|
+
/**
|
|
111
|
+
* Get the root ancestor of an entity (topmost parent), or self if no parent
|
|
112
|
+
* @param entityId The entity to get the root of
|
|
113
|
+
* @returns The root entity ID
|
|
114
|
+
*/
|
|
115
|
+
getRoot(entityId: number): number;
|
|
116
|
+
/**
|
|
117
|
+
* Get siblings of an entity (other children of the same parent)
|
|
118
|
+
* @param entityId The entity to get siblings of
|
|
119
|
+
* @returns Readonly array of sibling entity IDs
|
|
120
|
+
*/
|
|
121
|
+
getSiblings(entityId: number): readonly number[];
|
|
122
|
+
/**
|
|
123
|
+
* Check if an entity is a descendant of another entity
|
|
124
|
+
* @param entityId The potential descendant
|
|
125
|
+
* @param ancestorId The potential ancestor
|
|
126
|
+
* @returns true if entityId is a descendant of ancestorId
|
|
127
|
+
*/
|
|
128
|
+
isDescendantOf(entityId: number, ancestorId: number): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Check if an entity is an ancestor of another entity
|
|
131
|
+
* @param entityId The potential ancestor
|
|
132
|
+
* @param descendantId The potential descendant
|
|
133
|
+
* @returns true if entityId is an ancestor of descendantId
|
|
134
|
+
*/
|
|
135
|
+
isAncestorOf(entityId: number, descendantId: number): boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Get all root entities (entities that have children but no parent)
|
|
138
|
+
* @returns Readonly array of root entity IDs
|
|
139
|
+
*/
|
|
140
|
+
getRootEntities(): readonly number[];
|
|
141
|
+
/**
|
|
142
|
+
* Traverse the hierarchy in parent-first (breadth-first) order.
|
|
143
|
+
* Parents are guaranteed to be visited before their children.
|
|
144
|
+
* @param callback Function called for each entity with (entityId, parentId, depth)
|
|
145
|
+
* @param options Optional traversal options (roots to filter to specific subtrees)
|
|
146
|
+
*/
|
|
147
|
+
forEachInHierarchy(callback: (entityId: number, parentId: number | null, depth: number) => void, options?: HierarchyIteratorOptions): void;
|
|
148
|
+
/**
|
|
149
|
+
* Generator-based hierarchy traversal in parent-first (breadth-first) order.
|
|
150
|
+
* Supports early termination via break.
|
|
151
|
+
* @param options Optional traversal options (roots to filter to specific subtrees)
|
|
152
|
+
* @yields HierarchyEntry for each entity in parent-first order
|
|
39
153
|
*/
|
|
40
|
-
|
|
154
|
+
hierarchyIterator(options?: HierarchyIteratorOptions): Generator<HierarchyEntry, void, unknown>;
|
|
41
155
|
}
|