ecspresso 0.0.1 → 0.0.3

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 CHANGED
@@ -49,6 +49,22 @@ The ECS pattern separates data (Components) from behavior (Systems) through Enti
49
49
  - Fluent builder API for creating systems and bundles
50
50
  - Event handling with lifecycle hooks for systems
51
51
  - Resource management for global state
52
+ - Simplified system API - all system methods receive the ECSpresso instance
53
+
54
+ ### System API Design
55
+
56
+ All system methods (process, onAttach, onDetach, and event handlers) receive the ECSpresso instance as a parameter, which provides:
57
+
58
+ - Access to entity management via `ecs.entityManager`
59
+ - Access to resources via `ecs.resourceManager`
60
+ - Access to events via `ecs.eventBus`
61
+
62
+ This design simplifies the API and allows systems access to all ECS functionality through a single reference. Benefits of this approach include:
63
+
64
+ - **Simpler method signatures**: Systems only need to deal with one additional parameter (the ECS instance) rather than multiple managers
65
+ - **Future extensibility**: New functionality added to the ECSpresso class is automatically available to all systems without changing method signatures
66
+ - **Consistency**: All system methods (process, lifecycle hooks, event handlers) use the same parameter pattern
67
+ - **Reduced verbosity**: Systems can be written more concisely while still having access to all ECS functionality
52
68
 
53
69
  ## Installation
54
70
 
@@ -98,11 +114,11 @@ const ecs = new ECSpresso<
98
114
  ecs.addResource('gameState', { score: 0, level: 1 });
99
115
 
100
116
  // Create an entity
101
- const entityId = ecs.createEntity();
117
+ const entity = ecs.entityManager.createEntity();
102
118
 
103
119
  // Add components to the entity
104
- ecs.addComponent(entityId, 'position', { x: 0, y: 0 });
105
- ecs.addComponent(entityId, 'velocity', { dx: 1, dy: 2 });
120
+ ecs.entityManager.addComponent(entity.id, 'position', { x: 0, y: 0 });
121
+ ecs.entityManager.addComponent(entity.id, 'velocity', { dx: 1, dy: 2 });
106
122
 
107
123
  // Run the simulation
108
124
  ecs.update(16.67); // Pass delta time in ms
@@ -117,7 +133,7 @@ const movementSystem = ecs.entityManager
117
133
  .addQuery('movable', {
118
134
  with: ['position', 'velocity']
119
135
  })
