@vworlds/vecs 1.0.15 → 1.0.16

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.
Files changed (181) hide show
  1. package/README.md +249 -119
  2. package/dist/component.d.ts +52 -76
  3. package/dist/component.js +60 -45
  4. package/dist/component.js.map +1 -1
  5. package/dist/component_meta.d.ts +98 -0
  6. package/dist/component_meta.js +65 -0
  7. package/dist/component_meta.js.map +1 -0
  8. package/dist/dsl.d.ts +46 -34
  9. package/dist/dsl.js +459 -61
  10. package/dist/dsl.js.map +1 -1
  11. package/dist/entity/entity.base.d.ts +57 -0
  12. package/dist/entity/entity.base.js +81 -0
  13. package/dist/entity/entity.base.js.map +1 -0
  14. package/dist/entity/entity.components.d.ts +117 -0
  15. package/dist/entity/entity.components.js +244 -0
  16. package/dist/entity/entity.components.js.map +1 -0
  17. package/dist/entity/entity.d.ts +35 -0
  18. package/dist/entity/entity.identity.d.ts +8 -0
  19. package/dist/entity/entity.identity.js +15 -0
  20. package/dist/entity/entity.identity.js.map +1 -0
  21. package/dist/entity/entity.js +33 -0
  22. package/dist/entity/entity.js.map +1 -0
  23. package/dist/entity/entity.lifecycle.d.ts +12 -0
  24. package/dist/entity/entity.lifecycle.js +111 -0
  25. package/dist/entity/entity.lifecycle.js.map +1 -0
  26. package/dist/entity/entity.queries.d.ts +3 -0
  27. package/dist/entity/entity.queries.js +33 -0
  28. package/dist/entity/entity.queries.js.map +1 -0
  29. package/dist/entity/entity.relationships.d.ts +9 -0
  30. package/dist/entity/entity.relationships.js +74 -0
  31. package/dist/entity/entity.relationships.js.map +1 -0
  32. package/dist/entity/index.d.ts +2 -0
  33. package/dist/entity/index.js +3 -0
  34. package/dist/entity/index.js.map +1 -0
  35. package/dist/filter.d.ts +27 -8
  36. package/dist/filter.js +33 -18
  37. package/dist/filter.js.map +1 -1
  38. package/dist/index.d.ts +13 -5
  39. package/dist/index.js +12 -2
  40. package/dist/index.js.map +1 -1
  41. package/dist/inject.d.ts +80 -0
  42. package/dist/inject.js +270 -0
  43. package/dist/inject.js.map +1 -0
  44. package/dist/module.d.ts +23 -0
  45. package/dist/module.js +17 -0
  46. package/dist/module.js.map +1 -0
  47. package/dist/modules/identity.d.ts +15 -0
  48. package/dist/modules/identity.js +41 -0
  49. package/dist/modules/identity.js.map +1 -0
  50. package/dist/modules/singleton.d.ts +26 -0
  51. package/dist/modules/singleton.js +41 -0
  52. package/dist/modules/singleton.js.map +1 -0
  53. package/dist/package.json +12 -1
  54. package/dist/phase.d.ts +2 -2
  55. package/dist/query/index.d.ts +6 -0
  56. package/dist/query/index.js +5 -0
  57. package/dist/query/index.js.map +1 -0
  58. package/dist/query/query.00.base.d.ts +23 -0
  59. package/dist/query/query.00.base.js +77 -0
  60. package/dist/query/query.00.base.js.map +1 -0
  61. package/dist/query/query.01.reactive.d.ts +7 -0
  62. package/dist/query/query.01.reactive.js +58 -0
  63. package/dist/query/query.01.reactive.js.map +1 -0
  64. package/dist/query/query.02.lifecycle.d.ts +6 -0
  65. package/dist/query/query.02.lifecycle.js +63 -0
  66. package/dist/query/query.02.lifecycle.js.map +1 -0
  67. package/dist/query/query.03.tracking.d.ts +15 -0
  68. package/dist/query/query.03.tracking.js +31 -0
  69. package/dist/query/query.03.tracking.js.map +1 -0
  70. package/dist/query/query.04.callbacks.d.ts +14 -0
  71. package/dist/query/query.04.callbacks.js +65 -0
  72. package/dist/query/query.04.callbacks.js.map +1 -0
  73. package/dist/query/query.05.updates.d.ts +14 -0
  74. package/dist/query/query.05.updates.js +81 -0
  75. package/dist/query/query.05.updates.js.map +1 -0
  76. package/dist/query/query.06.predicate.d.ts +13 -0
  77. package/dist/query/query.06.predicate.js +40 -0
  78. package/dist/query/query.06.predicate.js.map +1 -0
  79. package/dist/query/query.07.groups.d.ts +41 -0
  80. package/dist/query/query.07.groups.js +110 -0
  81. package/dist/query/query.07.groups.js.map +1 -0
  82. package/dist/query/query.d.ts +53 -0
  83. package/dist/query/query.js +138 -0
  84. package/dist/query/query.js.map +1 -0
  85. package/dist/relationship.d.ts +19 -0
  86. package/dist/relationship.js +18 -0
  87. package/dist/relationship.js.map +1 -0
  88. package/dist/system.d.ts +37 -23
  89. package/dist/system.js +80 -64
  90. package/dist/system.js.map +1 -1
  91. package/dist/terms/all_term.d.ts +32 -0
  92. package/dist/terms/all_term.js +41 -0
  93. package/dist/terms/all_term.js.map +1 -0
  94. package/dist/terms/any_term.d.ts +33 -0
  95. package/dist/terms/any_term.js +42 -0
  96. package/dist/terms/any_term.js.map +1 -0
  97. package/dist/terms/build.d.ts +62 -0
  98. package/dist/terms/build.js +382 -0
  99. package/dist/terms/build.js.map +1 -0
  100. package/dist/terms/component_term.d.ts +37 -0
  101. package/dist/terms/component_term.js +49 -0
  102. package/dist/terms/component_term.js.map +1 -0
  103. package/dist/terms/empty_term.d.ts +6 -0
  104. package/dist/terms/empty_term.js +12 -0
  105. package/dist/terms/empty_term.js.map +1 -0
  106. package/dist/terms/index.d.ts +11 -0
  107. package/dist/terms/index.js +12 -0
  108. package/dist/terms/index.js.map +1 -0
  109. package/dist/terms/not_term.d.ts +35 -0
  110. package/dist/terms/not_term.js +47 -0
  111. package/dist/terms/not_term.js.map +1 -0
  112. package/dist/terms/only_term.d.ts +47 -0
  113. package/dist/terms/only_term.js +79 -0
  114. package/dist/terms/only_term.js.map +1 -0
  115. package/dist/terms/predicate_term.d.ts +80 -0
  116. package/dist/terms/predicate_term.js +109 -0
  117. package/dist/terms/predicate_term.js.map +1 -0
  118. package/dist/terms/target_term.d.ts +43 -0
  119. package/dist/terms/target_term.js +87 -0
  120. package/dist/terms/target_term.js.map +1 -0
  121. package/dist/terms/term.d.ts +94 -0
  122. package/dist/terms/term.js +202 -0
  123. package/dist/terms/term.js.map +1 -0
  124. package/dist/terms/world_term.d.ts +68 -0
  125. package/dist/terms/world_term.js +99 -0
  126. package/dist/terms/world_term.js.map +1 -0
  127. package/dist/timer.js +2 -2
  128. package/dist/timer.js.map +1 -1
  129. package/dist/util/array_map.js +12 -0
  130. package/dist/util/array_map.js.map +1 -1
  131. package/dist/util/bitset.js +107 -22
  132. package/dist/util/bitset.js.map +1 -1
  133. package/dist/util/dense_set.d.ts +1 -0
  134. package/dist/util/dense_set.js +90 -0
  135. package/dist/util/dense_set.js.map +1 -0
  136. package/dist/util/id_pool.d.ts +23 -0
  137. package/dist/util/id_pool.js +194 -0
  138. package/dist/util/id_pool.js.map +1 -0
  139. package/dist/world/index.d.ts +3 -0
  140. package/dist/world/index.js +3 -0
  141. package/dist/world/index.js.map +1 -0
  142. package/dist/world/world.base.d.ts +6 -0
  143. package/dist/world/world.base.js +21 -0
  144. package/dist/world/world.base.js.map +1 -0
  145. package/dist/world/world.components.d.ts +67 -0
  146. package/dist/world/world.components.js +93 -0
  147. package/dist/world/world.components.js.map +1 -0
  148. package/dist/world/world.d.ts +29 -0
  149. package/dist/world/world.deferred.d.ts +13 -0
  150. package/dist/world/world.deferred.js +93 -0
  151. package/dist/world/world.deferred.js.map +1 -0
  152. package/dist/world/world.entities.d.ts +18 -0
  153. package/dist/world/world.entities.js +97 -0
  154. package/dist/world/world.entities.js.map +1 -0
  155. package/dist/world/world.js +39 -0
  156. package/dist/world/world.js.map +1 -0
  157. package/dist/world/world.modules.d.ts +12 -0
  158. package/dist/world/world.modules.js +21 -0
  159. package/dist/world/world.modules.js.map +1 -0
  160. package/dist/world/world.pipeline.d.ts +21 -0
  161. package/dist/world/world.pipeline.js +105 -0
  162. package/dist/world/world.pipeline.js.map +1 -0
  163. package/dist/world/world.pools.d.ts +9 -0
  164. package/dist/world/world.pools.js +59 -0
  165. package/dist/world/world.pools.js.map +1 -0
  166. package/dist/world/world.queries.d.ts +18 -0
  167. package/dist/world/world.queries.js +101 -0
  168. package/dist/world/world.queries.js.map +1 -0
  169. package/dist/world/world.storage.d.ts +7 -0
  170. package/dist/world/world.storage.js +26 -0
  171. package/dist/world/world.storage.js.map +1 -0
  172. package/package.json +12 -1
  173. package/dist/entity.d.ts +0 -215
  174. package/dist/entity.js +0 -457
  175. package/dist/entity.js.map +0 -1
  176. package/dist/query.d.ts +0 -251
  177. package/dist/query.js +0 -353
  178. package/dist/query.js.map +0 -1
  179. package/dist/world.d.ts +0 -389
  180. package/dist/world.js +0 -631
  181. package/dist/world.js.map +0 -1
