@vworlds/vecs 1.0.10 → 1.0.11

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 (43) hide show
  1. package/README.md +218 -229
  2. package/dist/command.d.ts +1 -46
  3. package/dist/component.d.ts +51 -59
  4. package/dist/component.js +31 -25
  5. package/dist/component.js.map +1 -1
  6. package/dist/dsl.d.ts +34 -26
  7. package/dist/dsl.js +46 -20
  8. package/dist/dsl.js.map +1 -1
  9. package/dist/entity.d.ts +96 -106
  10. package/dist/entity.js +261 -190
  11. package/dist/entity.js.map +1 -1
  12. package/dist/filter.d.ts +31 -23
  13. package/dist/filter.js +24 -17
  14. package/dist/filter.js.map +1 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/package.json +3 -1
  17. package/dist/phase.d.ts +5 -28
  18. package/dist/phase.js +11 -10
  19. package/dist/phase.js.map +1 -1
  20. package/dist/query.d.ts +107 -144
  21. package/dist/query.js +200 -169
  22. package/dist/query.js.map +1 -1
  23. package/dist/system.d.ts +59 -87
  24. package/dist/system.js +114 -114
  25. package/dist/system.js.map +1 -1
  26. package/dist/util/array_map.d.ts +4 -55
  27. package/dist/util/array_map.js +35 -37
  28. package/dist/util/array_map.js.map +1 -1
  29. package/dist/util/bitset.d.ts +40 -50
  30. package/dist/util/bitset.js +76 -62
  31. package/dist/util/bitset.js.map +1 -1
  32. package/dist/util/events.d.ts +14 -18
  33. package/dist/util/events.js +24 -3
  34. package/dist/util/events.js.map +1 -1
  35. package/dist/util/ordered_set.d.ts +1 -17
  36. package/dist/util/ordered_set.js +74 -25
  37. package/dist/util/ordered_set.js.map +1 -1
  38. package/dist/world.d.ts +212 -224
  39. package/dist/world.js +368 -330
  40. package/dist/world.js.map +1 -1
  41. package/eslint-rules/internal-underscore.js +60 -0
  42. package/eslint.config.js +5 -0
  43. package/package.json +3 -1
package/dist/filter.d.ts CHANGED
@@ -5,49 +5,57 @@ import { type MaybeRequired, type QueryDSL } from "./dsl.js";
5
5
  /**
6
6
  * A non-reactive, one-shot entity filter.
7
7
  *
8
- * Unlike {@link Query}, a `Filter` holds no tracked entity set and registers
9
- * nothing with the world. Every {@link forEach} call walks all world entities
10
- * and invokes the callback for those that match the predicate captured at
11
- * construction time.
8
+ * Unlike {@link Query} a `Filter` keeps no tracked entity set and registers
9
+ * nothing on the world. Each call to {@link forEach} walks all current world
10
+ * entities and invokes the callback on those that match the predicate captured
11
+ * at construction time.
12
12
  *
13
- * Create via {@link World.filter}:
13
+ * Create one through {@link World.filter}:
14
14
  *
15
15
  * ```ts
16
16
  * const f = world.filter([Position, Velocity]);
17
17
  *
18
- * // Entity only:
18
+ * // Iterate matching entities:
19
19
  * f.forEach((e) => console.log(e.eid));
20
20
  *
21
- * // With component injection:
21
+ * // ...or with component injection:
22
22
  * f.forEach([Position, Velocity], (e, [pos, vel]) => {
23
23
  * pos.x += vel.vx;
24
24
  * });
25
25
  * ```
26
26
  *
27
- * ### Type parameter `R`
28
- * Tracks which component classes are guaranteed present on every matched
29
- * entity inferred automatically from the DSL by {@link World.filter}, or
30
- * supplied manually via the optional `_guaranteed` argument. Components in `R`
31
- * appear as non-nullable in `forEach` callback tuples.
27
+ * `forEach` runs the callback inside a {@link World.defer | deferred scope}, so
28
+ * mutations made by the callback are batched and become visible after iteration
29
+ * finishes. Nesting a `forEach` inside an already-deferred block (a system, a
30
+ * `Query.forEach`, an outer `defer`) inherits the outer scope and does not
31
+ * drain on exit.
32
+ *
33
+ * @typeParam R - Component classes guaranteed present on every matched entity.
34
+ * Inferred from the DSL by {@link World.filter} when possible, or supplied
35
+ * manually via the `_guaranteed` argument. Components in `R` are non-nullable
36
+ * in `forEach` callback tuples.
32
37
  */
