ecspresso 0.5.0 → 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.
@@ -0,0 +1,59 @@
1
+ import type { Entity, FilteredEntity } from "./types";
2
+ import type EntityManager from "./entity-manager";
3
+ /**
4
+ * Definition for a reactive query with enter/exit callbacks
5
+ */
6
+ export interface ReactiveQueryDefinition<ComponentTypes extends Record<string, any>, WithComponents extends keyof ComponentTypes = keyof ComponentTypes, WithoutComponents extends keyof ComponentTypes = never> {
7
+ /** Components the entity must have */
8
+ with: ReadonlyArray<WithComponents>;
9
+ /** Components the entity must not have */
10
+ without?: ReadonlyArray<WithoutComponents>;
11
+ /** Called when an entity starts matching the query */
12
+ onEnter?: (entity: FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>) => void;
13
+ /** Called when an entity stops matching the query (receives just the ID since entity may be gone) */
14
+ onExit?: (entityId: number) => void;
15
+ }
16
+ /**
17
+ * Manages reactive queries that trigger callbacks when entities enter/exit query matches
18
+ */
19
+ export default class ReactiveQueryManager<ComponentTypes extends Record<string, any>> {
20
+ private queries;
21
+ private entityManager;
22
+ constructor(entityManager: EntityManager<ComponentTypes>);
23
+ /**
24
+ * Add a reactive query
25
+ * @param name Unique name for the query
26
+ * @param definition Query definition with callbacks
27
+ */
28
+ addQuery<WithComponents extends keyof ComponentTypes, WithoutComponents extends keyof ComponentTypes = never>(name: string, definition: ReactiveQueryDefinition<ComponentTypes, WithComponents, WithoutComponents>): void;
29
+ /**
30
+ * Remove a reactive query
31
+ * @param name Name of the query to remove
32
+ * @returns true if the query existed and was removed
33
+ */
34
+ removeQuery(name: string): boolean;
35
+ /**
36
+ * Check if an entity matches a query definition
37
+ */
38
+ private entityMatchesQuery;
39
+ /**
40
+ * Called when a component is added to an entity
41
+ * Checks all queries for potential enter/exit events
42
+ */
43
+ onComponentAdded(entity: Entity<ComponentTypes>, _componentName: keyof ComponentTypes): void;
44
+ /**
45
+ * Called when a component is removed from an entity
46
+ * Checks all queries for potential enter/exit events
47
+ */
48
+ onComponentRemoved(entity: Entity<ComponentTypes>, _componentName: keyof ComponentTypes): void;
49
+ /**
50
+ * Called when an entity is removed
51
+ * Triggers onExit for all queries the entity was matching
52
+ */
53
+ onEntityRemoved(entityId: number): void;
54
+ /**
55
+ * Recheck an entity against all queries (used after batch component additions)
56
+ * Fires enter/exit callbacks as appropriate based on current state vs tracked state
57
+ */
58
+ recheckEntity(entity: Entity<ComponentTypes>): void;
59
+ }
@@ -1,14 +1,24 @@
1
+ /**
2
+ * Resource factory with declared dependencies and optional disposal callback
3
+ */
4
+ interface ResourceFactoryWithDeps<T> {
5
+ dependsOn?: readonly string[];
6
+ factory: (context?: any) => T | Promise<T>;
7
+ onDispose?: (resource: T, context?: any) => void | Promise<void>;
8
+ }
1
9
  export default class ResourceManager<ResourceTypes extends Record<string, any> = Record<string, any>> {
2
10
  private resources;
3
11
  private resourceFactories;
12
+ private resourceDependencies;
13
+ private resourceDisposers;
4
14
  private initializedResourceKeys;
5
15
  /**
6
16
  * Add a resource to the manager
7
17
  * @param label The resource key
8
- * @param resource The resource value or a factory function that returns the resource
18
+ * @param resource The resource value, a factory function, or a factory with dependencies
9
19
  * @returns The resource manager instance for chaining
10
20
  */
11
- add<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K] | ((context?: any) => ResourceTypes[K] | Promise<ResourceTypes[K]>)): this;
21
+ add<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K] | ((context?: any) => ResourceTypes[K] | Promise<ResourceTypes[K]>) | ResourceFactoryWithDeps<ResourceTypes[K]>): this;
12
22
  /**
13
23
  * Improved detection of factory functions vs direct values/classes
14
24
  * @private
@@ -29,7 +39,7 @@ export default class ResourceManager<ResourceTypes extends Record<string, any> =
29
39
  */
30
40
  has<K extends keyof ResourceTypes>(label: K): boolean;
31
41
  /**
32
- * Remove a resource
42
+ * Remove a resource (without calling onDispose)
33
43
  * @param label The resource key
34
44
  * @returns True if the resource was removed
35
45
  */
@@ -58,9 +68,31 @@ export default class ResourceManager<ResourceTypes extends Record<string, any> =
58
68
  */
59
69
  initializeResource<K extends keyof ResourceTypes>(label: K, context?: any): Promise<void>;
60
70
  /**
61
- * Initialize specific resources or all resources that haven't been initialized yet
62
- * @param keys Optional array of resource keys to initialize or optional context to pass to factory functions
71
+ * Initialize specific resources or all resources that haven't been initialized yet.
72
+ * Resources are initialized in topological order based on their dependencies.
73
+ * @param context Optional context to pass to factory functions (usually the ECSpresso instance)
74
+ * @param keys Optional array of resource keys to initialize
63
75
  * @returns Promise that resolves when the specified resources are initialized
64
76
  */
