iris-ecs 0.0.4 → 0.0.6

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/dist/query.d.ts CHANGED
@@ -1,13 +1,16 @@
1
- import type { EntityId } from "./encoding.js";
1
+ import type { EntityId, EntityWith } from "./encoding.js";
2
2
  import type { FilterMeta } from "./filters.js";
3
- import type { Observer } from "./observer.js";
4
3
  import type { World } from "./world.js";
4
+ /**
5
+ * Phantom brand for carrying guaranteed-present component types on QueryMeta.
6
+ */
7
+ declare const QUERY_COMPONENTS_BRAND: unique symbol;
5
8
  /**
6
9
  * Query metadata for registry caching.
7
10
  *
8
11
  * Stores required and excluded components with reference to underlying filter.
9
12
  */
10
- export type QueryMeta = {
13
+ export type QueryMeta<C extends EntityId = EntityId> = {
11
14
  /**
12
15
  * Required components.
13
16
  */
@@ -20,10 +23,6 @@ export type QueryMeta = {
20
23
  * Direct reference to underlying filter.
21
24
  */
22
25
  filter: FilterMeta;
23
- /**
24
- * Observer callback for filter destruction.
25
- */
26
- onFilterDestroy: Observer<"filterDestroyed">;
27
26
  /**
28
27
  * Components with added() modifier.
29
28
  */
@@ -36,19 +35,23 @@ export type QueryMeta = {
36
35
  * Per-system execution ticks for change detection: systemId -> tick.
37
36
  */
38
37
  lastTick: Map<string, number>;
38
+ /**
39
+ * Phantom field carrying guaranteed-present component types via contravariance.
40
+ */
41
+ readonly [QUERY_COMPONENTS_BRAND]: (c: C) => void;
39
42
  };
40
43
  export type ModifierType = "not" | "added" | "changed";
41
- export type NotModifier = {
44
+ export type NotModifier<C extends EntityId = EntityId> = {
42
45
  type: "not";
43
- componentId: EntityId;
46
+ componentId: C;
44
47
  };
45
- export type AddedModifier = {
48
+ export type AddedModifier<C extends EntityId = EntityId> = {
46
49
  type: "added";
47
- componentId: EntityId;
50
+ componentId: C;
48
51
  };
49
- export type ChangedModifier = {
52
+ export type ChangedModifier<C extends EntityId = EntityId> = {
50
53
  type: "changed";
51
- componentId: EntityId;
54
+ componentId: C;
52
55
  };
53
56
  export type QueryModifier = NotModifier | AddedModifier | ChangedModifier;
54
57
  /**
@@ -62,7 +65,7 @@ export type QueryModifier = NotModifier | AddedModifier | ChangedModifier;
62
65
  * queryEntities(world, [Position, not(Dead)], (entity) => { ... });
63
66
  * ```
64
67
  */
65
- export declare function not(componentId: EntityId): NotModifier;
68
+ export declare function not<C extends EntityId>(componentId: C): NotModifier<C>;
66
69
  /**
67
70
  * Create added modifier for change detection.
68
71
  *
@@ -74,7 +77,7 @@ export declare function not(componentId: EntityId): NotModifier;
74
77
  * @example
75
78
  * queryEntities(world, [added(Enemy)], (entity) => { ... });
76
79
  */
77
- export declare function added(componentId: EntityId): AddedModifier;
80
+ export declare function added<C extends EntityId>(componentId: C): AddedModifier<C>;
78
81
  /**
79
82
  * Create changed modifier for change detection.
80
83
  *
@@ -86,7 +89,11 @@ export declare function added(componentId: EntityId): AddedModifier;
86
89
  * @example
87
90
  * queryEntities(world, [changed(Health)], (entity) => { ... });
88
91
  */
89
- export declare function changed(componentId: EntityId): ChangedModifier;
92
+ export declare function changed<C extends EntityId>(componentId: C): ChangedModifier<C>;
93
+ /**
94
+ * Extract union of guaranteed-present component IDs from query terms tuple.
95
+ */
96
+ export type ExtractIncluded<T extends unknown[]> = T extends [infer Head, ...infer Tail] ? Head extends NotModifier ? ExtractIncluded<Tail> : Head extends AddedModifier<infer C> ? C | ExtractIncluded<Tail> : Head extends ChangedModifier<infer C> ? C | ExtractIncluded<Tail> : Head extends EntityId ? Head | ExtractIncluded<Tail> : ExtractIncluded<Tail> : never;
90
97
  /**
91
98
  * Hash query terms to unique string ID for cache lookup.
92
99
  *
@@ -113,23 +120,7 @@ export declare function hashQuery(include: EntityId[], exclude: EntityId[], adde
113
120
  * @example
114
121
  * const query = ensureQuery(world, Position, Velocity, not(Dead));
115
122
  */
116
- export declare function ensureQuery(world: World, ...terms: (EntityId | QueryModifier)[]): QueryMeta;
117
- /**
118
- * Destroy query and clean up associated resources.
119
- *
120
- * Unregisters observer callbacks and removes from query registry.
121
- *
122
- * @param world - World instance
123
- * @param queryMeta - Query metadata to destroy
124
- *
125
- * @example
126
- * ```typescript
127
- * const query = ensureQuery(world, Position);
128
- * // ... use query ...
129
- * destroyQuery(world, query);
130
- * ```
131
- */
132
- export declare function destroyQuery(world: World, queryMeta: QueryMeta): void;
123
+ export declare function ensureQuery<T extends (EntityId | QueryModifier)[]>(world: World, ...terms: [...T]): QueryMeta<ExtractIncluded<T>>;
133
124
  /**
134
125
  * Iterate entities matching components and modifiers via callback.
135
126
  *
@@ -157,7 +148,8 @@ export declare function destroyQuery(world: World, queryMeta: QueryMeta): void;
157
148
  * });
158
149
  * ```
159
150
  */
160
- export declare function queryEntities(world: World, termsOrQuery: (EntityId | QueryModifier)[] | QueryMeta, callback: (entity: EntityId) => unknown): void;
151
+ export declare function queryEntities<T extends (EntityId | QueryModifier)[]>(world: World, terms: [...T], callback: (entity: EntityWith<ExtractIncluded<T>>) => unknown): void;
152
+ export declare function queryEntities<C extends EntityId>(world: World, query: QueryMeta<C>, callback: (entity: EntityWith<C>) => unknown): void;
161
153
  /**
162
154
  * Get first entity matching components and modifiers.
163
155
  *
@@ -171,11 +163,12 @@ export declare function queryEntities(world: World, termsOrQuery: (EntityId | Qu
171
163
  * ```typescript
172
164
  * const player = queryFirstEntity(world, [Player, not(Dead)]);
173
165
  * if (player !== undefined) {
174
- * const health = getComponentValue(world, player, Health, "value");
166
+ * const health = getComponentValue(world, player, Health, "value"); // narrowed
175
167
  * }
176
168
  * ```
177
169
  */
178
- export declare function queryFirstEntity(world: World, termsOrQuery: (EntityId | QueryModifier)[] | QueryMeta): EntityId | undefined;
170
+ export declare function queryFirstEntity<T extends (EntityId | QueryModifier)[]>(world: World, terms: [...T]): EntityWith<ExtractIncluded<T>> | undefined;
171
+ export declare function queryFirstEntity<C extends EntityId>(world: World, query: QueryMeta<C>): EntityWith<C> | undefined;
179
172
  /**
180
173
  * Collect all matching entities into an array.
181
174
  *
@@ -192,5 +185,7 @@ export declare function queryFirstEntity(world: World, termsOrQuery: (EntityId |
192
185
  * sorted.sort((a, b) => getComponentValue(world, a, Position, "x")! - getComponentValue(world, b, Position, "x")!);
193
186
  * ```
194
187
  */
195
- export declare function collectEntities(world: World, termsOrQuery: (EntityId | QueryModifier)[] | QueryMeta): EntityId[];
188
+ export declare function collectEntities<T extends (EntityId | QueryModifier)[]>(world: World, terms: [...T]): EntityWith<ExtractIncluded<T>>[];
189
+ export declare function collectEntities<C extends EntityId>(world: World, query: QueryMeta<C>): EntityWith<C>[];
190
+ export {};
196
191
  //# sourceMappingURL=query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAMxC;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB;;OAEG;IACH,OAAO,EAAE,QAAQ,EAAE,CAAC;IAEpB;;OAEG;IACH,OAAO,EAAE,QAAQ,EAAE,CAAC;IAEpB;;OAEG;IACH,MAAM,EAAE,UAAU,CAAC;IAEnB;;OAEG;IACH,eAAe,EAAE,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IAE7C;;OAEG;IACH,KAAK,EAAE,QAAQ,EAAE,CAAC;IAElB;;OAEG;IACH,OAAO,EAAE,QAAQ,EAAE,CAAC;IAEpB;;OAEG;IACH,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAMF,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,QAAQ,CAAA;CAAE,CAAC;AACjE,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,QAAQ,CAAA;CAAE,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,WAAW,EAAE,QAAQ,CAAA;CAAE,CAAC;AACzE,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,eAAe,CAAC;AAE1E;;;;;;;;;;GAUG;AACH,wBAAgB,GAAG,CAAC,WAAW,EAAE,QAAQ,GAAG,WAAW,CAEtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,WAAW,EAAE,QAAQ,GAAG,aAAa,CAE1D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,WAAW,EAAE,QAAQ,GAAG,eAAe,CAE9D;AAaD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,CAKlH;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,QAAQ,GAAG,aAAa,CAAC,EAAE,GAAG,SAAS,CAkE3F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,CAMrE;AA6FD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,CAAC,QAAQ,GAAG,aAAa,CAAC,EAAE,GAAG,SAAS,EACtD,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,OAAO,GACtC,IAAI,CAEN;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,CAAC,QAAQ,GAAG,aAAa,CAAC,EAAE,GAAG,SAAS,GACrD,QAAQ,GAAG,SAAS,CAStB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,QAAQ,GAAG,aAAa,CAAC,EAAE,GAAG,SAAS,GAAG,QAAQ,EAAE,CAQhH"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
package/dist/query.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { assert, InvalidArgument } from "./error.js";
2
2
  import { ensureFilter } from "./filters.js";
3
- import { registerObserverCallback, unregisterObserverCallback } from "./observer.js";
4
3
  /**
5
4
  * Create exclusion modifier for query.
6
5
  *
@@ -123,42 +122,11 @@ export function ensureQuery(world, ...terms) {
123
122
  changed,
124
123
  filter: filterMeta,
125
124
  lastTick: new Map(),
126
- // Callback to clean up query when its underlying filter is destroyed
127
- onFilterDestroy: (destroyedFilter) => {
128
- if (destroyedFilter !== filterMeta) {
129
- return;
130
- }
131
- // Self-cleanup: unregister callback and remove from registry
132
- unregisterObserverCallback(world, "filterDestroyed", queryMeta.onFilterDestroy);
133
- world.queries.byId.delete(queryId);
134
- },
135
125
  };
136
126
  world.queries.byId.set(queryId, queryMeta);
137
- // Register for filter destruction events to enable automatic cleanup
138
- registerObserverCallback(world, "filterDestroyed", queryMeta.onFilterDestroy);
139
127
  }
140
128
  return queryMeta;
141
129
  }
142
- /**
143
- * Destroy query and clean up associated resources.
144
- *
145
- * Unregisters observer callbacks and removes from query registry.
146
- *
147
- * @param world - World instance
148
- * @param queryMeta - Query metadata to destroy
149
- *
150
- * @example
151
- * ```typescript
152
- * const query = ensureQuery(world, Position);
153
- * // ... use query ...
154
- * destroyQuery(world, query);
155
- * ```
156
- */
157
- export function destroyQuery(world, queryMeta) {
158
- const queryId = hashQuery(queryMeta.include, queryMeta.exclude, queryMeta.added, queryMeta.changed);
159
- unregisterObserverCallback(world, "filterDestroyed", queryMeta.onFilterDestroy);
160
- world.queries.byId.delete(queryId);
161
- }
162
130
  // ============================================================================
163
131
  // Query Iteration (Internal)
164
132
  // ============================================================================
@@ -167,12 +135,25 @@ export function destroyQuery(world, queryMeta) {
167
135
  */
168
136
  function queryEntitiesWithMeta(world, queryMeta, callback) {
169
137
  const hasChangeModifiers = queryMeta.added.length > 0 || queryMeta.changed.length > 0;
138
+ // Fast path: no change modifiers
139
+ if (!hasChangeModifiers) {
140
+ const archetypes = queryMeta.filter.archetypes;
141
+ for (let a = 0; a < archetypes.length; a++) {
142
+ const entities = archetypes[a].entities;
143
+ for (let i = entities.length - 1; i >= 0; i--) {
144
+ if (callback(entities[i]) === false) {
145
+ return;
146
+ }
147
+ }
148
+ }
149
+ return;
150
+ }
151
+ // Slow path: change detection requires system context
170
152
  const { systemId, tick } = world.execution;
171
- // Change detection requires system context, no meaningful tick tracking otherwise
172
- if (hasChangeModifiers && systemId === null) {
153
+ if (systemId === null) {
173
154
  return;
174
155
  }
175
- const lastTick = hasChangeModifiers ? (queryMeta.lastTick.get(systemId) ?? 0) : 0;
156
+ const lastTick = queryMeta.lastTick.get(systemId) ?? 0;
176
157
  const archetypes = queryMeta.filter.archetypes;
177
158
  // Pre-allocated arrays reused across archetypes to avoid allocation in hot loop
178
159
  const addedTickArrays = [];
@@ -219,11 +200,9 @@ function queryEntitiesWithMeta(world, queryMeta, callback) {
219
200
  }
220
201
  }
221
202
  finally {
222
- if (hasChangeModifiers) {
223
- // Update lastTick after iteration completes or on early exit, this ensures
224
- // subsequent iterations only see changes since this execution
225
- queryMeta.lastTick.set(systemId, tick);
226
- }
203
+ // Update lastTick after iteration completes or on early exit, this ensures
204
+ // subsequent iterations only see changes since this execution
205
+ queryMeta.lastTick.set(systemId, tick);
227
206
  }
228
207
  }
229
208
  /**
@@ -235,56 +214,11 @@ function resolveQuery(world, termsOrQuery) {
235
214
  }
236
215
  return ensureQuery(world, ...termsOrQuery);
237
216
  }
238
- // ============================================================================
239
- // Query Iteration (Public)
240
- // ============================================================================
241
- /**
242
- * Iterate entities matching components and modifiers via callback.
243
- *
244
- * Iterates backward for safe entity destruction during iteration.
245
- * Creates/reuses cached query internally.
246
- *
247
- * @param world - World instance
248
- * @param termsOrQuery - Array of component IDs and query modifiers, or pre-built QueryMeta
249
- * @param callback - Called for each matching entity. Return `false` to stop iteration early
250
- *
251
- * @example
252
- * ```typescript
253
- * // With inline terms
254
- * queryEntities(world, [Position, Velocity, not(Dead)], (entity) => {
255
- * const pos = getComponentValue(world, entity, Position, "x");
256
- * });
257
- *
258
- * // With pre-built query
259
- * const q = ensureQuery(world, Position, Velocity);
260
- * queryEntities(world, q, (entity) => { ... });
261
- *
262
- * // Early exit
263
- * queryEntities(world, [Position], (entity) => {
264
- * if (done) return false;
265
- * });
266
- * ```
267
- */
268
- export function queryEntities(world, termsOrQuery, callback) {
217
+ export function queryEntities(world, termsOrQuery,
218
+ // biome-ignore lint/suspicious/noExplicitAny: implementation overload must be wider than public overloads
219
+ callback) {
269
220
  queryEntitiesWithMeta(world, resolveQuery(world, termsOrQuery), callback);
270
221
  }
271
- /**
272
- * Get first entity matching components and modifiers.
273
- *
274
- * Useful for singleton patterns or when only one match is expected.
275
- *
276
- * @param world - World instance
277
- * @param termsOrQuery - Array of component IDs and query modifiers, or pre-built QueryMeta
278
- * @returns First matching entity ID, or undefined if no matches
279
- *
280
- * @example
281
- * ```typescript
282
- * const player = queryFirstEntity(world, [Player, not(Dead)]);
283
- * if (player !== undefined) {
284
- * const health = getComponentValue(world, player, Health, "value");
285
- * }
286
- * ```
287
- */
288
222
  export function queryFirstEntity(world, termsOrQuery) {
289
223
  let result;
290
224
  queryEntitiesWithMeta(world, resolveQuery(world, termsOrQuery), (entity) => {
@@ -293,22 +227,6 @@ export function queryFirstEntity(world, termsOrQuery) {
293
227
  });
294
228
  return result;
295
229
  }
296
- /**
297
- * Collect all matching entities into an array.
298
- *
299
- * @param world - World instance
300
- * @param termsOrQuery - Array of component IDs and query modifiers, or pre-built QueryMeta
301
- * @returns Array of matching entity IDs
302
- *
303
- * @example
304
- * ```typescript
305
- * const entities = collectEntities(world, [Position, Velocity]);
306
- *
307
- * // Pre-sort before iteration
308
- * const sorted = collectEntities(world, [Position]);
309
- * sorted.sort((a, b) => getComponentValue(world, a, Position, "x")! - getComponentValue(world, b, Position, "x")!);
310
- * ```
311
- */
312
230
  export function collectEntities(world, termsOrQuery) {
313
231
  const result = [];
314
232
  queryEntitiesWithMeta(world, resolveQuery(world, termsOrQuery), (entity) => {
package/dist/query.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { Component, EntityId } from "./encoding.js";
1
+ import type { Component, EntityId, EntityWith } from "./encoding.js";
2
2
  import type { InferSchema, InferSchemaRecord, SchemaRecord } from "./schema.js";
3
3
  import type { World } from "./world.js";
4
4
  /**
@@ -36,29 +36,35 @@ export declare function removeResource(world: World, component: EntityId): void;
36
36
  *
37
37
  * @param world - World instance
38
38
  * @param component - Component definition (acting as resource handle)
39
- * @returns True if the resource exists, false otherwise
39
+ * @returns True if the resource exists, narrowing the component for non-null access
40
40
  *
41
41
  * @example
42
42
  * ```typescript
43
43
  * if (hasResource(world, Time)) {
44
- * // Time resource is available
44
+ * // Time narrowed to Component<S> & EntityWith<Component<S>>
45
+ * const dt = getResourceValue(world, Time, "delta"); // non-null
45
46
  * }
46
47
  * ```
47
48
  */
49
+ export declare function hasResource<S extends SchemaRecord>(world: World, component: Component<S>): component is Component<S> & EntityWith<Component<S>>;
48
50
  export declare function hasResource(world: World, component: EntityId): boolean;
49
51
  /**
50
52
  * Gets the value of a specific field on a global resource.
51
53
  *
52
54
  * @param world - World instance
53
- * @param component - Component definition
55
+ * @param component - Component definition (narrowed via hasResource for non-null access)
54
56
  * @param key - Field name to retrieve
55
- * @returns The field value, or undefined if the resource is not present
57
+ * @returns The field value (non-null if narrowed), or undefined if not present
56
58
  *
57
59
  * @example
58
60
  * ```typescript
59
- * const dt = getResourceValue(world, Time, "delta");
61
+ * if (hasResource(world, Time)) {
62
+ * const dt = getResourceValue(world, Time, "delta"); // number
63
+ * }
64
+ * const current = getResourceValue(world, Time, "current"); // number | undefined
60
65
  * ```
61
66
  */
67
+ export declare function getResourceValue<S extends SchemaRecord, K extends keyof S>(world: World, component: Component<S> & EntityWith<Component<S>>, key: K): InferSchema<S[K]>;
62
68
  export declare function getResourceValue<S extends SchemaRecord, K extends keyof S>(world: World, component: Component<S>, key: K): InferSchema<S[K]> | undefined;
63
69
  /**
64
70
  * Sets the value of a specific field on a global resource.
@@ -1 +1 @@
1
- {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,YAAY,EAChD,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GACzB,IAAI,CAEN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI,CAEtE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,GAAG,OAAO,CAEtE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,MAAM,CAAC,EACxE,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,GACL,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAE/B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,MAAM,CAAC,EACxE,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,EACN,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACvB,IAAI,CAEN"}
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAMxC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,YAAY,EAChD,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GACzB,IAAI,CAEN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI,CAEtE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,YAAY,EAChD,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GACtB,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAExD,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,GAAG,OAAO,CAAC;AAMxE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,MAAM,CAAC,EACxE,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAClD,GAAG,EAAE,CAAC,GACL,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAErB,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,MAAM,CAAC,EACxE,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,GACL,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;AAUjC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,MAAM,CAAC,EACxE,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,EACN,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACvB,IAAI,CAEN"}
package/dist/resource.js CHANGED
@@ -1,4 +1,7 @@
1
1
  import { addComponent, getComponentValue, hasComponent, removeComponent, setComponentValue } from "./component.js";
2
+ // ============================================================================
3
+ // Resource Operations
4
+ // ============================================================================
2
5
  /**
3
6
  * Adds a global resource (singleton) to the world using the component-on-self pattern.
4
7
  *
@@ -33,36 +36,9 @@ export function addResource(world, component, data) {
33
36
  export function removeResource(world, component) {
34
37
  removeComponent(world, component, component);
35
38
  }
36
- /**
37
- * Checks if a global resource exists in the world.
38
- *
39
- * @param world - World instance
40
- * @param component - Component definition (acting as resource handle)
41
- * @returns True if the resource exists, false otherwise
42
- *
43
- * @example
44
- * ```typescript
45
- * if (hasResource(world, Time)) {
46
- * // Time resource is available
47
- * }
48
- * ```
49
- */
50
39
  export function hasResource(world, component) {
51
40
  return hasComponent(world, component, component);
52
41
  }
53
- /**
54
- * Gets the value of a specific field on a global resource.
55
- *
56
- * @param world - World instance
57
- * @param component - Component definition
58
- * @param key - Field name to retrieve
59
- * @returns The field value, or undefined if the resource is not present
60
- *
61
- * @example
62
- * ```typescript
63
- * const dt = getResourceValue(world, Time, "delta");
64
- * ```
65
- */
66
42
  export function getResourceValue(world, component, key) {
67
43
  return getComponentValue(world, component, component, key);
68
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKnH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,WAAW,CACzB,KAAY,EACZ,SAAuB,EACvB,IAA0B;IAE1B,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AAClD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,SAAmB;IAC9D,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,KAAY,EAAE,SAAmB;IAC3D,OAAO,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAY,EACZ,SAAuB,EACvB,GAAM;IAEN,OAAO,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAY,EACZ,SAAuB,EACvB,GAAM,EACN,KAAwB;IAExB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC"}
1
+ {"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKnH,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,WAAW,CACzB,KAAY,EACZ,SAAuB,EACvB,IAA0B;IAE1B,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AAClD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,SAAmB;IAC9D,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAC/C,CAAC;AAwBD,MAAM,UAAU,WAAW,CAAC,KAAY,EAAE,SAAmB;IAC3D,OAAO,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AACnD,CAAC;AA8BD,MAAM,UAAU,gBAAgB,CAC9B,KAAY,EACZ,SAAuB,EACvB,GAAM;IAEN,OAAO,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAY,EACZ,SAAuB,EACvB,GAAM,EACN,KAAwB;IAExB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC"}
@@ -70,6 +70,27 @@ export declare const Last: ScheduleLabel;
70
70
  * Takes world, returns void or Promise for async systems.
71
71
  */
72
72
  export type SystemRunner = (world: World) => void | Promise<void>;
73
+ /**
74
+ * System tick function returned by a SystemFactory's init.
75
+ *
76
+ * Runs every frame. The world is captured in the init closure scope,
77
+ * not passed as a parameter.
78
+ */
79
+ export type SystemTick = () => void | Promise<void>;
80
+ /**
81
+ * System factory with init/tick separation.
82
+ *
83
+ * Created via `defineSystem()`. The init function runs once at registration
84
+ * time (`addSystem`), the returned tick function runs every frame.
85
+ */
86
+ export type SystemFactory = {
87
+ /** @internal Runtime brand for discriminating SystemFactory from SystemRunner. */
88
+ readonly __systemFactory: true;
89
+ /** System name for scheduling constraints and execution context. */
90
+ readonly name: string;
91
+ /** Init function. Receives world, returns tick function. */
92
+ readonly init: (world: World) => SystemTick;
93
+ };
73
94
  /**
74
95
  * Options for system registration.
75
96
  */
@@ -119,17 +140,59 @@ export type SystemMeta = {
119
140
  /**
120
141
  * Registers a system in the world for later scheduling.
121
142
  *
143
+ * Accepts either a `SystemRunner` function or a `SystemFactory` created by
144
+ * `defineSystem()`. When a factory is passed, its init function runs
145
+ * immediately and the returned tick function is registered as the runner.
146
+ *
122
147
  * @param world - World instance
123
- * @param runner - System function (must be named unless name option provided)
148
+ * @param system - System function or factory (must be named unless name option provided)
124
149
  * @param options - Registration options (name, schedule, before, after)
125
150
  *
126
151
  * @example
127
152
  * ```typescript
128
153
  * addSystem(world, physicsSystem);
129
154
  * addSystem(world, renderSystem, { schedule: PostUpdate, after: "physicsSystem" });
155
+ * addSystem(world, movementFactory); // SystemFactory from defineSystem()
156
+ * ```
157
+ */
158
+ export declare function addSystem(world: World, system: SystemRunner | SystemFactory, options?: SystemOptions): void;
159
+ /**
160
+ * Define a system with separate init and tick phases.
161
+ *
162
+ * The init function runs once when the system is registered via `addSystem()`.
163
+ * Use it to cache query references, action getters, and other one-time setup.
164
+ * The returned tick function runs every frame during schedule execution.
165
+ *
166
+ * Local state can be declared as variables in the init closure — use it for
167
+ * system-internal bookkeeping (frame counters, cooldowns, cached computations).
168
+ * Use resources for state other systems need to read, components for per-entity state.
169
+ *
170
+ * @param name - System name
171
+ * @param init - Init function that receives the world and returns a tick function
172
+ * @returns SystemFactory to pass to `addSystem()`
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * const movementSystem = defineSystem("movementSystem", (world) => {
177
+ * // Init: runs once at addSystem() time
178
+ * const movers = ensureQuery(world, Position, Velocity);
179
+ *
180
+ * // Tick: runs every frame
181
+ * return () => {
182
+ * const dt = getResourceValue(world, Time, "delta") ?? 0;
183
+ * queryEntities(world, movers, (entity) => {
184
+ * const x = getComponentValue(world, entity, Position, "x")!;
185
+ * const vx = getComponentValue(world, entity, Velocity, "vx")!;
186
+ * setComponentValue(world, entity, Position, "x", x + vx * dt);
187
+ * });
188
+ * };
189
+ * });
190
+ *
191
+ * addSystem(world, movementSystem);
192
+ * addSystem(world, movementSystem, { schedule: PostUpdate, name: "lateMovement" });
130
193
  * ```
131
194
  */
132
- export declare function addSystem(world: World, runner: SystemRunner, options?: SystemOptions): void;
195
+ export declare function defineSystem(name: string, init: (world: World) => SystemTick): SystemFactory;
133
196
  /**
134
197
  * Insert a schedule before an existing schedule in the pipeline.
135
198
  *
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAMxC;;GAEG;AACH,OAAO,CAAC,MAAM,oBAAoB,EAAE,OAAO,MAAM,CAAC;AAElD;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG;IAAE,CAAC,oBAAoB,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAMtE;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAE1D;AAMD;;GAEG;AACH,eAAO,MAAM,OAAO,eAA4B,CAAC;AAEjD;;GAEG;AACH,eAAO,MAAM,QAAQ,eAA6B,CAAC;AAEnD;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,eAA0B,CAAC;AAE7C;;GAEG;AACH,eAAO,MAAM,SAAS,eAA8B,CAAC;AAErD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,eAA2B,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,UAAU,eAA+B,CAAC;AAEvD;;GAEG;AACH,eAAO,MAAM,IAAI,eAAyB,CAAC;AAM3C;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;IAEzB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAE3B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;OAEG;IACH,MAAM,EAAE,YAAY,CAAC;IAErB;;OAEG;IACH,QAAQ,EAAE,aAAa,CAAC;IAExB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB;;OAEG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAMF;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAoB3F;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CASvG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAQtG;AA4LD;;;;;;;;;;;;GAYG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBzD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAOtC;AAyBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBtD"}
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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"}