33
38
  export declare class Filter<R extends (typeof Component)[] = []> {
34
- private readonly world;
35
- private readonly belongs;
36
- constructor(world: World, dsl: QueryDSL);
39
+ /** World this filter reads entities from. */
40
+ readonly world: World;
41
+ private readonly _belongs;
42
+ constructor(
43
+ /** World this filter reads entities from. */
44
+ world: World, dsl: QueryDSL);
37
45
  /**
38
- * Iterate all world entities and call `callback` for each one that matches
39
- * the DSL this filter was created with.
46
+ * Walk all current world entities and call `callback` for each one that
47
+ * satisfies the filter's DSL.
40
48
  *
41
- * @param callback - Receives only the entity.
49
+ * @param callback - Receives only the matching entity.
42
50
  */
43
51
  forEach(callback: (e: Entity) => void): void;
44
52
  /**
45
- * Iterate all world entities and call `callback` for each one that matches
46
- * the DSL, with component injection.
53
+ * Walk all current world entities, call `callback` for each one that
54
+ * satisfies the filter's DSL, and inject the requested component instances.
47
55
  *
48
- * Components declared via {@link World.filter}'s DSL (or `_guaranteed`) are
49
- * non-nullable in the resolved tuple; any other requested component may be
50
- * `undefined` if the entity lacks it.
56
+ * Components covered by the filter's DSL or `_guaranteed` hint are
57
+ * non-nullable in the resolved tuple; any other component class may be
58
+ * `undefined` if the entity does not have it.
51
59
  *
52
60
  * @param components - Component classes to resolve from each matching entity.
53
61
  * @param callback - Receives the entity and a tuple of resolved component
package/dist/filter.js CHANGED
@@ -1,42 +1,49 @@
1
- import { buildEntityTest } from "./dsl.js";
1
+ import { _buildEntityTest } from "./dsl.js";
2
2
  /**
3
3
  * A non-reactive, one-shot entity filter.
4
4
  *
5
- * Unlike {@link Query}, a `Filter` holds no tracked entity set and registers
6
- * nothing with the world. Every {@link forEach} call walks all world entities
7
- * and invokes the callback for those that match the predicate captured at
8
- * construction time.
5
+ * Unlike {@link Query} a `Filter` keeps no tracked entity set and registers
6
+ * nothing on the world. Each call to {@link forEach} walks all current world
7
+ * entities and invokes the callback on those that match the predicate captured
8
+ * at construction time.
9
9
  *
10
- * Create via {@link World.filter}:
10
+ * Create one through {@link World.filter}:
11
11
  *
12
12
  * ```ts
13
13
  * const f = world.filter([Position, Velocity]);
14
14
  *
15
- * // Entity only:
15
+ * // Iterate matching entities:
16
16
  * f.forEach((e) => console.log(e.eid));
17
17
  *
18
- * // With component injection:
18
+ * // ...or with component injection:
19
19
  * f.forEach([Position, Velocity], (e, [pos, vel]) => {
20
20
  * pos.x += vel.vx;
21
21
  * });
22
22
  * ```
23
23
  *
24
- * ### Type parameter `R`
25
- * Tracks which component classes are guaranteed present on every matched
26
- * entity inferred automatically from the DSL by {@link World.filter}, or
27
- * supplied manually via the optional `_guaranteed` argument. Components in `R`
28
- * appear as non-nullable in `forEach` callback tuples.
24
+ * `forEach` runs the callback inside a {@link World.defer | deferred scope}, so
25
+ * mutations made by the callback are batched and become visible after iteration
26
+ * finishes. Nesting a `forEach` inside an already-deferred block (a system, a
27
+ * `Query.forEach`, an outer `defer`) inherits the outer scope and does not
28
+ * drain on exit.
29
+ *
30
+ * @typeParam R - Component classes guaranteed present on every matched entity.
31
+ * Inferred from the DSL by {@link World.filter} when possible, or supplied
32
+ * manually via the `_guaranteed` argument. Components in `R` are non-nullable
33
+ * in `forEach` callback tuples.
29
34
  */
30
35
  export class Filter {
31
- constructor(world, dsl) {
36
+ constructor(
37
+ /** World this filter reads entities from. */
38
+ world, dsl) {
32
39
  this.world = world;
33
- this.belongs = buildEntityTest(world, dsl);
40
+ this._belongs = _buildEntityTest(world, dsl);
34
41
  }
35
42
  forEach(componentsOrCallback, callback) {
36
43
  this.world.defer(() => {
37
44
  if (typeof componentsOrCallback === "function") {
38
45
  this.world.entities.forEach((e) => {
39
- if (this.belongs(e)) {
46
+ if (this._belongs(e)) {
40
47
  componentsOrCallback(e);
41
48
  }
42
49
  });
@@ -44,7 +51,7 @@ export class Filter {
44
51
  else {
45
52
  const types = componentsOrCallback.map((C) => this.world.getComponentType(C));
46
53
  this.world.entities.forEach((e) => {
47
- if (!this.belongs(e)) {
54
+ if (!this._belongs(e)) {
48
55
  return;
49
56
  }
50
57
  const resolved = types.map((t) => e.get(t));
@@ -1 +1 @@
1
- {"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAA0D,MAAM,UAAU,CAAC;AAEnG;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,OAAO,MAAM;IAGjB,YACmB,KAAY,EAC7B,GAAa;QADI,UAAK,GAAL,KAAK,CAAO;QAG7B,IAAI,CAAC,OAAO,GAAG,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IA2BM,OAAO,CACZ,oBAA6D,EAC7D,QAAoF;QAEpF,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE;YACpB,IAAI,OAAO,oBAAoB,KAAK,UAAU,EAAE;gBAC9C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;oBAChC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;wBACnB,oBAAoB,CAAC,CAAC,CAAC,CAAC;qBACzB;gBACH,CAAC,CAAC,CAAC;aACJ;iBAAM;gBACL,MAAM,KAAK,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC9E,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;oBAChC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;wBACpB,OAAO;qBACR;oBACD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC5C,QAAS,CAAC,CAAC,EAAE,QAAe,CAAC,CAAC;gBAChC,CAAC,CAAC,CAAC;aACJ;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAA0D,MAAM,UAAU,CAAC;AAEpG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,OAAO,MAAM;IAGjB;IACE,6CAA6C;IAC7B,KAAY,EAC5B,GAAa;QADG,UAAK,GAAL,KAAK,CAAO;QAG5B,IAAI,CAAC,QAAQ,GAAG,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/C,CAAC;IA2BM,OAAO,CACZ,oBAA6D,EAC7D,QAAoF;QAEpF,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE;YACpB,IAAI,OAAO,oBAAoB,KAAK,UAAU,EAAE;gBAC9C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;oBAChC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;wBACpB,oBAAoB,CAAC,CAAC,CAAC,CAAC;qBACzB;gBACH,CAAC,CAAC,CAAC;aACJ;iBAAM;gBACL,MAAM,KAAK,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC9E,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;oBAChC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;wBACrB,OAAO;qBACR;oBACD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC5C,QAAS,CAAC,CAAC,EAAE,QAAe,CAAC,CAAC;gBAChC,CAAC,CAAC,CAAC;aACJ;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { type System } from "./system.js";
1
+ export { type System, type SystemQuery } from "./system.js";
2
2
  export { Query } from "./query.js";
3
3
  export { World } from "./world.js";
4
4
  export { Filter } from "./filter.js";
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vworlds/vecs",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -12,6 +12,8 @@
12
12
  "test": "vitest run",
13
13
  "test:watch": "vitest",
14
14
  "lint": "eslint src/ tests/",
15
+ "typecheck": "tsc --noEmit",
16
+ "format:check": "prettier --check \"**/*.{ts,md}\"",
15
17
  "prepare": "husky"
16
18
  },
17
19
  "devDependencies": {
package/dist/phase.d.ts CHANGED
@@ -1,32 +1,9 @@
1
- import { type System } from "./system.js";
2
1
  import { type World } from "./world.js";
3
2
  /**
4
- * A named, ordered bucket of {@link System | systems} within the world's
5
- * update pipeline.
3
+ * Public interface for a pipeline phase, returned by {@link World.addPhase}.
6
4
  *
7
- * Created internally by {@link World.addPhase}. The systems in a phase run in
8
- * the order they were registered. Between each system run the world flushes
9
- * pending archetype changes, so `enter` / `exit` callbacks are always
10
- * delivered before the next system executes.
11
- *
12
- * @internal The concrete class is not part of the public API. Use
13
- * {@link IPhase} to refer to phases in user code.
14
- */
15
- export declare class Phase {
16
- /** Name used to look up the phase in the pipeline. */
17
- readonly name: string;
18
- world: World;
19
- /** Systems that belong to this phase, in execution order. */
20
- systems: System[];
21
- constructor(
22
- /** Name used to look up the phase in the pipeline. */
23
- name: string, world: World);
24
- }
25
- /**
26
- * Public interface for a pipeline phase returned by {@link World.addPhase}.
27
- *
28
- * Pass an `IPhase` to {@link System.phase} to assign a system to that phase,
29
- * or to {@link World.runPhase} to execute it:
5
+ * Pass an `IPhase` to {@link System.phase} to assign a system to the phase, or
6
+ * to {@link World.runPhase} to execute the phase:
30
7
  *
31
8
  * ```ts
32
9
  * const preUpdate = world.addPhase("preupdate");
@@ -40,8 +17,8 @@ export declare class Phase {
40
17
  * ```
41
18
  */
42
19
  export interface IPhase {
43
- /** The name this phase was registered under. */
20
+ /** Name this phase was registered under. */
44
21
  get name(): string;
45
- /** The world that owns this phase. */
22
+ /** World that owns this phase. */
46
23
  get world(): World;
47
24
  }
package/dist/phase.js CHANGED
@@ -1,22 +1,23 @@
1
1
  /**
2
- * A named, ordered bucket of {@link System | systems} within the world's
3
- * update pipeline.
2
+ * Concrete implementation of {@link IPhase}: a named, ordered bucket of
3
+ * {@link System | systems} within a world's update pipeline.
4
4
  *
5
- * Created internally by {@link World.addPhase}. The systems in a phase run in
6
- * the order they were registered. Between each system run the world flushes
7
- * pending archetype changes, so `enter` / `exit` callbacks are always
8
- * delivered before the next system executes.
5
+ * Created by {@link World.addPhase}. Systems run in the order they were added
6
+ * to the phase. Between systems the world drains pending commands so each
7
+ * system observes a consistent view of the world.
9
8
  *
10
- * @internal The concrete class is not part of the public API. Use
11
- * {@link IPhase} to refer to phases in user code.
9
+ * @internal The class itself is not part of the public API; user code should
10
+ * refer to phases via {@link IPhase}.
12
11
  */
13
12
  export class Phase {
14
13
  constructor(
15
14
  /** Name used to look up the phase in the pipeline. */
16
- name, world) {
15
+ name,
16
+ /** World that owns this phase. */
17
+ world) {
17
18
  this.name = name;
18
19
  this.world = world;
19
- /** Systems that belong to this phase, in execution order. */
20
+ /** Systems registered in this phase, in execution order. */
20
21
  this.systems = [];
21
22
  }
22
23
  }
package/dist/phase.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"phase.js","sourceRoot":"","sources":["../src/phase.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,KAAK;IAIhB;IACE,sDAAsD;IACtC,IAAY,EACrB,KAAY;QADH,SAAI,GAAJ,IAAI,CAAQ;QACrB,UAAK,GAAL,KAAK,CAAO;QANrB,6DAA6D;QACtD,YAAO,GAAa,EAAE,CAAC;IAM3B,CAAC;CACL"}
1
+ {"version":3,"file":"phase.js","sourceRoot":"","sources":["../src/phase.ts"],"names":[],"mappings":"AA2BA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,KAAK;IAIhB;IACE,sDAAsD;IACtC,IAAY;IAC5B,kCAAkC;IAClB,KAAY;QAFZ,SAAI,GAAJ,IAAI,CAAQ;QAEZ,UAAK,GAAL,KAAK,CAAO;QAP9B,4DAA4D;QACrD,YAAO,GAAa,EAAE,CAAC;IAO3B,CAAC;CACL"}