65
77
  initializeResources<K extends keyof ResourceTypes>(context?: any, ...keys: K[]): Promise<void>;
78
+ /**
79
+ * Get the dependencies of a resource
80
+ * @param label The resource key
81
+ * @returns Array of resource keys that this resource depends on
82
+ */
83
+ getDependencies<K extends keyof ResourceTypes>(label: K): readonly string[];
84
+ /**
85
+ * Dispose a single resource, calling its onDispose callback if it exists
86
+ * @param label The resource key to dispose
87
+ * @param context Optional context to pass to the onDispose callback
88
+ * @returns True if the resource existed and was disposed, false if it didn't exist
89
+ */
90
+ disposeResource<K extends keyof ResourceTypes>(label: K, context?: any): Promise<boolean>;
91
+ /**
92
+ * Dispose all initialized resources in reverse dependency order.
93
+ * Resources that depend on others are disposed first.
94
+ * @param context Optional context to pass to onDispose callbacks
95
+ */
96
+ disposeResources(context?: any): Promise<void>;
66
97
  }
98
+ export {};
@@ -15,6 +15,7 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
15
15
  private eventHandlers?;
16
16
  private _priority;
17
17
  private _isRegistered;
18
+ private _groups;
18
19
  private _inScreens?;
19
20
  private _excludeScreens?;
20
21
  private _requiredAssets?;
@@ -51,6 +52,13 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
51
52
  * @returns This SystemBuilder instance for method chaining
52
53
  */
53
54
  setPriority(priority: number): this;
55
+ /**
56
+ * Add this system to a group. Systems can belong to multiple groups.
57
+ * When any group a system belongs to is disabled, the system will be skipped.
58
+ * @param groupName The name of the group to add the system to
59
+ * @returns This SystemBuilder instance for method chaining
60
+ */
61
+ inGroup(groupName: string): this;
54
62
  /**
55
63
  * Restrict this system to only run in specified screens.
56
64
  * System will be skipped during update() when the current screen
package/dist/types.d.ts CHANGED
@@ -23,6 +23,24 @@ export interface HierarchyChangedEvent {
23
23
  /** The new parent, or null if entity was orphaned */
24
24
  newParent: number | null;
25
25
  }
26
+ /**
27
+ * Options for hierarchy traversal methods
28
+ */
29
+ export interface HierarchyIteratorOptions {
30
+ /** Specific root entities to start traversal from. If not provided, all root entities are used. */
31
+ roots?: readonly number[];
32
+ }
33
+ /**
34
+ * Entry yielded during hierarchy traversal
35
+ */
36
+ export interface HierarchyEntry {
37
+ /** The entity being visited */
38
+ entityId: number;
39
+ /** The parent entity ID, or null for root entities */
40
+ parentId: number | null;
41
+ /** Depth in the hierarchy (0 for roots) */
42
+ depth: number;
43
+ }
26
44
  export interface EventHandler<T> {
27
45
  callback: (data: T) => void;
28
46
  once: boolean;
@@ -107,6 +125,10 @@ export interface System<ComponentTypes extends Record<string, any> = {}, WithCom
107
125
  * When systems have the same priority, they execute in registration order
108
126
  */
109
127
  priority?: number;
128
+ /**
129
+ * Groups this system belongs to. If any group is disabled, the system will be skipped.
130
+ */
131
+ groups?: string[];
110
132
  /**
111
133
  * Screens where this system should run. If specified, system only runs
112
134
  * when current screen is in this list.
package/package.json CHANGED
@@ -1,11 +1,25 @@
1
1
  {
2
2
  "name": "ecspresso",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "description": "A minimal Entity-Component-System library for typescript and javascript.",
8
8
  "sideEffects": false,
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./bundles/renderers/pixi": {
15
+ "import": "./dist/bundles/renderers/pixi.js",
16
+ "types": "./dist/bundles/renderers/pixi.d.ts"
17
+ },
18
+ "./bundles/utils/timers": {
19
+ "import": "./dist/bundles/utils/timers.js",
20
+ "types": "./dist/bundles/utils/timers.d.ts"
21
+ }
22
+ },
9
23
  "publishConfig": {
10
24
  "registry": "https://npm.pkg.github.com/"
11
25
  },
@@ -30,7 +44,13 @@
30
44
  "three": "^0.180.0"
31
45
  },
32
46
  "peerDependencies": {
33
- "typescript": "^5.9.2"
47
+ "typescript": "^5.9.2",
48
+ "pixi.js": "^8.0.0"
49
+ },
50
+ "peerDependenciesMeta": {
51
+ "pixi.js": {
52
+ "optional": true
53
+ }
34
54
  },
35
55
  "files": [
36
56
  "dist"
@@ -38,7 +58,7 @@
38
58
  "scripts": {
39
59
  "build:clean": "rm -rf dist",
40
60
  "build:ts": "bun tsc -p tsconfig.build.json",
41
- "build:js": "bun build --target=browser --sourcemap=linked --minify --outdir=dist src/index.ts",
61
+ "build:js": "bun build --target=browser --sourcemap=linked --minify --external=pixi.js --outdir=dist src/index.ts src/bundles/renderers/pixi.ts src/bundles/utils/timers.ts",
42
62
  "build": "bun build:clean && bun build:ts && bun build:js",
43
63
  "check:types": "bun tsc --noEmit --skipLibCheck",
44
64
  "check": "bun run check:types && bun test",