@@ -1,86 +1,62 @@
1
- import { BitPtr } from "./util/bitset.js";
2
- import type { Entity } from "./entity.js";
3
- /** A component instance. Components are plain objects created with a no-arg constructor. */
4
- export type Component = object;
5
- /** A component class constructor. */
6
- export type ComponentClass<T extends Component = Component> = new () => T;
7
- /** A component class constructor or its numeric type id. */
8
- export type ComponentClassOrType = number | ComponentClass;
9
- /**
10
- * Lifecycle hook for a registered component class. Obtained via
11
- * {@link World.hook}.
12
- *
13
- * Hooks are a lightweight alternative to building a {@link System} when all
14
- * you need is a callback on add / remove / set for a single component type.
15
- * The same `Hook` is returned on every call to `world.hook(C)`, so registration
16
- * methods chain:
17
- *
18
- * ```ts
19
- * world.hook(Sprite)
20
- * .onAdd((e, c) => initSprite(e, c))
21
- * .onRemove((e, c) => destroySprite(e, c))
22
- * .onSet((e, c) => syncSprite(e, c));
23
- * ```
24
- *
25
- * Callbacks fire synchronously when the corresponding entity command is
26
- * applied: inline outside deferred mode, or while the world drains its command
27
- * queue inside a system / `forEach` / `defer` block.
28
- *
29
- * @typeParam C - Component class this hook is bound to.
30
- */
31
- export interface Hook<C extends Component = Component> {
1
+ import { Entity } from "./entity/index.js";
2
+ import type { ComponentType } from "./component_meta.js";
3
+ export { CleanupPolicy, ComponentMeta, type ComponentClass, type ComponentInstance, type ComponentRef, type ComponentRefArray, type ComponentType, type Hook, } from "./component_meta.js";
4
+ /** A component entity created by {@link World.component}. */
5
+ export declare class Component<T extends ComponentType = ComponentType> extends Entity {
32
6
  /**
33
- * Register a handler invoked when a component of this type is first attached
34
- * to an entity (`entity.add(C)` or `entity.set(C, ...)` on an entity that
35
- * does not yet have the component).
7
+ * Register a callback fired each time this component is **added** to an entity.
36
8
  *
37
- * @param handler - Receives the entity and freshly created component instance.
38
- * @returns This hook, for chaining.
9
+ * The handler is called with the owning entity and the freshly created
10
+ * component instance. Use it to initialise external state (e.g. scene objects)
11
+ * that should exist for the lifetime of the component.
12
+ *
13
+ * @param handler - Callback invoked with `(entity, componentInstance)`.
14
+ * @returns This `Component` entity, for chaining.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * world.component(Sprite).onAdd((entity, sprite) => sprite.initialize(scene));
19
+ * ```
39
20
  */
40
- onAdd(handler: (entity: Entity, c: C) => void): Hook<C>;
21
+ onAdd(handler: (entity: Entity, c: InstanceType<T>) => void): this;
41
22
  /**
42
- * Register a handler invoked when a component of this type is removed from
43
- * an entity (explicit `entity.remove(C)` or implicit removal during
44
- * `entity.destroy()`).
23
+ * Register a callback fired each time this component is **removed** from an
24
+ * entity, or when the owning entity is destroyed.
25
+ *
26
+ * The handler is called with the owning entity and the component instance that
27
+ * is about to be detached. Use it to clean up any external state associated
28
+ * with the component.
29
+ *
30
+ * @param handler - Callback invoked with `(entity, componentInstance)`.
31
+ * @returns This `Component` entity, for chaining.
45
32
  *
46
- * @param handler - Receives the entity and component instance that was removed.
47
- * @returns This hook, for chaining.
33
+ * @example
34
+ * ```ts
35
+ * world.component(Sprite).onRemove((entity, sprite) => sprite.destroy(scene));
36
+ * ```
48
37
  */
49
- onRemove(handler: (entity: Entity, c: C) => void): Hook<C>;
38
+ onRemove(handler: (entity: Entity, c: InstanceType<T>) => void): this;
50
39
  /**
51
- * Register a handler invoked when a component's data has been marked as
52
- * changed (`entity.modified(C)`), and when
53
- * `entity.set(C, props)` is called on an entity that already has the
54
- * component.
40
+ * Register a callback fired each time this component's data is **set or
41
+ * modified**.
55
42
  *
56
- * @param handler - Receives the entity and component instance whose data changed.
57
- * @returns This hook, for chaining.
43
+ * Fires when:
44
+ * - `entity.set(C, props)` applies data to the component.
45
+ * - `entity.attach(instance)` stores an existing instance.
46
+ * - `entity.modified(C)` is called after in-place mutation.
47
+ * - A system's `getMut(C)` marks the component dirty.
48
+ *
49
+ * The handler receives the owning entity and the current component instance.
50
+ * Component instances do not carry entity references, which is why the entity
51
+ * is passed explicitly.
52
+ *
53
+ * @param handler - Callback invoked with `(entity, componentInstance)`.
54
+ * @returns This `Component` entity, for chaining.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * world.component(Transform).onSet((entity, t) => renderer.syncTransform(entity.eid, t));
59
+ * ```
58
60
  */
59
- onSet(handler: (entity: Entity, c: C) => void): Hook<C>;
60
- }
61
- /**
62
- * Bookkeeping record produced for each component class registered via
63
- * {@link World.registerComponent}.
64
- *
65
- * Holds the constructor, numeric type id, display name, and pre-computed
66
- * {@link BitPtr} used by archetype checks. Implements {@link Hook}, so the
67
- * lifecycle handlers attached via `world.hook(C)` are stored directly on the
68
- * meta object.
69
- */
70
- export declare class ComponentMeta implements Hook<Component> {
71
- /** The component class constructor this meta represents. */
72
- readonly Class: ComponentClass;
73
- /** Numeric type id assigned at registration time. */
74
- readonly type: number;
75
- /** Human-readable name used in logs and serialization lookups. */
76
- readonly componentName: string;
77
- /** Pre-computed bit-pointer into the entity archetype {@link Bitset}. */
78
- readonly bitPtr: BitPtr;
79
- constructor(Class: ComponentClass, type: number, componentName: string);
80
- /** @inheritdoc */
81
- onAdd(handler: (entity: Entity, c: Component) => void): ComponentMeta;
82
- /** @inheritdoc */
83
- onRemove(handler: (entity: Entity, c: Component) => void): ComponentMeta;
84
- /** @inheritdoc */
85
- onSet(handler: (entity: Entity, c: Component) => void): ComponentMeta;
61
+ onSet(handler: (entity: Entity, c: InstanceType<T>) => void): this;
86
62
  }
package/dist/component.js CHANGED
@@ -1,56 +1,71 @@
1
- import { BitPtr, Bitset } from "./util/bitset.js";
2
- /**
3
- * Bookkeeping record produced for each component class registered via
4
- * {@link World.registerComponent}.
5
- *
6
- * Holds the constructor, numeric type id, display name, and pre-computed
7
- * {@link BitPtr} used by archetype checks. Implements {@link Hook}, so the
8
- * lifecycle handlers attached via `world.hook(C)` are stored directly on the
9
- * meta object.
10
- */
11
- export class ComponentMeta {
12
- constructor(Class, type, componentName) {
13
- /**
14
- * @internal Peer metas of components that cannot coexist with this one on
15
- * the same entity. Set via {@link World.setExclusiveComponents}; `undefined`
16
- * means no restriction.
17
- */
18
- this._exclusive = undefined;
19
- this.Class = Class;
20
- this.type = type;
21
- this.componentName = componentName;
22
- this.bitPtr = new BitPtr(type);
23
- }
24
- /** @inheritdoc */
1
+ import { Entity } from "./entity/index.js";
2
+ export { CleanupPolicy, ComponentMeta, } from "./component_meta.js";
3
+ /** A component entity created by {@link World.component}. */
4
+ export class Component extends Entity {
5
+ /**
6
+ * Register a callback fired each time this component is **added** to an entity.
7
+ *
8
+ * The handler is called with the owning entity and the freshly created
9
+ * component instance. Use it to initialise external state (e.g. scene objects)
10
+ * that should exist for the lifetime of the component.
11
+ *
12
+ * @param handler - Callback invoked with `(entity, componentInstance)`.
13
+ * @returns This `Component` entity, for chaining.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * world.component(Sprite).onAdd((entity, sprite) => sprite.initialize(scene));
18
+ * ```
19
+ */
25
20
  onAdd(handler) {
26
- (this._onAddHandlers ?? (this._onAddHandlers = [])).unshift(handler);
21
+ this.ownMeta.onAdd(handler);
27
22
  return this;
28
23
  }
29
- /** @inheritdoc */
24
+ /**
25
+ * Register a callback fired each time this component is **removed** from an
26
+ * entity, or when the owning entity is destroyed.
27
+ *
28
+ * The handler is called with the owning entity and the component instance that
29
+ * is about to be detached. Use it to clean up any external state associated
30
+ * with the component.
31
+ *
32
+ * @param handler - Callback invoked with `(entity, componentInstance)`.
33
+ * @returns This `Component` entity, for chaining.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * world.component(Sprite).onRemove((entity, sprite) => sprite.destroy(scene));
38
+ * ```
39
+ */
30
40
  onRemove(handler) {
31
- (this._onRemoveHandlers ?? (this._onRemoveHandlers = [])).unshift(handler);
41
+ this.ownMeta.onRemove(handler);
32
42
  return this;
33
43
  }
34
- /** @inheritdoc */
44
+ /**
45
+ * Register a callback fired each time this component's data is **set or
46
+ * modified**.
47
+ *
48
+ * Fires when:
49
+ * - `entity.set(C, props)` applies data to the component.
50
+ * - `entity.attach(instance)` stores an existing instance.
51
+ * - `entity.modified(C)` is called after in-place mutation.
52
+ * - A system's `getMut(C)` marks the component dirty.
53
+ *
54
+ * The handler receives the owning entity and the current component instance.
55
+ * Component instances do not carry entity references, which is why the entity
56
+ * is passed explicitly.
57
+ *
58
+ * @param handler - Callback invoked with `(entity, componentInstance)`.
59
+ * @returns This `Component` entity, for chaining.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * world.component(Transform).onSet((entity, t) => renderer.syncTransform(entity.eid, t));
64
+ * ```
65
+ */
35
66
  onSet(handler) {
36
- (this._onSetHandlers ?? (this._onSetHandlers = [])).unshift(handler);
67
+ this.ownMeta.onSet(handler);
37
68
  return this;
38
69
  }
39
70
  }
40
- /**
41
- * Compute a {@link Bitset} with one bit set for every component class or
42
- * numeric type id in `classes`.
43
- *
44
- * @internal Used to build archetype masks for `HAS` / `HAS_ONLY` queries.
45
- *
46
- * @param classes - Component classes or type ids to include.
47
- * @param world - World used to resolve classes to type ids.
48
- */
49
- export function _calculateComponentBitmask(classes, world) {
50
- const bitmask = new Bitset();
51
- classes.forEach((C) => {
52
- bitmask.add(world.getComponentType(C));
53
- });
54
- return bitmask;
55
- }
56
71
  //# sourceMappingURL=component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAoElD;;;;;;;;GAQG;AACH,MAAM,OAAO,aAAa;IAwBxB,YAAY,KAAqB,EAAE,IAAY,EAAE,aAAqB;QAdtE;;;;WAIG;QACI,eAAU,GAAgC,SAAS,CAAC;QAUzD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAA+C;QAC1D,CAAC,IAAI,CAAC,cAAc,KAAnB,IAAI,CAAC,cAAc,GAAK,EAAE,EAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,QAAQ,CAAC,OAA+C;QAC7D,CAAC,IAAI,CAAC,iBAAiB,KAAtB,IAAI,CAAC,iBAAiB,GAAK,EAAE,EAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAA+C;QAC1D,CAAC,IAAI,CAAC,cAAc,KAAnB,IAAI,CAAC,cAAc,GAAK,EAAE,EAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AASD;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAA4B,EAAE,KAAY;IACnF,MAAM,OAAO,GAAG,IAAI,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EACL,aAAa,EACb,aAAa,GAOd,MAAM,qBAAqB,CAAC;AAE7B,6DAA6D;AAC7D,MAAM,OAAO,SAAmD,SAAQ,MAAM;IAC5E;;;;;;;;;;;;;;OAcG;IACI,KAAK,CAAC,OAAqD;QAChE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAyD,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACI,QAAQ,CAAC,OAAqD;QACnE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAyD,CAAC,CAAC;QACjF,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACI,KAAK,CAAC,OAAqD;QAChE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAyD,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,98 @@
1
+ import { BitPtr } from "./util/bitset.js";
2
+ import type { Entity, EntityClass } from "./entity/index.js";
3
+ export declare enum CleanupPolicy {
4
+ Throw = "throw",
5
+ Remove = "remove",
6
+ Delete = "delete"
7
+ }
8
+ /** A component instance. Components are plain objects created with a no-arg constructor. */
9
+ export type ComponentInstance = object;
10
+ /** A component constructor used as a component key. */
11
+ export type ComponentType<T extends ComponentInstance = ComponentInstance> = new (...args: any[]) => T;
12
+ /** A component class constructor that can be instantiated by entity.add/set. */
13
+ export type ComponentClass<T extends ComponentInstance = ComponentInstance> = new () => T;
14
+ /** A component class constructor, component eid, or entity component key. */
15
+ export type ComponentRef = number | ComponentType | EntityClass | Entity;
16
+ /**
17
+ * Lifecycle hook for a registered component class. Exposed by
18
+ * {@link World.component}.
19
+ *
20
+ * Hooks are a lightweight alternative to building a {@link System} when all
21
+ * you need is a callback on add / remove / set for a single component type.
22
+ * Component entities expose the same registration methods, so calls chain:
23
+ *
24
+ * ```ts
25
+ * world.component(Sprite)
26
+ * .onAdd((e, c) => initSprite(e, c))
27
+ * .onRemove((e, c) => destroySprite(e, c))
28
+ * .onSet((e, c) => syncSprite(e, c));
29
+ * ```
30
+ *
31
+ * Callbacks fire synchronously when the corresponding entity command is
32
+ * applied: inline outside deferred mode, or while the world drains its command
33
+ * queue inside a system / `forEach` / `defer` block.
34
+ *
35
+ * @typeParam C - Component class this hook is bound to.
36
+ */
37
+ export interface Hook<C extends ComponentInstance = ComponentInstance> {
38
+ /**
39
+ * Register a handler invoked when a component of this type is first attached
40
+ * to an entity (`entity.add(C)` or `entity.set(C, ...)` on an entity that
41
+ * does not yet have the component).
42
+ *
43
+ * @param handler - Receives the entity and freshly created component instance.
44
+ * @returns This hook, for chaining.
45
+ */
46
+ onAdd(handler: (entity: Entity, c: C) => void): Hook<C>;
47
+ /**
48
+ * Register a handler invoked when a component of this type is removed from
49
+ * an entity (explicit `entity.remove(C)` or implicit removal during
50
+ * `entity.destroy()`).
51
+ *
52
+ * @param handler - Receives the entity and component instance that was removed.
53
+ * @returns This hook, for chaining.
54
+ */
55
+ onRemove(handler: (entity: Entity, c: C) => void): Hook<C>;
56
+ /**
57
+ * Register a handler invoked when a component's data has been marked as
58
+ * changed (`entity.modified(C)`), and when
59
+ * `entity.set(C, props)` is called on an entity that already has the
60
+ * component.
61
+ *
62
+ * @param handler - Receives the entity and component instance whose data changed.
63
+ * @returns This hook, for chaining.
64
+ */
65
+ onSet(handler: (entity: Entity, c: C) => void): Hook<C>;
66
+ }
67
+ /**
68
+ * Bookkeeping record produced for each component eid.
69
+ *
70
+ * Holds the constructor, component eid, and pre-computed
71
+ * {@link BitPtr} used by archetype checks. Implements {@link Hook}, so the
72
+ * lifecycle handlers attached via `world.component(C)` are stored directly on
73
+ * the meta object.
74
+ */
75
+ export declare class ComponentMeta implements Hook<ComponentInstance> {
76
+ /** The component class constructor this meta represents. */
77
+ readonly Class: ComponentType;
78
+ /** Component entity id assigned at registration time. */
79
+ readonly eid: number;
80
+ /** Pre-computed bit-pointer into the entity archetype {@link Bitset}. */
81
+ readonly bitPtr: BitPtr;
82
+ /** Whether this component is a relationship pointing at another entity. */
83
+ readonly isRelationship: boolean;
84
+ /** Applied to entities carrying this component when this component entity is deleted. */
85
+ onDelete: CleanupPolicy;
86
+ /** Applied to entities targeting a deleted entity through this relationship. */
87
+ onDeleteTarget: CleanupPolicy;
88
+ private _usageCount;
89
+ constructor(Class: ComponentType, eid: number);
90
+ /** Number of entities currently carrying this component eid. */
91
+ get usageCount(): number;
92
+ /** @inheritdoc */
93
+ onAdd(handler: (entity: Entity, c: ComponentInstance) => void): ComponentMeta;
94
+ /** @inheritdoc */
95
+ onRemove(handler: (entity: Entity, c: ComponentInstance) => void): ComponentMeta;
96
+ /** @inheritdoc */
97
+ onSet(handler: (entity: Entity, c: ComponentInstance) => void): ComponentMeta;
98
+ }
@@ -0,0 +1,65 @@
1
+ import { BitPtr } from "./util/bitset.js";
2
+ import { Relationship } from "./relationship.js";
3
+ export var CleanupPolicy;
4
+ (function (CleanupPolicy) {
5
+ CleanupPolicy["Throw"] = "throw";
6
+ CleanupPolicy["Remove"] = "remove";
7
+ CleanupPolicy["Delete"] = "delete";
8
+ })(CleanupPolicy || (CleanupPolicy = {}));
9
+ /**
10
+ * Bookkeeping record produced for each component eid.
11
+ *
12
+ * Holds the constructor, component eid, and pre-computed
13
+ * {@link BitPtr} used by archetype checks. Implements {@link Hook}, so the
14
+ * lifecycle handlers attached via `world.component(C)` are stored directly on
15
+ * the meta object.
16
+ */
17
+ export class ComponentMeta {
18
+ constructor(Class, eid) {
19
+ /** Applied to entities carrying this component when this component entity is deleted. */
20
+ this.onDelete = CleanupPolicy.Throw;
21
+ /** Applied to entities targeting a deleted entity through this relationship. */
22
+ this.onDeleteTarget = CleanupPolicy.Remove;
23
+ /**
24
+ * @internal Peer metas of components that cannot coexist with this one on
25
+ * the same entity. Set via {@link World.setExclusiveComponents}; `undefined`
26
+ * means no restriction.
27
+ */
28
+ this._exclusive = undefined;
29
+ this._usageCount = 0;
30
+ this.Class = Class;
31
+ this.eid = eid;
32
+ this.bitPtr = new BitPtr(eid);
33
+ this.isRelationship = Class.prototype instanceof Relationship;
34
+ }
35
+ /** Number of entities currently carrying this component eid. */
36
+ get usageCount() {
37
+ return this._usageCount;
38
+ }
39
+ /** @internal */
40
+ _incrementUsage() {
41
+ this._usageCount++;
42
+ }
43
+ /** @internal */
44
+ _decrementUsage() {
45
+ if (this._usageCount > 0) {
46
+ this._usageCount--;
47
+ }
48
+ }
49
+ /** @inheritdoc */
50
+ onAdd(handler) {
51
+ (this._onAddHandlers ?? (this._onAddHandlers = [])).unshift(handler);
52
+ return this;
53
+ }
54
+ /** @inheritdoc */
55
+ onRemove(handler) {
56
+ (this._onRemoveHandlers ?? (this._onRemoveHandlers = [])).unshift(handler);
57
+ return this;
58
+ }
59
+ /** @inheritdoc */
60
+ onSet(handler) {
61
+ (this._onSetHandlers ?? (this._onSetHandlers = [])).unshift(handler);
62
+ return this;
63
+ }
64
+ }
65
+ //# sourceMappingURL=component_meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component_meta.js","sourceRoot":"","sources":["../src/component_meta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,CAAN,IAAY,aAIX;AAJD,WAAY,aAAa;IACvB,gCAAe,CAAA;IACf,kCAAiB,CAAA;IACjB,kCAAiB,CAAA;AACnB,CAAC,EAJW,aAAa,KAAb,aAAa,QAIxB;AAsED;;;;;;;GAOG;AACH,MAAM,OAAO,aAAa;IA+BxB,YAAY,KAAoB,EAAE,GAAW;QArB7C,yFAAyF;QAClF,aAAQ,GAAG,aAAa,CAAC,KAAK,CAAC;QACtC,gFAAgF;QACzE,mBAAc,GAAG,aAAa,CAAC,MAAM,CAAC;QAE7C;;;;WAIG;QACI,eAAU,GAAgC,SAAS,CAAC;QASnD,gBAAW,GAAG,CAAC,CAAC;QAGtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,SAAS,YAAY,YAAY,CAAC;IAChE,CAAC;IAED,gEAAgE;IAChE,IAAW,UAAU;QACnB,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,gBAAgB;IACT,eAAe;QACpB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,gBAAgB;IACT,eAAe;QACpB,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAAuD;QAClE,CAAC,IAAI,CAAC,cAAc,KAAnB,IAAI,CAAC,cAAc,GAAK,EAAE,EAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,QAAQ,CAAC,OAAuD;QACrE,CAAC,IAAI,CAAC,iBAAiB,KAAtB,IAAI,CAAC,iBAAiB,GAAK,EAAE,EAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAAuD;QAClE,CAAC,IAAI,CAAC,cAAc,KAAnB,IAAI,CAAC,cAAc,GAAK,EAAE,EAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
package/dist/dsl.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { type ComponentClass, ComponentClassArray, ComponentClassOrType } from "./component.js";
2
- import type { Entity } from "./entity.js";
1
+ import { type ComponentRef, type ComponentRefArray, type ComponentType } from "./component.js";
2
+ import { Entity } from "./entity/index.js";
3
+ import type { World } from "./world/index.js";
3
4
  /**
4
5
  * A predicate that decides whether a given entity belongs to a query.
5
6
  *
6
- * Pass one directly inside {@link QueryDSL} to express membership rules that
7
+ * Use `{ test: fn }` inside {@link QueryDSL} to express membership rules that
7
8
  * the structured operators cannot reach.
8
9
  */
9
10
  export type EntityTestFunc = (e: Entity) => boolean;
@@ -14,38 +15,40 @@ export type EntityTestFunc = (e: Entity) => boolean;
14
15
  * Operators can be nested arbitrarily:
15
16
  *
16
17
  * ```ts
17
- * // Position AND (Sprite OR Container):
18
+ * // Position and either Sprite or Container:
18
19
  * world.system("render").query({
19
- * AND: [Position, { OR: [Sprite, Container] }],
20
+ * all: [Position, { any: [Sprite, Container] }],
20
21
  * });
21
22
  *
22
- * // Parent has Player AND Container:
23
- * world.system("attach").query({
24
- * PARENT: { AND: [Player, Container] },
25
- * });
26
- * ```
27
- *
28
23
  * Short forms recognized by `query` / `filter`:
29
- * - A registered component class or numeric type id is shorthand for `{ HAS: [C] }`.
30
- * - An array `[A, B]` is shorthand for `{ HAS: [A, B] }`.
31
- * - An {@link EntityTestFunc} is invoked directly for fully custom logic.
24
+ * - `true` matches all entities; `false` matches no entities.
25
+ * - A registered component class or numeric type id matches entities with that component.
26
+ * - An array `[A, B]` matches entities with all listed components.
27
+ * - An empty array `[]` is shorthand for `true`.
28
+ * - `{ test: fn, watch: refs }` invokes an arbitrary predicate, rechecked for watched refs.
32
29
  *
33
- * Function values are treated as component classes only when the world already
34
- * has registered metadata for that class. Register component classes before
35
- * using them in query DSL expressions.
30
+ * Function values are component classes. Register component classes before using
31
+ * them in query DSL expressions.
36
32
  */
37
- export type QueryDSL = ComponentClassArray | ComponentClassOrType | EntityTestFunc | {
38
- HAS: ComponentClassArray | ComponentClassOrType;
33
+ export type QueryDSL = true | false | ComponentRefArray | ComponentRef | {
34
+ all: readonly QueryDSL[];
35
+ } | {
36
+ any: readonly QueryDSL[];
37
+ } | {
38
+ not: QueryDSL;
39
+ } | {
40
+ only: ComponentRefArray | ComponentRef;
39
41
  } | {
40
- HAS_ONLY: ComponentClassArray | ComponentClassOrType;
42
+ target: readonly [ComponentRef, QueryDSL];
41
43
  } | {
42
- AND: readonly QueryDSL[];
44
+ source: readonly [ComponentRef, QueryDSL];
43
45
  } | {
44
- OR: readonly QueryDSL[];
46
+ parent: QueryDSL;
45
47
  } | {
46
- NOT: QueryDSL;
48
+ children: QueryDSL;
47
49
  } | {
48
- PARENT: QueryDSL;
50
+ test: EntityTestFunc;
51
+ watch?: ComponentRefArray | ComponentRef;
49
52
  };
50
53
  /**
51
54
  * Resolve component nullability based on what was declared in `requires` (or
@@ -57,7 +60,7 @@ export type QueryDSL = ComponentClassArray | ComponentClassOrType | EntityTestFu
57
60
  * @typeParam C - Component class being injected.
58
61
  * @typeParam R - Tuple of component classes guaranteed present.
59
62
  */
60
- export type MaybeRequired<C, R extends ComponentClass[]> = C extends ComponentClass ? C extends R[number] ? InstanceType<C> : InstanceType<C> | undefined : never;
63
+ export type MaybeRequired<C, R extends ComponentType[]> = C extends ComponentType ? C extends R[number] ? InstanceType<C> : InstanceType<C> | undefined : never;
61
64
  /**
62
65
  * Statically extract the component classes that are **guaranteed present** on
63
66
  * every entity matched by a {@link QueryDSL} expression.
@@ -65,22 +68,31 @@ export type MaybeRequired<C, R extends ComponentClass[]> = C extends ComponentCl
65
68
  * Rules:
66
69
  * - Plain component class `C` → `[C]`
67
70
  * - Plain array `[A, B]` → `[A, B]`
68
- * - `{ HAS: ... }` / `{ HAS_ONLY: ... }` → recurse into the payload
69
- * - `{ AND: [q1, q2, ...] }` → concatenate each branch's extraction
70
- * - `{ OR: ... }` / `{ NOT: ... }` / `{ PARENT: ... }` → `[]` (no guarantee)
71
- * - `EntityTestFunc` / numeric type id → `[]` (opaque)
71
+ * - `true` / `false` / `[]``[]` (no guarantee)
72
+ * - `{ only: ... }` → recurse into the payload
73
+ * - `{ all: [q1, q2, ...] }` concatenate each branch's extraction
74
+ * - `{ any: ... }` / `{ not: ... }` / `{ test: ... }` → `[]` (no guarantee)
75
+ * - numeric type id → `[]` (opaque)
72
76
  *
73
77
  * @typeParam Q - Query expression to analyse.
74
78
  */
75
- export type ExtractRequired<Q> = Q extends ComponentClass ? [Q] : Q extends readonly ComponentClass[] ? Q : Q extends {
76
- HAS: infer H;
79
+ export type ExtractRequired<Q> = Q extends ComponentType ? [Q] : Q extends readonly ComponentType[] ? Q : Q extends {
80
+ only: infer H;
77
81
  } ? ExtractRequired<H> : Q extends {
78
- HAS_ONLY: infer H;
79
- } ? ExtractRequired<H> : Q extends {
80
- AND: infer A extends readonly QueryDSL[];
82
+ all: infer A extends readonly QueryDSL[];
81
83
  } ? _ExtractAndChain<A> : [];
82
84
  type _ExtractAndChain<A extends readonly QueryDSL[]> = A extends readonly [
83
85
  infer First,
84
86
  ...infer Rest extends readonly QueryDSL[]
85
87
  ] ? [...ExtractRequired<First>, ..._ExtractAndChain<Rest>] : [];
88
+ export declare function _resolveRelationship(ref: ComponentRef, world: World): number;
89
+ export declare function containsDownTerm(q: QueryDSL): boolean;
90
+ /**
91
+ * Return a deterministic FNV-1a hash for a query DSL expression.
92
+ *
93
+ * Equivalent expressions hash identically because the DSL is simplified before
94
+ * hashing. Custom predicate functions are represented by process-local function
95
+ * identity ids. Like any 32-bit hash, collisions are theoretically possible.
96
+ */
97
+ export declare function getDSLKey(q: QueryDSL, world: World): number;
86
98
  export {};