120
- .setProcess((queries, deltaTime) => {
136
+ .setProcess((queries, deltaTime, ecs) => {
121
137
  // Process entities with both position and velocity
122
138
  for (const entity of queries.movable) {
123
139
  const { position, velocity } = entity.components;
@@ -146,11 +162,11 @@ physicsBundle
146
162
  .addQuery('collidable', {
147
163
  with: ['position']
148
164
  })
149
- .setProcess((queries, deltaTime, entityManager, resourceManager, eventBus) => {
165
+ .setProcess((queries, deltaTime, ecs) => {
150
166
  // Check for collisions
151
167
  // ...
152
168
  // Emit collision events
153
- eventBus.emit('collision', { entityA: 1, entityB: 2 });
169
+ ecs.eventBus.publish('collision', { entityA: 1, entityB: 2 });
154
170
  });
155
171
 
156
172
  // Install the bundle
@@ -165,9 +181,9 @@ const scoreSystem = ecs.entityManager
165
181
  .createSystem('score')
166
182
  .setEventHandlers({
167
183
  collision: {
168
- handler: (event, entityManager, resourceManager) => {
184
+ handler: (event, ecs) => {
169
185
  // Handle collision event
170
- const gameState = resourceManager.getResource('gameState');
186
+ const gameState = ecs.resourceManager.getResource('gameState');
171
187
  if (gameState) {
172
188
  gameState.score += 10;
173
189
  }
@@ -204,14 +220,73 @@ ecs.install(gameBundle);
204
220
  // Create a system with lifecycle hooks
205
221
  const renderSystem = ecs.entityManager
206
222
  .createSystem('render')
207
- .setOnAttach((entityManager, resourceManager, eventBus) => {
223
+ .setOnAttach((ecs) => {
208
224
  // Initialize rendering resources
209
225
  console.log('Render system attached');
210
226
  })
211
- .setOnDetach((entityManager, resourceManager, eventBus) => {
227
+ .setOnDetach((ecs) => {
212
228
  // Clean up rendering resources
213
229
  console.log('Render system detached');
214
230
  });
215
231
  ```
216
232
 
233
+ ### Complex System Example
234
+
235
+ The following example demonstrates a system that uses multiple aspects of the ECS (queries, resources, and events) with the simplified API:
236
+
237
+ ```typescript
238
+ // Create a complex AI system that needs access to multiple ECS features
239
+ const aiSystem = ecs.entityManager
240
+ .createSystem('enemyAI')
241
+ .addQuery('enemies', {
242
+ with: ['position', 'ai', 'health'],
243
+ without: ['stunned']
244
+ })
245
+ .addQuery('players', {
246
+ with: ['position', 'player']
247
+ })
248
+ .setProcess((queries, deltaTime, ecs) => {
249
+ // Access game configuration from resources
250
+ const config = ecs.resourceManager.get('gameConfig');
251
+ const difficultyMultiplier = config?.difficulty || 1.0;
252
+
253
+ // Process each enemy
254
+ for (const enemy of queries.enemies) {
255
+ // Find the nearest player
256
+ let nearestPlayer = null;
257
+ let shortestDistance = Infinity;
258
+
259
+ for (const player of queries.players) {
260
+ const distance = calculateDistance(
261
+ enemy.components.position,
262
+ player.components.position
263
+ );
264
+
265
+ if (distance < shortestDistance) {
266
+ nearestPlayer = player;
267
+ shortestDistance = distance;
268
+ }
269
+ }
270
+
271
+ if (nearestPlayer && shortestDistance < enemy.components.ai.detectionRange * difficultyMultiplier) {
272
+ // Enemy detected player, update AI state
273
+ if (enemy.components.ai.state !== 'chasing') {
274
+ enemy.components.ai.state = 'chasing';
275
+
276
+ // Emit event that enemy spotted player
277
+ ecs.eventBus.publish('enemySpottedPlayer', {
278
+ enemyId: enemy.id,
279
+ playerId: nearestPlayer.id
280
+ });
281
+ }
282
+
283
+ // Move enemy toward player
284
+ moveToward(enemy, nearestPlayer, deltaTime);
285
+ }
286
+ }
287
+ });
288
+ ```
289
+
290
+ This example shows how having access to the entire ECS through a single parameter simplifies the code, as the system can easily work with entity queries, access resources, and publish events without needing separate parameters for each manager.
291
+
217
292
  This project was created using `bun init` in bun v1.2.4. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
@@ -0,0 +1,67 @@
1
+ import { SystemBuilder } from './system-builder';
2
+ /**
3
+ * Bundle class that encapsulates a set of components, resources, events, and systems
4
+ * that can be merged into a ECSpresso instance
5
+ */
6
+ export default class Bundle<ComponentTypes extends Record<string, any> = Record<string, any>, EventTypes extends Record<string, any> = Record<string, any>, ResourceTypes extends Record<string, any> = Record<string, any>> {
7
+ private _systems;
8
+ private _resources;
9
+ private _id;
10
+ constructor(id?: string);
11
+ /**
12
+ * Get the unique ID of this bundle
13
+ */
14
+ get id(): string;
15
+ /**
16
+ * Set the ID of this bundle
17
+ * @internal Used by combineBundles
18
+ */
19
+ set id(value: string);
20
+ /**
21
+ * Add a system to this bundle
22
+ */
23
+ addSystem(label: string): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, {}>;
24
+ /**
25
+ * Add a resource to this bundle
26
+ * @param label The resource key
27
+ * @param resource The resource value
28
+ */
29
+ addResource<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K]): this;
30
+ /**
31
+ * Get all systems defined in this bundle
32
+ * Returns built System objects instead of SystemBuilders
33
+ */
34
+ getSystems(): import("./types").System<ComponentTypes, any, any, EventTypes, ResourceTypes>[];
35
+ /**
36
+ * Get all resources defined in this bundle
37
+ */
38
+ getResources(): Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]>;
39
+ /**
40
+ * Get a specific resource by key
41
+ * @param key The resource key
42
+ * @returns The resource value or undefined if not found
43
+ */
44
+ getResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] | undefined;
45
+ /**
46
+ * Get all system builders in this bundle
47
+ */
48
+ getSystemBuilders(): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, any>[];
49
+ /**
50
+ * Check if this bundle has a specific resource
51
+ * @param key The resource key to check
52
+ * @returns True if the resource exists
53
+ */
54
+ hasResource<K extends keyof ResourceTypes>(key: K): boolean;
55
+ }
56
+ /**
57
+ * Utility type for merging two types
58
+ */
59
+ export type Merge<T1, T2> = T1 & T2;
60
+ export type MergeAll<T extends any[]> = T extends [infer First, ...infer Rest] ? Rest extends [] ? First : Merge<First, MergeAll<Rest>> : {};
61
+ export declare function mergeBundles<Bundles extends Array<Bundle<any, any, any>>>(id: string, ...bundles: Bundles): Bundle<MergeAll<{
62
+ [K in keyof Bundles]: Bundles[K] extends Bundle<infer C, any, any> ? C : never;
63
+ }>, MergeAll<{
64
+ [K in keyof Bundles]: Bundles[K] extends Bundle<any, infer E, any> ? E : never;
65
+ }>, MergeAll<{
66
+ [K in keyof Bundles]: Bundles[K] extends Bundle<any, any, infer R> ? R : never;
67
+ }>>;
@@ -0,0 +1,77 @@
1
+ import EntityManager from "./entity-manager";
2
+ import EventBus from "./event-bus";
3
+ import ResourceManager from "./resource-manager";
4
+ import type Bundle from "./bundle";
5
+ /**
6
+ * The main ECS (Entity Component System) container class
7
+ *
8
+ * This class manages entities, components, systems, resources, and events.
9
+ *
10
+ * Systems interact with the ECS through a single parameter that provides access
11
+ * to the entire ECSpresso instance. This provides a simplified API for systems
12
+ * and allows them access to all ECS functionality through a single reference.
13
+ *
14
+ * @template ComponentTypes Record of component types used in this ECS instance
15
+ * @template EventTypes Record of event types used in this ECS instance
16
+ * @template ResourceTypes Record of resource types used in this ECS instance
17
+ */
18
+ export default class ECSpresso<ComponentTypes extends Record<string, any> = Record<string, any>, EventTypes extends Record<string, any> = Record<string, any>, ResourceTypes extends Record<string, any> = Record<string, any>> {
19
+ static readonly VERSION: string;
20
+ private _entityManager;
21
+ private _systems;
22
+ private _eventBus;
23
+ private _resourceManager;
24
+ private _installedBundles;
25
+ constructor();
26
+ /**
27
+ * Install one or more bundles into this ECS instance
28
+ * Systems in the bundle will have their onAttach method called with this ECSpresso instance
29
+ * @param bundles One or more bundles to install
30
+ * @returns This ECSpresso instance for method chaining
31
+ */
32
+ install<Bundles extends Array<Bundle<any, any, any>>>(...bundles: Bundles): this;
33
+ /**
34
+ * Remove a system by its label
35
+ * Calls the system's onDetach method with this ECSpresso instance if defined
36
+ * @param label The unique label of the system to remove
37
+ * @returns true if the system was found and removed, false otherwise
38
+ */
39
+ removeSystem(label: string): boolean;
40
+ /**
41
+ * Check if a resource exists
42
+ */
43
+ hasResource<K extends keyof ResourceTypes>(key: K): boolean;
44
+ /**
45
+ * Get a resource if it exists, or undefined if not
46
+ */
47
+ getResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] | undefined;
48
+ /**
49
+ * Get a resource, throws error if not found
50
+ */
51
+ getResourceOrThrow<K extends keyof ResourceTypes>(key: K): ResourceTypes[K];
52
+ /**
53
+ * Add a resource to the ECS instance
54
+ */
55
+ addResource<K extends keyof ResourceTypes>(key: K, resource: ResourceTypes[K]): this;
56
+ /**
57
+ * Check if an entity has a component
58
+ */
59
+ hasComponent<K extends keyof ComponentTypes>(entityId: number, componentName: K): boolean;
60
+ /**
61
+ * Get all entities with specific components
62
+ */
63
+ getEntitiesWithComponents(withComponents: (keyof ComponentTypes)[], withoutComponents?: (keyof ComponentTypes)[]): import("./types").FilteredEntity<ComponentTypes, keyof ComponentTypes extends infer T ? T extends keyof ComponentTypes ? T extends never ? never : T : never : never, keyof ComponentTypes extends infer T_1 ? T_1 extends keyof ComponentTypes ? T_1 extends never ? never : T_1 : never : never>[];
64
+ /**
65
+ * Update all systems
66
+ * Calls each system's process method with this ECSpresso instance
67
+ * @param deltaTime Time elapsed since the last update in seconds
68
+ */
69
+ update(deltaTime: number): void;
70
+ get entityManager(): EntityManager<ComponentTypes>;
71
+ get eventBus(): EventBus<EventTypes>;
72
+ get resourceManager(): ResourceManager<ResourceTypes>;
73
+ /**
74
+ * Get all installed bundle IDs
75
+ */
76
+ get installedBundles(): string[];
77
+ }
@@ -0,0 +1,13 @@
1
+ import type { Entity, FilteredEntity } from "./types";
2
+ export default class EntityManager<ComponentTypes> {
3
+ private nextId;
4
+ private entities;
5
+ private componentIndices;
6
+ createEntity(): Entity<ComponentTypes>;
7
+ addComponent<ComponentName extends keyof ComponentTypes>(entityOrId: number | Entity<ComponentTypes>, componentName: ComponentName, data: ComponentTypes[ComponentName]): this;
8
+ removeComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): void;
9
+ getComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): ComponentTypes[ComponentName] | null;
10
+ getEntitiesWithComponents<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>>;
11
+ removeEntity(entityId: number): boolean;
12
+ getEntity(entityId: number): Entity<ComponentTypes> | undefined;
13
+ }
@@ -0,0 +1,18 @@
1
+ export default class EventBus<EventTypes> {
2
+ private handlers;
3
+ /**
4
+ * Subscribe to an event
5
+ */
6
+ subscribe<E extends keyof EventTypes>(eventType: E, callback: (data: EventTypes[E]) => void): () => void;
7
+ /**
8
+ * Subscribe to an event once
9
+ */
10
+ once<E extends keyof EventTypes>(eventType: E, callback: (data: EventTypes[E]) => void): () => void;
11
+ /**
12
+ * Internal method to add an event handler
13
+ */
14
+ private addHandler;
15
+ publish<E extends keyof EventTypes>(eventType: E, data?: EventTypes[E]): void;
16
+ clear(): void;
17
+ clearEvent<E extends keyof EventTypes>(eventType: E): void;
18
+ }
package/dist/index.d.ts CHANGED
@@ -1,323 +1,10 @@
1
- declare module "src/resource-manager" {
2
- export default class ResourceManager<ResourceTypes extends Record<string, any> = Record<string, any>> {
3
- private resources;
4
- /**
5
- * Add a resource to the manager
6
- * @param label The resource key
7
- * @param resource The resource value
8
- * @returns The added resource
9
- */
10
- add<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K]): ResourceTypes[K];
11
- /**
12
- * Get a resource from the manager
13
- * @param label The resource key
14
- * @returns The resource value
15
- * @throws Error if resource not found
16
- */
17
- get<K extends keyof ResourceTypes>(label: K): ResourceTypes[K];
18
- /**
19
- * Get a resource from the manager, returning undefined if not found
20
- * @param label The resource key
21
- * @returns The resource value or undefined if not found
22
- */
23
- getOptional<K extends keyof ResourceTypes>(label: K): ResourceTypes[K] | undefined;
24
- /**
25
- * Check if a resource exists
26
- * @param label The resource key
27
- * @returns True if the resource exists
28
- */
29
- has<K extends keyof ResourceTypes>(label: K): boolean;
30
- /**
31
- * Remove a resource
32
- * @param label The resource key
33
- * @returns True if the resource was removed
34
- */
35
- remove<K extends keyof ResourceTypes>(label: K): boolean;
36
- /**
37
- * Get all resource keys
38
- * @returns Array of resource keys
39
- */
40
- getKeys(): Array<keyof ResourceTypes>;
41
- }
42
- }
43
- declare module "src/event-bus" {
44
- export default class EventBus<EventTypes> {
45
- private handlers;
46
- /**
47
- * Subscribe to an event
48
- */
49
- subscribe<E extends keyof EventTypes>(eventType: E, callback: (data: EventTypes[E]) => void): () => void;
50
- /**
51
- * Subscribe to an event once
52
- */
53
- once<E extends keyof EventTypes>(eventType: E, callback: (data: EventTypes[E]) => void): () => void;
54
- /**
55
- * Internal method to add an event handler
56
- */
57
- private addHandler;
58
- publish<E extends keyof EventTypes>(eventType: E, data?: EventTypes[E]): void;
59
- clear(): void;
60
- clearEvent<E extends keyof EventTypes>(eventType: E): void;
61
- }
62
- }
63
- declare module "src/types" {
64
- import type ResourceManager from "src/resource-manager";
65
- import type EventBus from "src/event-bus";
66
- import type EntityManager from "src/entity-manager";
67
- export interface Entity<ComponentTypes> {
68
- id: number;
69
- components: Partial<ComponentTypes>;
70
- }
71
- export interface EventHandler<T> {
72
- callback: (data: T) => void;
73
- once: boolean;
74
- }
75
- export interface FilteredEntity<ComponentTypes, WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never> {
76
- id: number;
77
- components: Omit<Partial<ComponentTypes>, WithoutComponents> & {
78
- [ComponentName in WithComponents]: ComponentTypes[ComponentName];
79
- };
80
- }
81
- export interface QueryConfig<ComponentTypes, WithComponents extends keyof ComponentTypes, WithoutComponents extends keyof ComponentTypes> {
82
- with: ReadonlyArray<WithComponents>;
83
- without?: ReadonlyArray<WithoutComponents>;
84
- }
85
- export interface System<ComponentTypes, WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never, EventTypes extends Record<string, any> = Record<string, any>, ResourceTypes extends Record<string, any> = Record<string, any>> {
86
- label: string;
87
- entityQueries?: {
88
- [queryName: string]: QueryConfig<ComponentTypes, WithComponents, WithoutComponents>;
89
- };
90
- process?(queries: {
91
- [queryName: string]: Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>;
92
- } | Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>, deltaTime: number, entityManager: EntityManager<ComponentTypes>, resourceManager: ResourceManager<ResourceTypes>, eventBus: EventBus<EventTypes>): void;
93
- onAttach?(entityManager: EntityManager<ComponentTypes>, resourceManager: ResourceManager<ResourceTypes>, eventBus: EventBus<EventTypes>): void;
94
- onDetach?(entityManager: EntityManager<ComponentTypes>, resourceManager: ResourceManager<ResourceTypes>, eventBus: EventBus<EventTypes>): void;
95
- eventHandlers?: {
96
- [EventName in keyof EventTypes]?: {
97
- handler(data: EventTypes[EventName], entityManager: EntityManager<ComponentTypes>, resourceManager: ResourceManager<ResourceTypes>, eventBus: EventBus<EventTypes>): void;
98
- };
99
- };
100
- }
101
- }
102
- declare module "src/entity-manager" {
103
- import type { Entity, FilteredEntity } from "src/types";
104
- export default class EntityManager<ComponentTypes> {
105
- private nextId;
106
- private entities;
107
- private componentIndices;
108
- createEntity(): Entity<ComponentTypes>;
109
- addComponent<ComponentName extends keyof ComponentTypes>(entityOrId: number | Entity<ComponentTypes>, componentName: ComponentName, data: ComponentTypes[ComponentName]): this;
110
- removeComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): void;
111
- getComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): ComponentTypes[ComponentName] | null;
112
- getEntitiesWithComponents<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>>;
113
- removeEntity(entityId: number): boolean;
114
- getEntity(entityId: number): Entity<ComponentTypes> | undefined;
115
- }
116
- }
117
- declare module "src/system-builder" {
118
- import Bundle from "src/bundle";
119
- import type EntityManager from "src/entity-manager";
120
- import type EventBus from "src/event-bus";
121
- import type ResourceManager from "src/resource-manager";
122
- import type { FilteredEntity, System } from "src/types";
123
- /**
124
- * Builder class for creating type-safe ECS Systems with proper query inference
125
- */
126
- export class SystemBuilder<ComponentTypes extends Record<string, any> = Record<string, any>, EventTypes extends Record<string, any> = Record<string, any>, ResourceTypes extends Record<string, any> = Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>> = {}> {
127
- private _label;
128
- private _bundle;
129
- private queries;
130
- private processFunction?;
131
- private attachFunction?;
132
- private detachFunction?;
133
- private eventHandlers?;
134
- constructor(_label: string, _bundle?: Bundle<ComponentTypes, EventTypes, ResourceTypes>);
135
- get label(): string;
136
- get bundle(): Bundle<ComponentTypes, EventTypes, ResourceTypes>;
137
- /**
138
- * Add a query definition to the system
139
- */
140
- addQuery<QueryName extends string, WithComponents extends keyof ComponentTypes, WithoutComponents extends keyof ComponentTypes = never>(name: QueryName, definition: {
141
- with: ReadonlyArray<WithComponents>;
142
- without?: ReadonlyArray<WithoutComponents>;
143
- }): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries & Record<QueryName, QueryDefinition<ComponentTypes, WithComponents, WithoutComponents>>>;
144
- /**
145
- * Set the system's process function that runs each update
146
- */
147
- setProcess(process: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries>;
148
- /**
149
- * Set the onAttach lifecycle hook
150
- */
151
- setOnAttach(onAttach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries>;
152
- /**
153
- * Set the onDetach lifecycle hook
154
- */
155
- setOnDetach(onDetach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries>;
156
- /**
157
- * Set event handlers for the system
158
- */
159
- setEventHandlers(handlers: {
160
- [EventName in keyof EventTypes]?: {
161
- handler(data: EventTypes[EventName], entityManager: EntityManager<ComponentTypes>, resourceManager: ResourceManager<ResourceTypes>, eventBus: EventBus<EventTypes>): void;
162
- };
163
- }): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries>;
164
- /**
165
- * Build the final system object
166
- */
167
- build(): System<ComponentTypes, any, any, EventTypes, ResourceTypes>;
168
- }
169
- type QueryDefinition<ComponentTypes, WithComponents extends keyof ComponentTypes = any, WithoutComponents extends keyof ComponentTypes = any> = {
170
- with: ReadonlyArray<WithComponents>;
171
- without?: ReadonlyArray<WithoutComponents>;
172
- };
173
- type QueryResults<ComponentTypes, Queries extends Record<string, QueryDefinition<ComponentTypes>>> = {
174
- [QueryName in keyof Queries]: QueryName extends string ? FilteredEntity<ComponentTypes, Queries[QueryName] extends QueryDefinition<ComponentTypes, infer W, any> ? W : never, Queries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO> ? WO : never>[] : never;
175
- };
176
- type ProcessFunction<ComponentTypes, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>>> = (queries: QueryResults<ComponentTypes, Queries>, deltaTime: number, entityManager: EntityManager<ComponentTypes>, resourceManager: ResourceManager<ResourceTypes>, eventBus: EventBus<EventTypes>) => void;
177
- type LifecycleFunction<ComponentTypes, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>> = (entityManager: EntityManager<ComponentTypes>, resourceManager: ResourceManager<ResourceTypes>, eventBus: EventBus<EventTypes>) => void;
178
- }
179
- declare module "src/bundle" {
180
- import { SystemBuilder } from "src/system-builder";
181
- /**
182
- * Bundle class that encapsulates a set of components, resources, events, and systems
183
- * that can be merged into a ECSpresso instance
184
- */
185
- export default class Bundle<ComponentTypes extends Record<string, any> = Record<string, any>, EventTypes extends Record<string, any> = Record<string, any>, ResourceTypes extends Record<string, any> = Record<string, any>> {
186
- private _systems;
187
- private _resources;
188
- private _id;
189
- constructor(id?: string);
190
- /**
191
- * Get the unique ID of this bundle
192
- */
193
- get id(): string;
194
- /**
195
- * Set the ID of this bundle
196
- * @internal Used by combineBundles
197
- */
198
- set id(value: string);
199
- /**
200
- * Add a system to this bundle
201
- */
202
- addSystem(label: string): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, {}>;
203
- /**
204
- * Add a resource to this bundle
205
- * @param label The resource key
206
- * @param resource The resource value
207
- */
208
- addResource<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K]): this;
209
- /**
210
- * Get all systems defined in this bundle
211
- * Returns built System objects instead of SystemBuilders
212
- */
213
- getSystems(): import("src").System<ComponentTypes, any, any, EventTypes, ResourceTypes>[];
214
- /**
215
- * Get all resources defined in this bundle
216
- */
217
- getResources(): Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]>;
218
- /**
219
- * Get a specific resource by key
220
- * @param key The resource key
221
- * @returns The resource value or undefined if not found
222
- */
223
- getResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] | undefined;
224
- /**
225
- * Get all system builders in this bundle
226
- */
227
- getSystemBuilders(): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, any>[];
228
- /**
229
- * Check if this bundle has a specific resource
230
- * @param key The resource key to check
231
- * @returns True if the resource exists
232
- */
233
- hasResource<K extends keyof ResourceTypes>(key: K): boolean;
234
- }
235
- /**
236
- * Utility type for merging two types
237
- */
238
- export type Merge<T1, T2> = T1 & T2;
239
- export type MergeAll<T extends any[]> = T extends [infer First, ...infer Rest] ? Rest extends [] ? First : Merge<First, MergeAll<Rest>> : {};
240
- export function mergeBundles<Bundles extends Array<Bundle<any, any, any>>>(id: string, ...bundles: Bundles): Bundle<MergeAll<{
241
- [K in keyof Bundles]: Bundles[K] extends Bundle<infer C, any, any> ? C : never;
242
- }>, MergeAll<{
243
- [K in keyof Bundles]: Bundles[K] extends Bundle<any, infer E, any> ? E : never;
244
- }>, MergeAll<{
245
- [K in keyof Bundles]: Bundles[K] extends Bundle<any, any, infer R> ? R : never;
246
- }>>;
247
- }
248
- declare module "src/ecspresso" {
249
- import EntityManager from "src/entity-manager";
250
- import EventBus from "src/event-bus";
251
- import ResourceManager from "src/resource-manager";
252
- import type Bundle from "src/bundle";
253
- export default class ECSpresso<ComponentTypes extends Record<string, any> = Record<string, any>, EventTypes extends Record<string, any> = Record<string, any>, ResourceTypes extends Record<string, any> = Record<string, any>> {
254
- static readonly VERSION: string;
255
- private _entityManager;
256
- private _systems;
257
- private _eventBus;
258
- private _resourceManager;
259
- private _installedBundles;
260
- constructor();
261
- /**
262
- * Install one or more bundles into this ECS instance
263
- */
264
- install<Bundles extends Array<Bundle<any, any, any>>>(...bundles: Bundles): this;
265
- /**
266
- * Remove a system by its label
267
- */
268
- removeSystem(label: string): boolean;
269
- /**
270
- * Check if a resource exists
271
- */
272
- hasResource<K extends keyof ResourceTypes>(key: K): boolean;
273
- /**
274
- * Get a resource if it exists, or undefined if not
275
- */
276
- getResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] | undefined;
277
- /**
278
- * Get a resource, throws error if not found
279
- */
280
- getResourceOrThrow<K extends keyof ResourceTypes>(key: K): ResourceTypes[K];
281
- /**
282
- * Add a resource to the ECS instance
283
- */
284
- addResource<K extends keyof ResourceTypes>(key: K, resource: ResourceTypes[K]): this;
285
- /**
286
- * Check if an entity has a component
287
- */
288
- hasComponent<K extends keyof ComponentTypes>(entityId: number, componentName: K): boolean;
289
- /**
290
- * Get all entities with specific components
291
- */
292
- getEntitiesWithComponents(withComponents: (keyof ComponentTypes)[], withoutComponents?: (keyof ComponentTypes)[]): import("src").FilteredEntity<ComponentTypes, keyof ComponentTypes extends infer T ? T extends keyof ComponentTypes ? T extends never ? never : T : never : never, keyof ComponentTypes extends infer T_1 ? T_1 extends keyof ComponentTypes ? T_1 extends never ? never : T_1 : never : never>[];
293
- /**
294
- * Update all systems
295
- */
296
- update(deltaTime: number): void;
297
- get entityManager(): EntityManager<ComponentTypes>;
298
- get eventBus(): EventBus<EventTypes>;
299
- get resourceManager(): ResourceManager<ResourceTypes>;
300
- /**
301
- * Get all installed bundle IDs
302
- */
303
- get installedBundles(): string[];
304
- }
305
- }
306
- declare module "src/bundle.test" { }
307
- declare module "src/ecspresso.test" { }
308
- declare module "src/event-bus.test" { }
309
- declare module "src/index" {
310
- import ECSpresso from "src/ecspresso";
311
- import { SystemBuilder } from "src/system-builder";
312
- import Bundle, { mergeBundles } from "src/bundle";
313
- export * from "src/types";
314
- export { default as EntityManager } from "src/entity-manager";
315
- export { default as EventBus } from "src/event-bus";
316
- export { default as ResourceManager } from "src/resource-manager";
317
- export { SystemBuilder };
318
- export { Bundle, mergeBundles };
319
- export default ECSpresso;
320
- }
321
- declare module "src/resource-manager.test" { }
322
- declare module "src/system-builder.test" { }
323
- //# sourceMappingURL=index.d.ts.map
1
+ import ECSpresso from './ecspresso';
2
+ import { SystemBuilder } from './system-builder';
3
+ import Bundle, { mergeBundles } from './bundle';
4
+ export * from './types';
5
+ export { default as EntityManager } from './entity-manager';
6
+ export { default as EventBus } from './event-bus';
7
+ export { default as ResourceManager } from './resource-manager';
8
+ export { SystemBuilder };
9
+ export { Bundle, mergeBundles };
10
+ export default ECSpresso;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- class M{nextId=1;entities=new Map;componentIndices=new Map;createEntity(){let f=this.nextId++,g={id:f,components:{}};return this.entities.set(f,g),g}addComponent(f,g,j){let J=typeof f==="number"?this.entities.get(f):f;if(!J)throw new Error(`Entity ${f} does not exist`);if(J.components[g]=j,!this.componentIndices.has(g))this.componentIndices.set(g,new Set);return this.componentIndices.get(g)?.add(J.id),this}removeComponent(f,g){let j=this.entities.get(f);if(!j)throw new Error(`Entity ${f} does not exist`);delete j.components[g],this.componentIndices.get(g)?.delete(f)}getComponent(f,g){let j=this.entities.get(f);if(!j)throw new Error(`Entity ${f} does not exist`);return j.components[g]||null}getEntitiesWithComponents(f=[],g=[]){if(f.length===0){if(g.length===0)return Array.from(this.entities.values());return Array.from(this.entities.values()).filter((E)=>{return g.every((F)=>!(F in E.components))})}let j=f.reduce((E,F)=>{let K=this.componentIndices.get(F),U=K?K.size:0,X=this.componentIndices.get(E)?.size??1/0;return U<X?F:E},f[0]);return Array.from(this.componentIndices.get(j)||[]).filter((E)=>{let F=this.entities.get(E);return F&&f.every((K)=>(K in F.components))&&g.every((K)=>!(K in F.components))}).map((E)=>this.entities.get(E))}removeEntity(f){let g=this.entities.get(f);if(!g)return!1;for(let j of Object.keys(g.components))this.componentIndices.get(j)?.delete(f);return this.entities.delete(f)}getEntity(f){return this.entities.get(f)}}class P{handlers=new Map;subscribe(f,g){return this.addHandler(f,g,!1)}once(f,g){return this.addHandler(f,g,!0)}addHandler(f,g,j){if(!this.handlers.has(f))this.handlers.set(f,[]);let J={callback:g,once:j};return this.handlers.get(f).push(J),()=>{let E=this.handlers.get(f);if(E){let F=E.indexOf(J);if(F!==-1)E.splice(F,1)}}}publish(f,g=void 0){let j=this.handlers.get(f);if(!j)return;let J=[...j],E=[];for(let F of J)if(F.callback(g),F.once)E.push(F);if(E.length>0)for(let F of E){let K=j.indexOf(F);if(K!==-1)j.splice(K,1)}}clear(){this.handlers.clear()}clearEvent(f){this.handlers.delete(f)}}class Q{resources=new Map;add(f,g){return this.resources.set(f,g),g}get(f){let g=this.resources.get(f);if(g===void 0)throw new Error(`Resource ${String(f)} not found`);return g}getOptional(f){return this.resources.get(f)}has(f){return this.resources.has(f)}remove(f){return this.resources.delete(f)}getKeys(){return Array.from(this.resources.keys())}}var Y="0.0.1";class V{static VERSION=Y;_entityManager;_systems=[];_eventBus;_resourceManager;_installedBundles=new Set;constructor(){this._entityManager=new M,this._eventBus=new P,this._resourceManager=new Q}install(...f){for(let g of f){if(this._installedBundles.has(g.id)){console.warn(`Bundle ${g.id} is already installed`);continue}let j=g.getSystems();if(!j.length)console.warn(`Bundle ${g.id} has no systems`);for(let E of j){let F=E;if(this._systems.push(F),F.onAttach)F.onAttach(this._entityManager,this._resourceManager,this._eventBus);if(F.eventHandlers)for(let K in F.eventHandlers){let U=F.eventHandlers[K];if(U?.handler){let X=(Z)=>{U.handler(Z,this._entityManager,this._resourceManager,this._eventBus)};this._eventBus.subscribe(K,X)}}}let J=g.getResources();for(let[E,F]of J.entries())this._resourceManager.add(E,F);this._installedBundles.add(g.id)}return this}removeSystem(f){let g=this._systems.findIndex((J)=>J.label===f);if(g===-1)return!1;let j=this._systems[g];if(!j)return!1;return j.onDetach?.(this._entityManager,this._resourceManager,this._eventBus),this._systems.splice(g,1),!0}hasResource(f){return this._resourceManager.has(f)}getResource(f){return this._resourceManager.getOptional(f)}getResourceOrThrow(f){return this._resourceManager.get(f)}addResource(f,g){return this._resourceManager.add(f,g),this}hasComponent(f,g){return this._entityManager.getComponent(f,g)!==null}getEntitiesWithComponents(f,g=[]){return this._entityManager.getEntitiesWithComponents(f,g)}update(f){for(let g of this._systems){if(!g.process)continue;let j={};if(g.entityQueries){for(let J in g.entityQueries){let E=g.entityQueries[J];if(E)j[J]=this._entityManager.getEntitiesWithComponents(E.with,E.without||[])}g.process(j,f,this._entityManager,this._resourceManager,this._eventBus)}else g.process([],f,this._entityManager,this._resourceManager,this._eventBus)}}get entityManager(){return this._entityManager}get eventBus(){return this._eventBus}get resourceManager(){return this._resourceManager}get installedBundles(){return Array.from(this._installedBundles)}}function $(){return`bundle_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,9)}`}class L{_systems=[];_resources=new Map;_id;constructor(f){this._id=f||$()}get id(){return this._id}set id(f){this._id=f}addSystem(f){let g=new W(f,this);return this._systems.push(g),g}addResource(f,g){return this._resources.set(f,g),this}getSystems(){return this._systems.map((f)=>f.build())}getResources(){return new Map(this._resources)}getResource(f){return this._resources.get(f)}getSystemBuilders(){return[...this._systems]}hasResource(f){return this._resources.has(f)}}function D(f,...g){if(g.length===0)return new L(f);let j=new L(f);for(let J of g){for(let E of J.getSystemBuilders())j.addSystem(E);for(let[E,F]of J.getResources().entries())j.addResource(E,F)}return j}class W{_label;_bundle;queries={};processFunction;attachFunction;detachFunction;eventHandlers;constructor(f,g=new L){this._label=f;this._bundle=g}get label(){return this._label}get bundle(){return this._bundle}addQuery(f,g){let j=this;return j.queries={...this.queries,[f]:g},j}setProcess(f){return this.processFunction=f,this}setOnAttach(f){return this.attachFunction=f,this}setOnDetach(f){return this.detachFunction=f,this}setEventHandlers(f){return this.eventHandlers=f,this}build(){let f={label:this._label,entityQueries:this.queries};if(this.processFunction)f.process=this.processFunction;if(this.attachFunction)f.onAttach=this.attachFunction;if(this.detachFunction)f.onDetach=this.detachFunction;if(this.eventHandlers)f.eventHandlers=this.eventHandlers;return f}}var i=V;export{D as mergeBundles,i as default,W as SystemBuilder,Q as ResourceManager,P as EventBus,M as EntityManager,L as Bundle};
1
+ class P{nextId=1;entities=new Map;componentIndices=new Map;createEntity(){let f=this.nextId++,g={id:f,components:{}};return this.entities.set(f,g),g}addComponent(f,g,j){let K=typeof f==="number"?this.entities.get(f):f;if(!K)throw new Error(`Entity ${f} does not exist`);if(K.components[g]=j,!this.componentIndices.has(g))this.componentIndices.set(g,new Set);return this.componentIndices.get(g)?.add(K.id),this}removeComponent(f,g){let j=this.entities.get(f);if(!j)throw new Error(`Entity ${f} does not exist`);delete j.components[g],this.componentIndices.get(g)?.delete(f)}getComponent(f,g){let j=this.entities.get(f);if(!j)throw new Error(`Entity ${f} does not exist`);return j.components[g]||null}getEntitiesWithComponents(f=[],g=[]){if(f.length===0){if(g.length===0)return Array.from(this.entities.values());return Array.from(this.entities.values()).filter((F)=>{return g.every((J)=>!(J in F.components))})}let j=f.reduce((F,J)=>{let L=this.componentIndices.get(J),V=L?L.size:0,Y=this.componentIndices.get(F)?.size??1/0;return V<Y?J:F},f[0]);return Array.from(this.componentIndices.get(j)||[]).filter((F)=>{let J=this.entities.get(F);return J&&f.every((L)=>(L in J.components))&&g.every((L)=>!(L in J.components))}).map((F)=>this.entities.get(F))}removeEntity(f){let g=this.entities.get(f);if(!g)return!1;for(let j of Object.keys(g.components))this.componentIndices.get(j)?.delete(f);return this.entities.delete(f)}getEntity(f){return this.entities.get(f)}}class Q{handlers=new Map;subscribe(f,g){return this.addHandler(f,g,!1)}once(f,g){return this.addHandler(f,g,!0)}addHandler(f,g,j){if(!this.handlers.has(f))this.handlers.set(f,[]);let K={callback:g,once:j};return this.handlers.get(f).push(K),()=>{let F=this.handlers.get(f);if(F){let J=F.indexOf(K);if(J!==-1)F.splice(J,1)}}}publish(f,g=void 0){let j=this.handlers.get(f);if(!j)return;let K=[...j],F=[];for(let J of K)if(J.callback(g),J.once)F.push(J);if(F.length>0)for(let J of F){let L=j.indexOf(J);if(L!==-1)j.splice(L,1)}}clear(){this.handlers.clear()}clearEvent(f){this.handlers.delete(f)}}class U{resources=new Map;add(f,g){return this.resources.set(f,g),this}get(f){let g=this.resources.get(f);if(g===void 0)throw new Error(`Resource ${String(f)} not found`);return g}getOptional(f){return this.resources.get(f)}has(f){return this.resources.has(f)}remove(f){return this.resources.delete(f)}getKeys(){return Array.from(this.resources.keys())}}var Z="0.0.3";class W{static VERSION=Z;_entityManager;_systems=[];_eventBus;_resourceManager;_installedBundles=new Set;constructor(){this._entityManager=new P,this._eventBus=new Q,this._resourceManager=new U}install(...f){for(let g of f){if(this._installedBundles.has(g.id)){console.warn(`Bundle ${g.id} is already installed`);continue}let j=g.getSystems();if(!j.length)console.warn(`Bundle ${g.id} has no systems`);for(let F of j){let J=F;if(this._systems.push(J),J.onAttach)J.onAttach(this);if(J.eventHandlers)for(let L in J.eventHandlers){let V=J.eventHandlers[L];if(V?.handler){let Y=(_)=>{V.handler(_,this)};this._eventBus.subscribe(L,Y)}}}let K=g.getResources();for(let[F,J]of K.entries())this._resourceManager.add(F,J);this._installedBundles.add(g.id)}return this}removeSystem(f){let g=this._systems.findIndex((K)=>K.label===f);if(g===-1)return!1;let j=this._systems[g];if(!j)return!1;return j.onDetach?.(this),this._systems.splice(g,1),!0}hasResource(f){return this._resourceManager.has(f)}getResource(f){return this._resourceManager.getOptional(f)}getResourceOrThrow(f){return this._resourceManager.get(f)}addResource(f,g){return this._resourceManager.add(f,g),this}hasComponent(f,g){return this._entityManager.getComponent(f,g)!==null}getEntitiesWithComponents(f,g=[]){return this._entityManager.getEntitiesWithComponents(f,g)}update(f){for(let g of this._systems){if(!g.process)continue;let j={};if(g.entityQueries){for(let K in g.entityQueries){let F=g.entityQueries[K];if(F)j[K]=this._entityManager.getEntitiesWithComponents(F.with,F.without||[])}g.process(j,f,this)}else g.process([],f,this)}}get entityManager(){return this._entityManager}get eventBus(){return this._eventBus}get resourceManager(){return this._resourceManager}get installedBundles(){return Array.from(this._installedBundles)}}function D(){return`bundle_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,9)}`}class M{_systems=[];_resources=new Map;_id;constructor(f){this._id=f||D()}get id(){return this._id}set id(f){this._id=f}addSystem(f){let g=new X(f,this);return this._systems.push(g),g}addResource(f,g){return this._resources.set(f,g),this}getSystems(){return this._systems.map((f)=>f.build())}getResources(){return new Map(this._resources)}getResource(f){return this._resources.get(f)}getSystemBuilders(){return[...this._systems]}hasResource(f){return this._resources.has(f)}}function H(f,...g){if(g.length===0)return new M(f);let j=new M(f);for(let K of g){for(let F of K.getSystemBuilders())j.addSystem(F);for(let[F,J]of K.getResources().entries())j.addResource(F,J)}return j}class X{_label;_bundle;queries={};processFunction;attachFunction;detachFunction;eventHandlers;constructor(f,g=new M){this._label=f;this._bundle=g}get label(){return this._label}get bundle(){return this._bundle}addQuery(f,g){let j=this;return j.queries={...this.queries,[f]:g},j}setProcess(f){return this.processFunction=f,this}setOnAttach(f){return this.attachFunction=f,this}setOnDetach(f){return this.detachFunction=f,this}setEventHandlers(f){return this.eventHandlers=f,this}build(){let f={label:this._label,entityQueries:this.queries};if(this.processFunction)f.process=this.processFunction;if(this.attachFunction)f.onAttach=this.attachFunction;if(this.detachFunction)f.onDetach=this.detachFunction;if(this.eventHandlers)f.eventHandlers=this.eventHandlers;return f}}var i=W;export{H as mergeBundles,i as default,X as SystemBuilder,U as ResourceManager,Q as EventBus,P as EntityManager,M as Bundle};
2
2
 
3
- //# debugId=281E4BB1A8D4F83A64756E2164756E21
3
+ //# debugId=D9F45C94B8DFE1F064756E2164756E21
4
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -4,13 +4,13 @@
4
4
  "sourcesContent": [
5
5
  "import type { Entity, FilteredEntity } from \"./types\";\n\nexport default\nclass EntityManager<ComponentTypes> {\n\tprivate nextId: number = 1;\n\tprivate entities: Map<number, Entity<ComponentTypes>> = new Map();\n\tprivate componentIndices: Map<keyof ComponentTypes, Set<number>> = new Map();\n\t\n\tcreateEntity(): Entity<ComponentTypes> {\n\t\tconst id = this.nextId++;\n\t\tconst entity: Entity<ComponentTypes> = { id, components: {} };\n\t\tthis.entities.set(id, entity);\n\t\treturn entity;\n\t}\n\n\t// TODO: Component object pooling if(/when) garbage collection is an issue...?\n\taddComponent<ComponentName extends keyof ComponentTypes>(\n\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\tcomponentName: ComponentName,\n\t\tdata: ComponentTypes[ComponentName]\n\t) {\n\t\tconst entity = typeof entityOrId === 'number' ?\n\t\t\tthis.entities.get(entityOrId) :\n\t\t\tentityOrId;\n\n\t\tif (!entity) throw new Error(`Entity ${entityOrId} does not exist`);\n\n\t\tentity.components[componentName] = data;\n\t\t\n\t\t// Update component index\n\t\tif (!this.componentIndices.has(componentName)) {\n\t\t\tthis.componentIndices.set(componentName, new Set());\n\t\t}\n\t\tthis.componentIndices.get(componentName)?.add(entity.id);\n\t\treturn this;\n\t}\n\n\tremoveComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName) {\n\t\tconst entity = this.entities.get(entityId);\n\t\tif (!entity) throw new Error(`Entity ${entityId} does not exist`);\n\n\t\tdelete entity.components[componentName];\n\t\t\n\t\t// Update component index\n\t\tthis.componentIndices.get(componentName)?.delete(entityId);\n\t}\n\n\tgetComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): ComponentTypes[ComponentName] | null {\n\t\tconst entity = this.entities.get(entityId);\n\n\t\tif (!entity) throw new Error(`Entity ${entityId} does not exist`);\n\n\t\treturn entity.components[componentName] || null;\n\t}\n\n\tgetEntitiesWithComponents<\n\t\tWithComponents extends keyof ComponentTypes = never,\n\t\tWithoutComponents extends keyof ComponentTypes = never\n\t>(\n\t\trequired: ReadonlyArray<WithComponents> = [] as any, \n\t\texcluded: ReadonlyArray<WithoutComponents> = [] as any,\n\t): Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>> {\n\t\t// Use the smallest component set as base for better performance\n\t\tif (required.length === 0) {\n\t\t\tif (excluded.length === 0) {\n\t\t\t\treturn Array.from(this.entities.values()) as any;\n\t\t\t}\n\n\t\t\treturn Array\n\t\t\t\t.from(this.entities.values())\n\t\t\t\t.filter((entity) => {\n\t\t\t\t\treturn excluded.every(comp => !(comp in entity.components));\n\t\t\t\t}) as any;\n\t\t}\n\t\t\n\t\t// Find the component with the smallest entity set to start with\n\t\tconst smallestComponent = required.reduce((smallest, comp) => {\n\t\t\tconst set = this.componentIndices.get(comp);\n\t\t\tconst currentSize = set ? set.size : 0;\n\t\t\tconst smallestSize = this.componentIndices.get(smallest!)?.size ?? Infinity;\n\t\t\t\n\t\t\treturn currentSize < smallestSize ? comp : smallest;\n\t\t}, required[0])!;\n\n\t\t// Start with the entities from the smallest component set\n\t\tconst candidates = Array.from(this.componentIndices.get(smallestComponent) || []);\n\n\t\t// Return full entity objects, not just IDs\n\t\treturn candidates\n\t\t\t.filter(id => {\n\t\t\t\tconst entity = this.entities.get(id);\n\t\t\t\treturn (\n\t\t\t\t\tentity &&\n\t\t\t\t\trequired.every(comp => comp in entity.components) && \n\t\t\t\t\texcluded.every(comp => !(comp in entity.components))\n\t\t\t\t);\n\t\t\t})\n\t\t\t.map(id => this.entities.get(id)!) as Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>>;\n\t}\n\n\tremoveEntity(entityId: number): boolean {\n\t\tconst entity = this.entities.get(entityId);\n\t\tif (!entity) return false;\n\t\t\n\t\t// Remove entity from all component indices\n\t\tfor (const componentName of Object.keys(entity.components) as Array<keyof ComponentTypes>) {\n\t\t\tthis.componentIndices.get(componentName)?.delete(entityId);\n\t\t}\n\t\t\n\t\t// Remove the entity itself\n\t\treturn this.entities.delete(entityId);\n\t}\n\n\tgetEntity(entityId: number): Entity<ComponentTypes> | undefined {\n\t\treturn this.entities.get(entityId);\n\t}\n}\n",
6
6
  "import type { EventHandler } from \"./types\";\n\nexport default\nclass EventBus<EventTypes> {\n\tprivate handlers: Map<keyof EventTypes, Array<EventHandler<any>>> = new Map();\n\n\t/**\n\t * Subscribe to an event\n\t */\n\tsubscribe<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[E]) => void\n\t): () => void {\n\t\treturn this.addHandler(eventType, callback, false);\n\t}\n\n\t/**\n\t * Subscribe to an event once\n\t */\n\tonce<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[E]) => void\n\t): () => void {\n\t\treturn this.addHandler(eventType, callback, true);\n\t}\n\n\t/**\n\t * Internal method to add an event handler\n\t */\n\tprivate addHandler<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[E]) => void,\n\t\tonce: boolean\n\t): () => void {\n\t\tif (!this.handlers.has(eventType)) {\n\t\t\tthis.handlers.set(eventType, []);\n\t\t}\n\n\t\tconst handler: EventHandler<EventTypes[E]> = {\n\t\t\tcallback,\n\t\t\tonce\n\t\t};\n\n\t\tthis.handlers.get(eventType)!.push(handler);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tconst handlers = this.handlers.get(eventType);\n\t\t\tif (handlers) {\n\t\t\t\tconst index = handlers.indexOf(handler);\n\t\t\t\tif (index !== -1) {\n\t\t\t\t\thandlers.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tpublish<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tdata: EventTypes[E] = undefined as EventTypes[E]\n\t): void {\n\t\tconst handlers = this.handlers.get(eventType);\n\t\tif (!handlers) return;\n\n\t\t// Create a copy of handlers to avoid issues with handlers that modify the array\n\t\tconst handlersToCall = [...handlers];\n\t\t\n\t\t// Call all handlers and collect handlers to remove\n\t\tconst handlersToRemove: EventHandler<any>[] = [];\n\t\t\n\t\tfor (const handler of handlersToCall) {\n\t\t\thandler.callback(data);\n\t\t\tif (handler.once) {\n\t\t\t\thandlersToRemove.push(handler);\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (handlersToRemove.length > 0) {\n\t\t\tfor (const handler of handlersToRemove) {\n\t\t\t\tconst index = handlers.indexOf(handler);\n\t\t\t\tif (index !== -1) {\n\t\t\t\t\thandlers.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tclear(): void {\n\t\tthis.handlers.clear();\n\t}\n\n\tclearEvent<E extends keyof EventTypes>(eventType: E): void {\n\t\tthis.handlers.delete(eventType);\n\t}\n}\n",
7
- "export default\nclass ResourceManager<ResourceTypes extends Record<string, any> = Record<string, any>> {\n\tprivate resources: Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]> = new Map();\n\n\t/**\n\t * Add a resource to the manager\n\t * @param label The resource key\n\t * @param resource The resource value\n\t * @returns The added resource\n\t */\n\tadd<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K]): ResourceTypes[K] {\n\t\tthis.resources.set(label, resource);\n\t\treturn resource;\n\t}\n\n\t/**\n\t * Get a resource from the manager\n\t * @param label The resource key\n\t * @returns The resource value\n\t * @throws Error if resource not found\n\t */\n\tget<K extends keyof ResourceTypes>(label: K): ResourceTypes[K] {\n\t\tconst resource = this.resources.get(label);\n\t\tif (resource === undefined) {\n\t\t\tthrow new Error(`Resource ${String(label)} not found`);\n\t\t}\n\t\treturn resource as ResourceTypes[K];\n\t}\n\n\t/**\n\t * Get a resource from the manager, returning undefined if not found\n\t * @param label The resource key\n\t * @returns The resource value or undefined if not found\n\t */\n\tgetOptional<K extends keyof ResourceTypes>(label: K): ResourceTypes[K] | undefined {\n\t\tconst resource = this.resources.get(label);\n\t\treturn resource as ResourceTypes[K] | undefined;\n\t}\n\n\t/**\n\t * Check if a resource exists\n\t * @param label The resource key\n\t * @returns True if the resource exists\n\t */\n\thas<K extends keyof ResourceTypes>(label: K): boolean {\n\t\treturn this.resources.has(label);\n\t}\n\n\t/**\n\t * Remove a resource\n\t * @param label The resource key\n\t * @returns True if the resource was removed\n\t */\n\tremove<K extends keyof ResourceTypes>(label: K): boolean {\n\t\treturn this.resources.delete(label);\n\t}\n\n\t/**\n\t * Get all resource keys\n\t * @returns Array of resource keys\n\t */\n\tgetKeys(): Array<keyof ResourceTypes> {\n\t\treturn Array.from(this.resources.keys());\n\t}\n}\n",
8
- "import EntityManager from \"./entity-manager\";\nimport EventBus from \"./event-bus\";\nimport ResourceManager from \"./resource-manager\";\nimport type { System } from \"./types\";\nimport type Bundle from \"./bundle\";\nimport { version } from \"../package.json\";\n\n\nexport default\nclass ECSpresso<\n\tComponentTypes extends Record<string, any> = Record<string, any>,\n\tEventTypes extends Record<string, any> = Record<string, any>,\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n> {\n\tpublic static readonly VERSION = version;\n\tprivate _entityManager: EntityManager<ComponentTypes>;\n\tprivate _systems: System<ComponentTypes, any, any, EventTypes, ResourceTypes>[] = [];\n\tprivate _eventBus: EventBus<EventTypes>;\n\tprivate _resourceManager: ResourceManager<ResourceTypes>;\n\tprivate _installedBundles: Set<string> = new Set();\n\n\tconstructor() {\n\t\tthis._entityManager = new EntityManager<ComponentTypes>();\n\t\tthis._eventBus = new EventBus<EventTypes>();\n\t\tthis._resourceManager = new ResourceManager<ResourceTypes>();\n\t}\n\n\t/**\n\t * Install one or more bundles into this ECS instance\n\t */\n\tinstall<\n\t\tBundles extends Array<Bundle<any, any, any>>\n\t>(...bundles: Bundles): this {\n\t\tfor (const bundle of bundles) {\n\t\t\t// Check if this bundle is already installed\n\t\t\tif (this._installedBundles.has(bundle.id)) {\n\t\t\t\tconsole.warn(`Bundle ${bundle.id} is already installed`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst systems = bundle.getSystems();\n\n\t\t\t// Check if bundle has systems\n\t\t\tif (!systems.length) {\n\t\t\t\tconsole.warn(`Bundle ${bundle.id} has no systems`);\n\t\t\t}\n\n\t\t\t// Register all systems from the bundle\n\t\t\tfor (const system of systems) {\n\t\t\t\t// Need to cast here because we can't fully type the system generics\n\t\t\t\tconst typedSystem = system as unknown as System<ComponentTypes, any, any, EventTypes, ResourceTypes>;\n\t\t\t\tthis._systems.push(typedSystem);\n\n\t\t\t\t// Call onAttach lifecycle hook if defined\n\t\t\t\tif (typedSystem.onAttach) {\n\t\t\t\t\ttypedSystem.onAttach(\n\t\t\t\t\t\tthis._entityManager,\n\t\t\t\t\t\tthis._resourceManager,\n\t\t\t\t\t\tthis._eventBus\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Auto-subscribe to events if eventHandlers are defined\n\t\t\t\tif (typedSystem.eventHandlers) {\n\t\t\t\t\tfor (const eventName in typedSystem.eventHandlers) {\n\t\t\t\t\t\tconst handler = typedSystem.eventHandlers[eventName];\n\t\t\t\t\t\tif (handler?.handler) {\n\t\t\t\t\t\t\t// Create a wrapper that passes the additional parameters to the handler\n\t\t\t\t\t\t\tconst wrappedHandler = (data: any) => {\n\t\t\t\t\t\t\t\thandler.handler(\n\t\t\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t\t\t\tthis._entityManager,\n\t\t\t\t\t\t\t\t\tthis._resourceManager,\n\t\t\t\t\t\t\t\t\tthis._eventBus\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tthis._eventBus.subscribe(eventName, wrappedHandler);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Register all resources from the bundle\n\t\t\tconst resources = bundle.getResources();\n\t\t\tfor (const [key, value] of resources.entries()) {\n\t\t\t\t// We need to cast here because TypeScript can't verify the type compatibility\n\t\t\t\t// between bundles, but we trust that the bundle's resource types are compatible\n\t\t\t\tthis._resourceManager.add(key as unknown as keyof ResourceTypes, value as any);\n\t\t\t}\n\n\t\t\t// Mark this bundle as installed\n\t\t\tthis._installedBundles.add(bundle.id);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Remove a system by its label\n\t */\n\tremoveSystem(label: string): boolean {\n\t\tconst index = this._systems.findIndex(system => system.label === label);\n\t\tif (index === -1) return false;\n\n\t\tconst system = this._systems[index];\n\t\tif (!system) return false;\n\n\t\tsystem.onDetach?.(\n\t\t\tthis._entityManager,\n\t\t\tthis._resourceManager,\n\t\t\tthis._eventBus\n\t\t);\n\n\t\t// Remove system\n\t\tthis._systems.splice(index, 1);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Check if a resource exists\n\t */\n\thasResource<K extends keyof ResourceTypes>(key: K): boolean {\n\t\treturn this._resourceManager.has(key);\n\t}\n\n\t/**\n\t * Get a resource if it exists, or undefined if not\n\t */\n\tgetResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] | undefined {\n\t\treturn this._resourceManager.getOptional(key);\n\t}\n\n\t/**\n\t * Get a resource, throws error if not found\n\t */\n\tgetResourceOrThrow<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] {\n\t\treturn this._resourceManager.get(key);\n\t}\n\n\t/**\n\t * Add a resource to the ECS instance\n\t */\n\taddResource<K extends keyof ResourceTypes>(key: K, resource: ResourceTypes[K]): this {\n\t\tthis._resourceManager.add(key, resource);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Check if an entity has a component\n\t */\n\thasComponent<K extends keyof ComponentTypes>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): boolean {\n\t\tconst component = this._entityManager.getComponent(entityId, componentName);\n\t\treturn component !== null;\n\t}\n\n\t/**\n\t * Get all entities with specific components\n\t */\n\tgetEntitiesWithComponents(\n\t\twithComponents: (keyof ComponentTypes)[],\n\t\twithoutComponents: (keyof ComponentTypes)[] = []\n\t) {\n\t\treturn this._entityManager.getEntitiesWithComponents(\n\t\t\twithComponents,\n\t\t\twithoutComponents\n\t\t);\n\t}\n\n\t/**\n\t * Update all systems\n\t */\n\tupdate(deltaTime: number) {\n\t\tfor (const system of this._systems) {\n\t\t\tif (!system.process) continue;\n\n\t\t\t// Prepare query results\n\t\t\tconst queryResults: Record<string, any[]> = {};\n\n\t\t\t// Process entity queries if defined\n\t\t\tif (system.entityQueries) {\n\t\t\t\tfor (const queryName in system.entityQueries) {\n\t\t\t\t\tconst query = system.entityQueries[queryName];\n\t\t\t\t\tif (query) {\n\t\t\t\t\t\tqueryResults[queryName] = this._entityManager.getEntitiesWithComponents(\n\t\t\t\t\t\t\tquery.with,\n\t\t\t\t\t\t\tquery.without || []\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Call the system's process method\n\t\t\t\tsystem.process(\n\t\t\t\t\tqueryResults,\n\t\t\t\t\tdeltaTime,\n\t\t\t\t\tthis._entityManager,\n\t\t\t\t\tthis._resourceManager,\n\t\t\t\t\tthis._eventBus\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// No queries defined, pass an empty array\n\t\t\t\tsystem.process(\n\t\t\t\t\t[],\n\t\t\t\t\tdeltaTime,\n\t\t\t\t\tthis._entityManager,\n\t\t\t\t\tthis._resourceManager,\n\t\t\t\t\tthis._eventBus\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Getters for the internal managers\n\tget entityManager() {\n\t\treturn this._entityManager;\n\t}\n\n\tget eventBus() {\n\t\treturn this._eventBus;\n\t}\n\n\tget resourceManager() {\n\t\treturn this._resourceManager;\n\t}\n\n\t/**\n\t * Get all installed bundle IDs\n\t */\n\tget installedBundles(): string[] {\n\t\treturn Array.from(this._installedBundles);\n\t}\n}\n",
7
+ "export default\nclass ResourceManager<ResourceTypes extends Record<string, any> = Record<string, any>> {\n\tprivate resources: Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]> = new Map();\n\n\t/**\n\t * Add a resource to the manager\n\t * @param label The resource key\n\t * @param resource The resource value\n\t * @returns The resource manager instance for chaining\n\t */\n\tadd<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K]) {\n\t\tthis.resources.set(label, resource);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get a resource from the manager\n\t * @param label The resource key\n\t * @returns The resource value\n\t * @throws Error if resource not found\n\t */\n\tget<K extends keyof ResourceTypes>(label: K): ResourceTypes[K] {\n\t\tconst resource = this.resources.get(label);\n\n\t\tif (resource === undefined) {\n\t\t\tthrow new Error(`Resource ${String(label)} not found`);\n\t\t}\n\n\t\treturn resource;\n\t}\n\n\t/**\n\t * Get a resource from the manager, returning undefined if not found\n\t * @param label The resource key\n\t * @returns The resource value or undefined if not found\n\t */\n\tgetOptional<K extends keyof ResourceTypes>(label: K): ResourceTypes[K] | undefined {\n\t\tconst resource = this.resources.get(label);\n\t\treturn resource as ResourceTypes[K] | undefined;\n\t}\n\n\t/**\n\t * Check if a resource exists\n\t * @param label The resource key\n\t * @returns True if the resource exists\n\t */\n\thas<K extends keyof ResourceTypes>(label: K): boolean {\n\t\treturn this.resources.has(label);\n\t}\n\n\t/**\n\t * Remove a resource\n\t * @param label The resource key\n\t * @returns True if the resource was removed\n\t */\n\tremove<K extends keyof ResourceTypes>(label: K): boolean {\n\t\treturn this.resources.delete(label);\n\t}\n\n\t/**\n\t * Get all resource keys\n\t * @returns Array of resource keys\n\t */\n\tgetKeys(): Array<keyof ResourceTypes> {\n\t\treturn Array.from(this.resources.keys());\n\t}\n}\n",
8
+ "import EntityManager from \"./entity-manager\";\nimport EventBus from \"./event-bus\";\nimport ResourceManager from \"./resource-manager\";\nimport type { System } from \"./types\";\nimport type Bundle from \"./bundle\";\nimport { version } from \"../package.json\";\n\n\n/**\n * The main ECS (Entity Component System) container class\n *\n * This class manages entities, components, systems, resources, and events.\n *\n * Systems interact with the ECS through a single parameter that provides access\n * to the entire ECSpresso instance. This provides a simplified API for systems\n * and allows them access to all ECS functionality through a single reference.\n *\n * @template ComponentTypes Record of component types used in this ECS instance\n * @template EventTypes Record of event types used in this ECS instance\n * @template ResourceTypes Record of resource types used in this ECS instance\n */\nexport default\nclass ECSpresso<\n\tComponentTypes extends Record<string, any> = Record<string, any>,\n\tEventTypes extends Record<string, any> = Record<string, any>,\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n> {\n\tpublic static readonly VERSION = version;\n\tprivate _entityManager: EntityManager<ComponentTypes>;\n\tprivate _systems: System<ComponentTypes, any, any, EventTypes, ResourceTypes>[] = [];\n\tprivate _eventBus: EventBus<EventTypes>;\n\tprivate _resourceManager: ResourceManager<ResourceTypes>;\n\tprivate _installedBundles: Set<string> = new Set();\n\n\tconstructor() {\n\t\tthis._entityManager = new EntityManager<ComponentTypes>();\n\t\tthis._eventBus = new EventBus<EventTypes>();\n\t\tthis._resourceManager = new ResourceManager<ResourceTypes>();\n\t}\n\n\t/**\n\t * Install one or more bundles into this ECS instance\n\t * Systems in the bundle will have their onAttach method called with this ECSpresso instance\n\t * @param bundles One or more bundles to install\n\t * @returns This ECSpresso instance for method chaining\n\t */\n\tinstall<\n\t\tBundles extends Array<Bundle<any, any, any>>\n\t>(...bundles: Bundles): this {\n\t\tfor (const bundle of bundles) {\n\t\t\t// Check if this bundle is already installed\n\t\t\tif (this._installedBundles.has(bundle.id)) {\n\t\t\t\tconsole.warn(`Bundle ${bundle.id} is already installed`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst systems = bundle.getSystems();\n\n\t\t\t// Check if bundle has systems\n\t\t\tif (!systems.length) {\n\t\t\t\tconsole.warn(`Bundle ${bundle.id} has no systems`);\n\t\t\t}\n\n\t\t\t// Register all systems from the bundle\n\t\t\tfor (const system of systems) {\n\t\t\t\t// Need to cast here because we can't fully type the system generics\n\t\t\t\tconst typedSystem = system as unknown as System<ComponentTypes, any, any, EventTypes, ResourceTypes>;\n\t\t\t\tthis._systems.push(typedSystem);\n\n\t\t\t\t// Call onAttach lifecycle hook if defined\n\t\t\t\tif (typedSystem.onAttach) {\n\t\t\t\t\ttypedSystem.onAttach(\n\t\t\t\t\t\tthis\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Auto-subscribe to events if eventHandlers are defined\n\t\t\t\tif (typedSystem.eventHandlers) {\n\t\t\t\t\tfor (const eventName in typedSystem.eventHandlers) {\n\t\t\t\t\t\tconst handler = typedSystem.eventHandlers[eventName];\n\t\t\t\t\t\tif (handler?.handler) {\n\t\t\t\t\t\t\t// Create a wrapper that passes the additional parameters to the handler\n\t\t\t\t\t\t\tconst wrappedHandler = (data: any) => {\n\t\t\t\t\t\t\t\thandler.handler(\n\t\t\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t\t\t\tthis\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tthis._eventBus.subscribe(eventName, wrappedHandler);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Register all resources from the bundle\n\t\t\tconst resources = bundle.getResources();\n\t\t\tfor (const [key, value] of resources.entries()) {\n\t\t\t\t// We need to cast here because TypeScript can't verify the type compatibility\n\t\t\t\t// between bundles, but we trust that the bundle's resource types are compatible\n\t\t\t\tthis._resourceManager.add(key as unknown as keyof ResourceTypes, value as any);\n\t\t\t}\n\n\t\t\t// Mark this bundle as installed\n\t\t\tthis._installedBundles.add(bundle.id);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Remove a system by its label\n\t * Calls the system's onDetach method with this ECSpresso instance if defined\n\t * @param label The unique label of the system to remove\n\t * @returns true if the system was found and removed, false otherwise\n\t */\n\tremoveSystem(label: string): boolean {\n\t\tconst index = this._systems.findIndex(system => system.label === label);\n\t\tif (index === -1) return false;\n\n\t\tconst system = this._systems[index];\n\t\tif (!system) return false;\n\n\t\tsystem.onDetach?.(\n\t\t\tthis\n\t\t);\n\n\t\t// Remove system\n\t\tthis._systems.splice(index, 1);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Check if a resource exists\n\t */\n\thasResource<K extends keyof ResourceTypes>(key: K): boolean {\n\t\treturn this._resourceManager.has(key);\n\t}\n\n\t/**\n\t * Get a resource if it exists, or undefined if not\n\t */\n\tgetResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] | undefined {\n\t\treturn this._resourceManager.getOptional(key);\n\t}\n\n\t/**\n\t * Get a resource, throws error if not found\n\t */\n\tgetResourceOrThrow<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] {\n\t\treturn this._resourceManager.get(key);\n\t}\n\n\t/**\n\t * Add a resource to the ECS instance\n\t */\n\taddResource<K extends keyof ResourceTypes>(key: K, resource: ResourceTypes[K]): this {\n\t\tthis._resourceManager.add(key, resource);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Check if an entity has a component\n\t */\n\thasComponent<K extends keyof ComponentTypes>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): boolean {\n\t\tconst component = this._entityManager.getComponent(entityId, componentName);\n\t\treturn component !== null;\n\t}\n\n\t/**\n\t * Get all entities with specific components\n\t */\n\tgetEntitiesWithComponents(\n\t\twithComponents: (keyof ComponentTypes)[],\n\t\twithoutComponents: (keyof ComponentTypes)[] = []\n\t) {\n\t\treturn this._entityManager.getEntitiesWithComponents(\n\t\t\twithComponents,\n\t\t\twithoutComponents\n\t\t);\n\t}\n\n\t/**\n\t * Update all systems\n\t * Calls each system's process method with this ECSpresso instance\n\t * @param deltaTime Time elapsed since the last update in seconds\n\t */\n\tupdate(deltaTime: number) {\n\t\tfor (const system of this._systems) {\n\t\t\tif (!system.process) continue;\n\n\t\t\t// Prepare query results\n\t\t\tconst queryResults: Record<string, any[]> = {};\n\n\t\t\t// Process entity queries if defined\n\t\t\tif (system.entityQueries) {\n\t\t\t\tfor (const queryName in system.entityQueries) {\n\t\t\t\t\tconst query = system.entityQueries[queryName];\n\t\t\t\t\tif (query) {\n\t\t\t\t\t\tqueryResults[queryName] = this._entityManager.getEntitiesWithComponents(\n\t\t\t\t\t\t\tquery.with,\n\t\t\t\t\t\t\tquery.without || []\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Call the system's process method\n\t\t\t\tsystem.process(\n\t\t\t\t\tqueryResults,\n\t\t\t\t\tdeltaTime,\n\t\t\t\t\tthis\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// No queries defined, pass an empty array\n\t\t\t\tsystem.process(\n\t\t\t\t\t[],\n\t\t\t\t\tdeltaTime,\n\t\t\t\t\tthis\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Getters for the internal managers\n\tget entityManager() {\n\t\treturn this._entityManager;\n\t}\n\n\tget eventBus() {\n\t\treturn this._eventBus;\n\t}\n\n\tget resourceManager() {\n\t\treturn this._resourceManager;\n\t}\n\n\t/**\n\t * Get all installed bundle IDs\n\t */\n\tget installedBundles(): string[] {\n\t\treturn Array.from(this._installedBundles);\n\t}\n}\n",
9
9
  "import { SystemBuilder } from './system-builder';\n\n/**\n * Generates a unique ID for a bundle\n */\nfunction generateBundleId(): string {\n\treturn `bundle_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Bundle class that encapsulates a set of components, resources, events, and systems\n * that can be merged into a ECSpresso instance\n */\nexport default class Bundle<\n\tComponentTypes extends Record<string, any> = Record<string, any>,\n\tEventTypes extends Record<string, any> = Record<string, any>,\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n> {\n\tprivate _systems: SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, any>[] = [];\n\tprivate _resources: Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]> = new Map();\n\tprivate _id: string;\n\n\tconstructor(id?: string) {\n\t\tthis._id = id || generateBundleId();\n\t}\n\n\t/**\n\t * Get the unique ID of this bundle\n\t */\n\tget id(): string {\n\t\treturn this._id;\n\t}\n\n\t/**\n\t * Set the ID of this bundle\n\t * @internal Used by combineBundles\n\t */\n\tset id(value: string) {\n\t\tthis._id = value;\n\t}\n\n\t/**\n\t * Add a system to this bundle\n\t */\n\taddSystem(label: string) {\n\t\tconst system = new SystemBuilder(label, this);\n\n\t\tthis._systems.push(system);\n\n\t\treturn system;\n\t}\n\n\t/**\n\t * Add a resource to this bundle\n\t * @param label The resource key\n\t * @param resource The resource value\n\t */\n\taddResource<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K]) {\n\t\tthis._resources.set(label, resource);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get all systems defined in this bundle\n\t * Returns built System objects instead of SystemBuilders\n\t */\n\tgetSystems() {\n\t\treturn this._systems.map(system => system.build());\n\t}\n\n\t/**\n\t * Get all resources defined in this bundle\n\t */\n\tgetResources(): Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]> {\n\t\treturn new Map(this._resources);\n\t}\n\n\t/**\n\t * Get a specific resource by key\n\t * @param key The resource key\n\t * @returns The resource value or undefined if not found\n\t */\n\tgetResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] | undefined {\n\t\treturn this._resources.get(key) as ResourceTypes[K] | undefined;\n\t}\n\n\t/**\n\t * Get all system builders in this bundle\n\t */\n\tgetSystemBuilders(): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, any>[] {\n\t\treturn [...this._systems];\n\t}\n\n\t/**\n\t * Check if this bundle has a specific resource\n\t * @param key The resource key to check\n\t * @returns True if the resource exists\n\t */\n\thasResource<K extends keyof ResourceTypes>(key: K): boolean {\n\t\treturn this._resources.has(key);\n\t}\n}\n\n/**\n * Utility type for merging two types\n */\n// This sets props with the same name but different type to \"never\". Maybe we want this?\nexport type Merge<T1, T2> = T1 & T2;\n// This makes the later prop types override the earlier ones. Maybe we want this instead?\n// export type Merge<T1, T2> = Omit<T1, keyof T2> & T2;\n// Or maybe this, which sets props with the same name to a union of the two types\n// export type Merge<T1, T2> = {\n// \t[K in keyof T1 | keyof T2]: K extends keyof T1 & keyof T2\n// \t\t? T1[K] | T2[K]\n// \t\t: K extends keyof T1\n// \t\t\t? T1[K]\n// \t\t\t: K extends keyof T2\n// \t\t\t\t? T2[K]\n// \t\t\t\t: never;\n// };\n\nexport type MergeAll<T extends any[]> = T extends [infer First, ...infer Rest] ?\n\tRest extends [] ?\n\t\tFirst: Merge<First, MergeAll<Rest>>:\n\t{};\n\nexport function mergeBundles<\n\tBundles extends Array<Bundle<any, any, any>>\n>(\n\tid: string,\n\t...bundles: Bundles\n): Bundle<\n\tMergeAll<{ [K in keyof Bundles]: Bundles[K] extends Bundle<infer C, any, any> ? C : never }>,\n\tMergeAll<{ [K in keyof Bundles]: Bundles[K] extends Bundle<any, infer E, any> ? E : never }>,\n\tMergeAll<{ [K in keyof Bundles]: Bundles[K] extends Bundle<any, any, infer R> ? R : never }>\n> {\n\tif (bundles.length === 0) {\n\t\treturn new Bundle(id);\n\t}\n\n\tconst combined = new Bundle(id);\n\n\tfor (const bundle of bundles) {\n\t\tfor (const system of bundle.getSystemBuilders()) {\n\t\t\tcombined.addSystem(system as any);\n\t\t}\n\n\t\t// Add resources from this bundle\n\t\tfor (const [label, resource] of bundle.getResources().entries()) {\n\t\t\tcombined.addResource(label as any, resource);\n\t\t}\n\t}\n\n\treturn combined as any;\n}\n",
10
- "import Bundle from \"./bundle\";\nimport type EntityManager from \"./entity-manager\";\nimport type EventBus from \"./event-bus\";\nimport type ResourceManager from \"./resource-manager\";\nimport type { FilteredEntity, System } from \"./types\";\n\n/**\n * Builder class for creating type-safe ECS Systems with proper query inference\n */\nexport class SystemBuilder<\n\tComponentTypes extends Record<string, any> = Record<string, any>,\n\tEventTypes extends Record<string, any> = Record<string, any>,\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>> = {},\n> {\n\tprivate queries: Queries = {} as Queries;\n\tprivate processFunction?: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>;\n\tprivate attachFunction?: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>;\n\tprivate detachFunction?: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>;\n\tprivate eventHandlers?: {\n\t\t[EventName in keyof EventTypes]?: {\n\t\t\thandler(\n\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\tentityManager: EntityManager<ComponentTypes>,\n\t\t\t\tresourceManager: ResourceManager<ResourceTypes>,\n\t\t\t\teventBus: EventBus<EventTypes>,\n\t\t\t): void;\n\t\t};\n\t};\n\n\tconstructor(\n\t\tprivate _label: string,\n\t\tprivate _bundle = new Bundle<ComponentTypes, EventTypes, ResourceTypes>()\n\t) {}\n\n\tget label() {\n\t\treturn this._label;\n\t}\n\n\tget bundle() {\n\t\treturn this._bundle;\n\t}\n\n\t/**\n\t * Add a query definition to the system\n\t */\n\taddQuery<\n\t\tQueryName extends string,\n\t\tWithComponents extends keyof ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never,\n\t>(\n\t\tname: QueryName,\n\t\tdefinition: {\n\t\t\twith: ReadonlyArray<WithComponents>;\n\t\t\twithout?: ReadonlyArray<WithoutComponents>;\n\t\t}\n\t): SystemBuilder<\n\t\tComponentTypes,\n\t\tEventTypes,\n\t\tResourceTypes,\n\t\tQueries & Record<QueryName, QueryDefinition<ComponentTypes, WithComponents, WithoutComponents>>\n\t> {\n\t\t// Cast is needed because TypeScript can't preserve the type information\n\t\t// when modifying an object property\n\t\tconst newBuilder = this as any;\n\t\tnewBuilder.queries = {\n\t\t\t...this.queries,\n\t\t\t[name]: definition,\n\t\t};\n\t\treturn newBuilder;\n\t}\n\n\t/**\n\t * Set the system's process function that runs each update\n\t */\n\tsetProcess(\n\t\tprocess: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.processFunction = process;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set the onAttach lifecycle hook\n\t */\n\tsetOnAttach(\n\t\tonAttach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.attachFunction = onAttach;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set the onDetach lifecycle hook\n\t */\n\tsetOnDetach(\n\t\tonDetach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.detachFunction = onDetach;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set event handlers for the system\n\t */\n\tsetEventHandlers(\n\t\thandlers: {\n\t\t\t[EventName in keyof EventTypes]?: {\n\t\t\t\thandler(\n\t\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\t\tentityManager: EntityManager<ComponentTypes>,\n\t\t\t\t\tresourceManager: ResourceManager<ResourceTypes>,\n\t\t\t\t\teventBus: EventBus<EventTypes>,\n\t\t\t\t): void;\n\t\t\t};\n\t\t}\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.eventHandlers = handlers;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Build the final system object\n\t */\n\tbuild(): System<ComponentTypes, any, any, EventTypes, ResourceTypes> {\n\t\tconst system: System<ComponentTypes, any, any, EventTypes, ResourceTypes> = {\n\t\t\tlabel: this._label,\n\t\t\tentityQueries: this.queries as any,\n\t\t};\n\n\t\tif (this.processFunction) {\n\t\t\tsystem.process = this.processFunction as any;\n\t\t}\n\n\t\tif (this.attachFunction) {\n\t\t\tsystem.onAttach = this.attachFunction;\n\t\t}\n\n\t\tif (this.detachFunction) {\n\t\t\tsystem.onDetach = this.detachFunction;\n\t\t}\n\n\t\tif (this.eventHandlers) {\n\t\t\tsystem.eventHandlers = this.eventHandlers;\n\t\t}\n\n\t\treturn system;\n\t}\n}\n\n// Helper type definitions\ntype QueryDefinition<\n\tComponentTypes,\n\tWithComponents extends keyof ComponentTypes = any,\n\tWithoutComponents extends keyof ComponentTypes = any,\n> = {\n\twith: ReadonlyArray<WithComponents>;\n\twithout?: ReadonlyArray<WithoutComponents>;\n};\n\ntype QueryResults<\n\tComponentTypes,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>>,\n> = {\n\t[QueryName in keyof Queries]: QueryName extends string\n\t\t? FilteredEntity<\n\t\t\tComponentTypes,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, infer W, any> ? W : never,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO> ? WO : never\n\t\t>[]\n\t\t: never;\n};\n\ntype ProcessFunction<\n\tComponentTypes,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>>,\n> = (\n\tqueries: QueryResults<ComponentTypes, Queries>,\n\tdeltaTime: number,\n\tentityManager: EntityManager<ComponentTypes>,\n\tresourceManager: ResourceManager<ResourceTypes>,\n\teventBus: EventBus<EventTypes>,\n) => void;\n\ntype LifecycleFunction<\n\tComponentTypes,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n> = (\n\tentityManager: EntityManager<ComponentTypes>,\n\tresourceManager: ResourceManager<ResourceTypes>,\n\teventBus: EventBus<EventTypes>,\n) => void;\n\n// // Factory function for easier creation\n// function createSystem<\n// \tComponentTypes,\n// \tEventTypes = any,\n// \tResourceTypes = any\n// >(\n// \tlabel: string\n// ): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes> {\n// \treturn new SystemBuilder<ComponentTypes, EventTypes, ResourceTypes>(label);\n// }\n",
10
+ "import Bundle from \"./bundle\";\nimport type { FilteredEntity, System } from \"./types\";\n\n/**\n * Builder class for creating type-safe ECS Systems with proper query inference\n */\nexport class SystemBuilder<\n\tComponentTypes extends Record<string, any> = Record<string, any>,\n\tEventTypes extends Record<string, any> = Record<string, any>,\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>> = {},\n> {\n\tprivate queries: Queries = {} as Queries;\n\tprivate processFunction?: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>;\n\tprivate attachFunction?: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>;\n\tprivate detachFunction?: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>;\n\tprivate eventHandlers?: {\n\t\t[EventName in keyof EventTypes]?: {\n\t\t\thandler(\n\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\tecs: import(\"./ecspresso\").default<\n\t\t\t\t\tComponentTypes & Record<string, any>,\n\t\t\t\t\tEventTypes,\n\t\t\t\t\tResourceTypes\n\t\t\t\t>\n\t\t\t): void;\n\t\t};\n\t};\n\n\tconstructor(\n\t\tprivate _label: string,\n\t\tprivate _bundle = new Bundle<ComponentTypes, EventTypes, ResourceTypes>()\n\t) {}\n\n\tget label() {\n\t\treturn this._label;\n\t}\n\n\tget bundle() {\n\t\treturn this._bundle;\n\t}\n\n\t/**\n\t * Add a query definition to the system\n\t */\n\taddQuery<\n\t\tQueryName extends string,\n\t\tWithComponents extends keyof ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never,\n\t>(\n\t\tname: QueryName,\n\t\tdefinition: {\n\t\t\twith: ReadonlyArray<WithComponents>;\n\t\t\twithout?: ReadonlyArray<WithoutComponents>;\n\t\t}\n\t): SystemBuilder<\n\t\tComponentTypes,\n\t\tEventTypes,\n\t\tResourceTypes,\n\t\tQueries & Record<QueryName, QueryDefinition<ComponentTypes, WithComponents, WithoutComponents>>\n\t> {\n\t\t// Cast is needed because TypeScript can't preserve the type information\n\t\t// when modifying an object property\n\t\tconst newBuilder = this as any;\n\t\tnewBuilder.queries = {\n\t\t\t...this.queries,\n\t\t\t[name]: definition,\n\t\t};\n\t\treturn newBuilder;\n\t}\n\n\t/**\n\t * Set the system's process function that runs each update\n\t * @param process Function to process entities matching the system's queries each update\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tsetProcess(\n\t\tprocess: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.processFunction = process;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set the onAttach lifecycle hook\n\t * Called when the system is attached to the ECS\n\t * @param onAttach Function to run when this system is attached to the ECS\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tsetOnAttach(\n\t\tonAttach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.attachFunction = onAttach;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set the onDetach lifecycle hook\n\t * Called when the system is removed from the ECS\n\t * @param onDetach Function to run when this system is detached from the ECS\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tsetOnDetach(\n\t\tonDetach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.detachFunction = onDetach;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set event handlers for the system\n\t * These handlers will be automatically subscribed when the system is attached\n\t * @param handlers Object mapping event names to handler functions\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tsetEventHandlers(\n\t\thandlers: {\n\t\t\t[EventName in keyof EventTypes]?: {\n\t\t\t\thandler(\n\t\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\t\tecs: import(\"./ecspresso\").default<\n\t\t\t\t\t\tComponentTypes & Record<string, any>,\n\t\t\t\t\t\tEventTypes,\n\t\t\t\t\t\tResourceTypes\n\t\t\t\t\t>\n\t\t\t\t): void;\n\t\t\t};\n\t\t}\n\t): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\t\tthis.eventHandlers = handlers;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Build the final system object\n\t */\n\tbuild(): System<ComponentTypes, any, any, EventTypes, ResourceTypes> {\n\t\tconst system: System<ComponentTypes, any, any, EventTypes, ResourceTypes> = {\n\t\t\tlabel: this._label,\n\t\t\tentityQueries: this.queries as any,\n\t\t};\n\n\t\tif (this.processFunction) {\n\t\t\tsystem.process = this.processFunction as any;\n\t\t}\n\n\t\tif (this.attachFunction) {\n\t\t\tsystem.onAttach = this.attachFunction;\n\t\t}\n\n\t\tif (this.detachFunction) {\n\t\t\tsystem.onDetach = this.detachFunction;\n\t\t}\n\n\t\tif (this.eventHandlers) {\n\t\t\tsystem.eventHandlers = this.eventHandlers;\n\t\t}\n\n\t\treturn system;\n\t}\n}\n\n// Helper type definitions\ntype QueryDefinition<\n\tComponentTypes,\n\tWithComponents extends keyof ComponentTypes = any,\n\tWithoutComponents extends keyof ComponentTypes = any,\n> = {\n\twith: ReadonlyArray<WithComponents>;\n\twithout?: ReadonlyArray<WithoutComponents>;\n};\n\ntype QueryResults<\n\tComponentTypes,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>>,\n> = {\n\t[QueryName in keyof Queries]: QueryName extends string\n\t\t? FilteredEntity<\n\t\t\tComponentTypes,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, infer W, any> ? W : never,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO> ? WO : never\n\t\t>[]\n\t\t: never;\n};\n\n/**\n * Function signature for system process methods\n * @param queries Results of entity queries defined by the system\n * @param deltaTime Time elapsed since last update in seconds\n * @param ecs The ECSpresso instance providing access to all ECS functionality\n */\ntype ProcessFunction<\n\tComponentTypes,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>>,\n> = (\n\tqueries: QueryResults<ComponentTypes, Queries>,\n\tdeltaTime: number,\n\tecs: import(\"./ecspresso\").default<\n\t\tComponentTypes & Record<string, any>,\n\t\tEventTypes,\n\t\tResourceTypes\n\t>\n) => void;\n\n/**\n * Function signature for system lifecycle hooks (onAttach and onDetach)\n * @param ecs The ECSpresso instance providing access to all ECS functionality\n */\ntype LifecycleFunction<\n\tComponentTypes,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n> = (\n\tecs: import(\"./ecspresso\").default<\n\t\tComponentTypes & Record<string, any>,\n\t\tEventTypes,\n\t\tResourceTypes\n\t>\n) => void;\n\n// // Factory function for easier creation\n// function createSystem<\n// \tComponentTypes,\n// \tEventTypes = any,\n// \tResourceTypes = any\n// >(\n// \tlabel: string\n// ): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes> {\n// \treturn new SystemBuilder<ComponentTypes, EventTypes, ResourceTypes>(label);\n// }\n",
11
11
  "import ECSpresso from './ecspresso';\nimport { SystemBuilder } from './system-builder';\nimport Bundle, { mergeBundles } from './bundle';\n\nexport * from './types';\nexport { default as EntityManager } from './entity-manager';\nexport { default as EventBus } from './event-bus';\nexport { default as ResourceManager } from './resource-manager';\nexport { SystemBuilder };\nexport { Bundle, mergeBundles };\nexport default ECSpresso;\n"
12
12
  ],
13
- "mappings": "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",
14
- "debugId": "281E4BB1A8D4F83A64756E2164756E21",
13
+ "mappings": "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",
14
+ "debugId": "D9F45C94B8DFE1F064756E2164756E21",
15
15
  "names": []
16
16
  }
@@ -0,0 +1,40 @@
1
+ export default class ResourceManager<ResourceTypes extends Record<string, any> = Record<string, any>> {
2
+ private resources;
3
+ /**
4
+ * Add a resource to the manager
5
+ * @param label The resource key
6
+ * @param resource The resource value
7
+ * @returns The resource manager instance for chaining
8
+ */
9
+ add<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K]): this;
10
+ /**
11
+ * Get a resource from the manager
12
+ * @param label The resource key
13
+ * @returns The resource value
14
+ * @throws Error if resource not found
15
+ */
16
+ get<K extends keyof ResourceTypes>(label: K): ResourceTypes[K];
17
+ /**
18
+ * Get a resource from the manager, returning undefined if not found
19
+ * @param label The resource key
20
+ * @returns The resource value or undefined if not found
21
+ */
22
+ getOptional<K extends keyof ResourceTypes>(label: K): ResourceTypes[K] | undefined;
23
+ /**
24
+ * Check if a resource exists
25
+ * @param label The resource key
26
+ * @returns True if the resource exists
27
+ */
28
+ has<K extends keyof ResourceTypes>(label: K): boolean;
29
+ /**
30
+ * Remove a resource
31
+ * @param label The resource key
32
+ * @returns True if the resource was removed
33
+ */
34
+ remove<K extends keyof ResourceTypes>(label: K): boolean;
35
+ /**
36
+ * Get all resource keys
37
+ * @returns Array of resource keys
38
+ */
39
+ getKeys(): Array<keyof ResourceTypes>;
40
+ }
@@ -0,0 +1,79 @@
1
+ import Bundle from "./bundle";
2
+ import type { FilteredEntity, System } from "./types";
3
+ /**
4
+ * Builder class for creating type-safe ECS Systems with proper query inference
5
+ */
6
+ export declare class SystemBuilder<ComponentTypes extends Record<string, any> = Record<string, any>, EventTypes extends Record<string, any> = Record<string, any>, ResourceTypes extends Record<string, any> = Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>> = {}> {
7
+ private _label;
8
+ private _bundle;
9
+ private queries;
10
+ private processFunction?;
11
+ private attachFunction?;
12
+ private detachFunction?;
13
+ private eventHandlers?;
14
+ constructor(_label: string, _bundle?: Bundle<ComponentTypes, EventTypes, ResourceTypes>);
15
+ get label(): string;
16
+ get bundle(): Bundle<ComponentTypes, EventTypes, ResourceTypes>;
17
+ /**
18
+ * Add a query definition to the system
19
+ */
20
+ addQuery<QueryName extends string, WithComponents extends keyof ComponentTypes, WithoutComponents extends keyof ComponentTypes = never>(name: QueryName, definition: {
21
+ with: ReadonlyArray<WithComponents>;
22
+ without?: ReadonlyArray<WithoutComponents>;
23
+ }): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries & Record<QueryName, QueryDefinition<ComponentTypes, WithComponents, WithoutComponents>>>;
24
+ /**
25
+ * Set the system's process function that runs each update
26
+ * @param process Function to process entities matching the system's queries each update
27
+ * @returns This SystemBuilder instance for method chaining
28
+ */
29
+ setProcess(process: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries>;
30
+ /**
31
+ * Set the onAttach lifecycle hook
32
+ * Called when the system is attached to the ECS
33
+ * @param onAttach Function to run when this system is attached to the ECS
34
+ * @returns This SystemBuilder instance for method chaining
35
+ */
36
+ setOnAttach(onAttach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries>;
37
+ /**
38
+ * Set the onDetach lifecycle hook
39
+ * Called when the system is removed from the ECS
40
+ * @param onDetach Function to run when this system is detached from the ECS
41
+ * @returns This SystemBuilder instance for method chaining
42
+ */
43
+ setOnDetach(onDetach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries>;
44
+ /**
45
+ * Set event handlers for the system
46
+ * These handlers will be automatically subscribed when the system is attached
47
+ * @param handlers Object mapping event names to handler functions
48
+ * @returns This SystemBuilder instance for method chaining
49
+ */
50
+ setEventHandlers(handlers: {
51
+ [EventName in keyof EventTypes]?: {
52
+ handler(data: EventTypes[EventName], ecs: import("./ecspresso").default<ComponentTypes & Record<string, any>, EventTypes, ResourceTypes>): void;
53
+ };
54
+ }): SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries>;
55
+ /**
56
+ * Build the final system object
57
+ */
58
+ build(): System<ComponentTypes, any, any, EventTypes, ResourceTypes>;
59
+ }
60
+ type QueryDefinition<ComponentTypes, WithComponents extends keyof ComponentTypes = any, WithoutComponents extends keyof ComponentTypes = any> = {
61
+ with: ReadonlyArray<WithComponents>;
62
+ without?: ReadonlyArray<WithoutComponents>;
63
+ };
64
+ type QueryResults<ComponentTypes, Queries extends Record<string, QueryDefinition<ComponentTypes>>> = {
65
+ [QueryName in keyof Queries]: QueryName extends string ? FilteredEntity<ComponentTypes, Queries[QueryName] extends QueryDefinition<ComponentTypes, infer W, any> ? W : never, Queries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO> ? WO : never>[] : never;
66
+ };
67
+ /**
68
+ * Function signature for system process methods
69
+ * @param queries Results of entity queries defined by the system
70
+ * @param deltaTime Time elapsed since last update in seconds
71
+ * @param ecs The ECSpresso instance providing access to all ECS functionality
72
+ */
73
+ type ProcessFunction<ComponentTypes, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>>> = (queries: QueryResults<ComponentTypes, Queries>, deltaTime: number, ecs: import("./ecspresso").default<ComponentTypes & Record<string, any>, EventTypes, ResourceTypes>) => void;
74
+ /**
75
+ * Function signature for system lifecycle hooks (onAttach and onDetach)
76
+ * @param ecs The ECSpresso instance providing access to all ECS functionality
77
+ */
78
+ type LifecycleFunction<ComponentTypes, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>> = (ecs: import("./ecspresso").default<ComponentTypes & Record<string, any>, EventTypes, ResourceTypes>) => void;
79
+ export {};
@@ -0,0 +1,56 @@
1
+ export interface Entity<ComponentTypes> {
2
+ id: number;
3
+ components: Partial<ComponentTypes>;
4
+ }
5
+ export interface EventHandler<T> {
6
+ callback: (data: T) => void;
7
+ once: boolean;
8
+ }
9
+ export interface FilteredEntity<ComponentTypes, WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never> {
10
+ id: number;
11
+ components: Omit<Partial<ComponentTypes>, WithoutComponents> & {
12
+ [ComponentName in WithComponents]: ComponentTypes[ComponentName];
13
+ };
14
+ }
15
+ export interface QueryConfig<ComponentTypes, WithComponents extends keyof ComponentTypes, WithoutComponents extends keyof ComponentTypes> {
16
+ with: ReadonlyArray<WithComponents>;
17
+ without?: ReadonlyArray<WithoutComponents>;
18
+ }
19
+ export interface System<ComponentTypes, WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never, EventTypes extends Record<string, any> = Record<string, any>, ResourceTypes extends Record<string, any> = Record<string, any>> {
20
+ label: string;
21
+ entityQueries?: {
22
+ [queryName: string]: QueryConfig<ComponentTypes, WithComponents, WithoutComponents>;
23
+ };
24
+ /**
25
+ * Process method that runs during each update cycle
26
+ * @param queries The entity queries results based on system's entityQueries definition
27
+ * @param deltaTime Time elapsed since the last update in seconds
28
+ * @param ecs The ECSpresso instance providing access to all ECS functionality
29
+ */
30
+ process?(queries: {
31
+ [queryName: string]: Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>;
32
+ } | Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>, deltaTime: number, ecs: import("./ecspresso").default<ComponentTypes & Record<string, any>, EventTypes, ResourceTypes>): void;
33
+ /**
34
+ * Lifecycle hook called when the system is attached to the ECS
35
+ * @param ecs The ECSpresso instance providing access to all ECS functionality
36
+ */
37
+ onAttach?(ecs: import("./ecspresso").default<ComponentTypes & Record<string, any>, EventTypes, ResourceTypes>): void;
38
+ /**
39
+ * Lifecycle hook called when the system is detached from the ECS
40
+ * @param ecs The ECSpresso instance providing access to all ECS functionality
41
+ */
42
+ onDetach?(ecs: import("./ecspresso").default<ComponentTypes & Record<string, any>, EventTypes, ResourceTypes>): void;
43
+ /**
44
+ * Event handlers for specific event types
45
+ */
46
+ eventHandlers?: {
47
+ [EventName in keyof EventTypes]?: {
48
+ /**
49
+ * Event handler function
50
+ * @param data The event data specific to this event type
51
+ * @param ecs The ECSpresso instance providing access to all ECS functionality
52
+ */
53
+ handler(data: EventTypes[EventName], ecs: import("./ecspresso").default<ComponentTypes & Record<string, any>, EventTypes, ResourceTypes>): void;
54
+ };
55
+ };
56
+ }
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "ecspresso",
3
- "version": "0.0.1",
4
- "main": "src/index.ts",
5
- "module": "src/index.ts",
3
+ "version": "0.0.3",
4
+ "main": "dist/index.js",
5
+ "module": "dist/index.js",
6
+ "types": "dist/index.d.ts",
6
7
  "description": "A minimal Entity-Component-System library for typescript and javascript.",
7
8
  "repository": {
8
9
  "type": "git",
@@ -29,10 +30,10 @@
29
30
  ],
30
31
  "scripts": {
31
32
  "build:clean": "rm -rf dist",
32
- "build:types": "bun tsc -p tsconfig.build.json",
33
- "build:ts": "bun build --target=browser --sourcemap=linked --minify --outdir=dist src/index.ts",
34
- "build": "bun build:clean && bun build:ts && bun build:types",
33
+ "build:ts": "bun tsc -p tsconfig.build.json",
34
+ "build:js": "bun build --target=browser --sourcemap=linked --minify --outdir=dist src/index.ts",
35
+ "build": "bun build:clean && bun build:ts && bun build:js",
35
36
  "prepublishOnly": "bun run build"
36
37
  },
37
38
  "type": "module"
38
- }
39
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/resource-manager.ts","../src/event-bus.ts","../src/types.ts","../src/entity-manager.ts","../src/system-builder.ts","../src/bundle.ts","../src/ecspresso.ts","../src/bundle.test.ts","../src/ecspresso.test.ts","../src/event-bus.test.ts","../src/index.ts","../src/resource-manager.test.ts","../src/system-builder.test.ts"],"names":[],"mappings":"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"}