@vworlds/vecs 1.0.19 → 1.0.21

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 (145) hide show
  1. package/README.md +51 -48
  2. package/dist/component.d.ts +5 -2
  3. package/dist/component.js +4 -57
  4. package/dist/component.js.map +1 -1
  5. package/dist/component_meta.d.ts +15 -8
  6. package/dist/component_meta.js +6 -4
  7. package/dist/component_meta.js.map +1 -1
  8. package/dist/dsl.d.ts +56 -11
  9. package/dist/dsl.js +21 -31
  10. package/dist/dsl.js.map +1 -1
  11. package/dist/entity/entity.base.d.ts +4 -3
  12. package/dist/entity/entity.base.js +4 -4
  13. package/dist/entity/entity.base.js.map +1 -1
  14. package/dist/entity/entity.components.d.ts +16 -7
  15. package/dist/entity/entity.components.js +48 -23
  16. package/dist/entity/entity.components.js.map +1 -1
  17. package/dist/entity/entity.d.ts +5 -1
  18. package/dist/entity/entity.js +5 -0
  19. package/dist/entity/entity.js.map +1 -1
  20. package/dist/entity/entity.lifecycle.js +25 -25
  21. package/dist/entity/entity.lifecycle.js.map +1 -1
  22. package/dist/entity/entity.queries.js +0 -6
  23. package/dist/entity/entity.queries.js.map +1 -1
  24. package/dist/entity/entity.relationships.d.ts +1 -1
  25. package/dist/entity/entity.relationships.js +7 -5
  26. package/dist/entity/entity.relationships.js.map +1 -1
  27. package/dist/entity/index.d.ts +1 -1
  28. package/dist/entity/index.js.map +1 -1
  29. package/dist/filter.d.ts +6 -6
  30. package/dist/filter.js +2 -1
  31. package/dist/filter.js.map +1 -1
  32. package/dist/index.d.ts +8 -4
  33. package/dist/index.js +5 -3
  34. package/dist/index.js.map +1 -1
  35. package/dist/inject.d.ts +18 -17
  36. package/dist/inject.js +34 -34
  37. package/dist/inject.js.map +1 -1
  38. package/dist/module.d.ts +0 -2
  39. package/dist/module.js +0 -3
  40. package/dist/module.js.map +1 -1
  41. package/dist/modules/relationship_types.d.ts +34 -0
  42. package/dist/modules/relationship_types.js +36 -0
  43. package/dist/modules/relationship_types.js.map +1 -0
  44. package/dist/modules/relationships.d.ts +24 -0
  45. package/dist/modules/relationships.js +82 -0
  46. package/dist/modules/relationships.js.map +1 -0
  47. package/dist/modules/singleton.js +1 -2
  48. package/dist/modules/singleton.js.map +1 -1
  49. package/dist/package.json +1 -1
  50. package/dist/query/callbacks.d.ts +17 -0
  51. package/dist/query/callbacks.js +113 -0
  52. package/dist/query/callbacks.js.map +1 -0
  53. package/dist/query/constants.d.ts +1 -0
  54. package/dist/query/constants.js +2 -0
  55. package/dist/query/constants.js.map +1 -0
  56. package/dist/query/{query.03.tracking.d.ts → group.d.ts} +11 -9
  57. package/dist/query/group.js +31 -0
  58. package/dist/query/group.js.map +1 -0
  59. package/dist/query/grouped_query.d.ts +26 -0
  60. package/dist/query/grouped_query.js +121 -0
  61. package/dist/query/grouped_query.js.map +1 -0
  62. package/dist/query/grouped_query_registry.d.ts +4 -0
  63. package/dist/query/grouped_query_registry.js +11 -0
  64. package/dist/query/grouped_query_registry.js.map +1 -0
  65. package/dist/query/grouping.d.ts +24 -0
  66. package/dist/query/{query.07.groups.js → grouping.js} +29 -60
  67. package/dist/query/grouping.js.map +1 -0
  68. package/dist/query/index.d.ts +6 -6
  69. package/dist/query/index.js +6 -4
  70. package/dist/query/index.js.map +1 -1
  71. package/dist/query/query.d.ts +58 -28
  72. package/dist/query/query.js +327 -88
  73. package/dist/query/query.js.map +1 -1
  74. package/dist/system.d.ts +18 -34
  75. package/dist/system.js +33 -49
  76. package/dist/system.js.map +1 -1
  77. package/dist/terms/all_term.d.ts +2 -6
  78. package/dist/terms/all_term.js +2 -7
  79. package/dist/terms/all_term.js.map +1 -1
  80. package/dist/terms/any_term.d.ts +2 -6
  81. package/dist/terms/any_term.js +2 -7
  82. package/dist/terms/any_term.js.map +1 -1
  83. package/dist/terms/build.d.ts +9 -6
  84. package/dist/terms/build.js +17 -14
  85. package/dist/terms/build.js.map +1 -1
  86. package/dist/terms/component_term.d.ts +3 -3
  87. package/dist/terms/component_term.js.map +1 -1
  88. package/dist/terms/composite_build.d.ts +32 -0
  89. package/dist/terms/composite_build.js +28 -0
  90. package/dist/terms/composite_build.js.map +1 -0
  91. package/dist/terms/only_term.d.ts +3 -3
  92. package/dist/terms/only_term.js.map +1 -1
  93. package/dist/terms/predicate_term.d.ts +3 -3
  94. package/dist/terms/predicate_term.js +3 -3
  95. package/dist/terms/predicate_term.js.map +1 -1
  96. package/dist/terms/target_term.d.ts +3 -2
  97. package/dist/terms/target_term.js +11 -17
  98. package/dist/terms/target_term.js.map +1 -1
  99. package/dist/util/dense_set.js +1 -1
  100. package/dist/util/id_pool.d.ts +2 -0
  101. package/dist/util/id_pool.js +10 -0
  102. package/dist/util/id_pool.js.map +1 -1
  103. package/dist/util/ordered_set.js +15 -10
  104. package/dist/util/ordered_set.js.map +1 -1
  105. package/dist/world/world.components.d.ts +5 -4
  106. package/dist/world/world.components.js +16 -16
  107. package/dist/world/world.components.js.map +1 -1
  108. package/dist/world/world.entities.d.ts +2 -2
  109. package/dist/world/world.entities.js.map +1 -1
  110. package/dist/world/world.js +2 -4
  111. package/dist/world/world.js.map +1 -1
  112. package/dist/world/world.modules.d.ts +2 -2
  113. package/dist/world/world.modules.js +6 -1
  114. package/dist/world/world.modules.js.map +1 -1
  115. package/dist/world/world.pools.d.ts +2 -1
  116. package/dist/world/world.pools.js.map +1 -1
  117. package/dist/world/world.queries.d.ts +3 -5
  118. package/dist/world/world.queries.js +11 -8
  119. package/dist/world/world.queries.js.map +1 -1
  120. package/package.json +1 -1
  121. package/dist/query/query.00.base.d.ts +0 -23
  122. package/dist/query/query.00.base.js +0 -77
  123. package/dist/query/query.00.base.js.map +0 -1
  124. package/dist/query/query.01.reactive.d.ts +0 -7
  125. package/dist/query/query.01.reactive.js +0 -58
  126. package/dist/query/query.01.reactive.js.map +0 -1
  127. package/dist/query/query.02.lifecycle.d.ts +0 -6
  128. package/dist/query/query.02.lifecycle.js +0 -63
  129. package/dist/query/query.02.lifecycle.js.map +0 -1
  130. package/dist/query/query.03.tracking.js +0 -31
  131. package/dist/query/query.03.tracking.js.map +0 -1
  132. package/dist/query/query.04.callbacks.d.ts +0 -14
  133. package/dist/query/query.04.callbacks.js +0 -65
  134. package/dist/query/query.04.callbacks.js.map +0 -1
  135. package/dist/query/query.05.updates.d.ts +0 -14
  136. package/dist/query/query.05.updates.js +0 -81
  137. package/dist/query/query.05.updates.js.map +0 -1
  138. package/dist/query/query.06.predicate.d.ts +0 -13
  139. package/dist/query/query.06.predicate.js +0 -40
  140. package/dist/query/query.06.predicate.js.map +0 -1
  141. package/dist/query/query.07.groups.d.ts +0 -41
  142. package/dist/query/query.07.groups.js.map +0 -1
  143. package/dist/relationship.d.ts +0 -19
  144. package/dist/relationship.js +0 -18
  145. package/dist/relationship.js.map +0 -1
package/README.md CHANGED
@@ -74,7 +74,7 @@ const cleanup: IPhase = world.addPhase("cleanup");
74
74
  world
75
75
  .system("Move")
76
76
  .phase(update)
77
- .requires(Position, Velocity)
77
+ .with(Position, Velocity)
78
78
  .each([Position, Velocity], (e, [pos, vel]) => {
79
79
  pos.x += vel.vx;
80
80
  pos.y += vel.vy;
@@ -85,7 +85,7 @@ world
85
85
  world
86
86
  .system("Health")
87
87
  .phase(cleanup)
88
- .requires(Health)
88
+ .with(Health)
89
89
  .update(Health, (entity, health) => {
90
90
  if (health.hp <= 0) {
91
91
  entity.destroy();
@@ -145,7 +145,7 @@ const world = new World();
145
145
 
146
146
  #### Component registration
147
147
 
148
- Components are ordinary classes. They do not inherit from a vecs base class, and vecs constructs them with `new ComponentClass()`, so constructors should take no parameters. Register every component class before using it in `add`, `set`, `get`, `requires`, `query`, `filter`, hook registration, or `setExclusiveComponents`.
148
+ Components are ordinary classes. They do not inherit from a vecs base class, and vecs constructs them with `new ComponentClass()`, so constructors should take no parameters. Register every component class before using it in `add`, `set`, `get`, `with`, `filter`, hook registration, or `setExclusiveComponents`.
149
149
 
150
150
  ```ts
151
151
  class Position {
@@ -160,7 +160,7 @@ const positionComponent = world.component(Position);
160
160
  world.component(Position, 42);
161
161
 
162
162
  // Access component metadata (numeric id, cleanup policy, etc.):
163
- const meta = world.component(Position).ownMeta; // ComponentMeta
163
+ const componentMeta = world.component(Position).meta; // ComponentMeta
164
164
 
165
165
  // Give the component a name so it can be looked up by string later:
166
166
  world.component(Position).name = "Position";
@@ -222,7 +222,7 @@ world.component("Position"); // resolves the same component entity
222
222
 
223
223
  #### Component entity deletion cleanup
224
224
 
225
- Every component key is backed by a component entity. Destroying that component entity is controlled by `world.component(C).ownMeta.onDelete`:
225
+ Every component key is backed by a component entity. Destroying that component entity is controlled by `world.component(C).meta.onDelete`:
226
226
 
227
227
  | Policy | Meaning |
228
228
  | ---------------------- | -------------------------------------------------------------------------------------------------- |
@@ -233,7 +233,7 @@ Every component key is backed by a component entity. Destroying that component e
233
233
  ```ts
234
234
  import { CleanupPolicy } from "@vworlds/vecs";
235
235
 
236
- world.component(Temporary).ownMeta.onDelete = CleanupPolicy.Remove;
236
+ world.component(Temporary).meta.onDelete = CleanupPolicy.Remove;
237
237
  world.component(Temporary).destroy(); // strips Temporary from all carriers
238
238
  ```
239
239
 
@@ -280,7 +280,7 @@ Systems with no explicit phase are placed in the built-in `"update"` phase.
280
280
  world
281
281
  .system("MySystem")
282
282
  .phase("update")
283
- .requires(A, B)
283
+ .with(A, B)
284
284
  .enter(...)
285
285
  .update(...)
286
286
  .each(...)
@@ -353,7 +353,7 @@ Tick source objects and systems can both be used as sources. Disabling a source
353
353
  ```ts
354
354
  const enemies = world
355
355
  .query("Enemies")
356
- .requires(Enemy, Health)
356
+ .with(Enemy, Health)
357
357
  .enter((e) => console.log("enemy spawned", e.eid));
358
358
 
359
359
  world.start();
@@ -380,7 +380,9 @@ world.filter({ all: [Position, Velocity] }).forEach([Position, Velocity], (e, [p
380
380
  });
381
381
 
382
382
  // Manual hint for queries the type extractor can't see through:
383
- world.filter({ any: [Position, Velocity] }, [Position]).forEach([Position], (e, [pos]) => pos.x);
383
+ world
384
+ .filter({ with: { any: [Position, Velocity] }, hint: [Position] })
385
+ .forEach([Position], (e, [pos]) => pos.x);
384
386
  ```
385
387
 
386
388
  A `Filter` requires no name, no `world.start()`, and no `destroy()` — create it anywhere and discard freely.
@@ -433,7 +435,7 @@ entity.get(Position) === shared; // true
433
435
  | Shared instances possible | `entity.attach(instance)` stores the exact passed object; code should use the entity passed by vecs callbacks. |
434
436
  | Manual dirty marking | After mutating fields directly, call `entity.modified(C)` to notify hooks, queries, and systems. |
435
437
 
436
- Use `world.component(C).ownMeta` when you need metadata such as the numeric type id or component name. Metadata is world-specific.
438
+ Use `world.component(C).meta` when you need metadata such as the numeric type id or component name. Metadata is world-specific.
437
439
 
438
440
  ---
439
441
 
@@ -495,14 +497,14 @@ item.parent(EquippedBy); // player
495
497
  player.children(EquippedBy).has(item); // true
496
498
  ```
497
499
 
498
- Relationship target cleanup is controlled by `ownMeta.onDeleteTarget`:
500
+ Relationship target cleanup is controlled by `meta.onDeleteTarget`:
499
501
 
500
502
  | Policy | Meaning |
501
503
  | ---------------------- | -------------------------------------------------------------------------------------------- |
502
504
  | `CleanupPolicy.Remove` | Default. When a target is destroyed, remove the relationship component from each source. |
503
505
  | `CleanupPolicy.Delete` | When a target is destroyed, destroy each source entity that targets it through the relation. |
504
506
 
505
- `ChildOf` is registered by every `World` and uses `CleanupPolicy.Delete`. Custom relationships default to `Remove`; set `world.component(MyRelationship).ownMeta.onDeleteTarget = CleanupPolicy.Delete` if target deletion should cascade.
507
+ `ChildOf` is registered by every `World` and uses `CleanupPolicy.Delete`. Custom relationships default to `Remove`; set `world.component(MyRelationship).meta.onDeleteTarget = CleanupPolicy.Delete` if target deletion should cascade.
506
508
 
507
509
  `onDeleteTarget` is independent from `onDelete`: `onDeleteTarget` runs when a relationship target is destroyed, while `onDelete` runs when the relationship component entity itself is destroyed.
508
510
 
@@ -511,8 +513,8 @@ Retarget relationships with `entity.set(RelationshipClass, { target })`. `entity
511
513
  Relationship queries use `target` to follow a relationship from the candidate entity to its target and test that target with another DSL expression. Use `parent` for the built-in `ChildOf` hierarchy:
512
514
 
513
515
  ```ts
514
- world.query("body-friends").query({ all: [Body, { target: [FriendOf, [Position, Velocity]] }] });
515
- world.query("positioned-children").query({ all: [Position, { parent: Body }] });
516
+ world.query("body-friends").with({ all: [Body, { target: [FriendOf, [Position, Velocity]] }] });
517
+ world.query("positioned-children").with({ all: [Position, { parent: Body }] });
516
518
  ```
517
519
 
518
520
  Tracked queries stay live when either side changes. Adding or removing `FriendOf` on the candidate re-routes the candidate normally; adding or removing `Position` / `Velocity` on the target also refreshes every candidate that points at that target. Nested `target` works the same way across multiple hops.
@@ -530,7 +532,7 @@ Component injection supports lowercase `down` in `forEach` and system `each` inj
530
532
  ```ts
531
533
  world
532
534
  .query("parents")
533
- .requires(Body)
535
+ .with(Body)
534
536
  .forEach([Body, { down: [ChildOf, [Position]] }], (parent, [body, childPos]) => {
535
537
  // One call per ChildOf child of parent. childPos is undefined when that child lacks Position.
536
538
  });
@@ -547,17 +549,18 @@ Two details matter:
547
549
 
548
550
  Systems are created via `world.system(name)` and configured through a fluent builder. Every method returns `this` for chaining. `System` extends `Query`, so the membership / enter / exit / update / sort APIs are shared.
549
551
 
550
- #### `.requires(...components)` and `.query(q)`
552
+ #### `.with(...specs)`
551
553
 
552
554
  Declare which entities the system tracks.
553
555
 
554
556
  ```ts
555
- .requires(Position, Velocity) // shorthand for [Position, Velocity]
556
- .query([Position, Velocity]) // explicit component list
557
- .query({ all: [Position, { any: [Sprite, Container] }] }) // compound
558
- .query({ not: Invisible })
559
- .query({ target: [FriendOf, Position] }) // relationship target has Position
560
- .query({ parent: Body }) // ChildOf target has Body
557
+ .with(Position, Velocity) // explicit component list
558
+ .with([Position, Velocity]) // array shorthand
559
+ .with({ all: [Position, { any: [Sprite, Container] }] }) // compound
560
+ .with({ not: Invisible })
561
+ .without(Invisible) // shorthand for .with({ not: Invisible })
562
+ .with({ target: [FriendOf, Position] }) // relationship target has Position
563
+ .with({ parent: Body }) // ChildOf target has Body
561
564
  ```
562
565
 
563
566
  **Query operators:**
@@ -578,31 +581,31 @@ Declare which entities the system tracks.
578
581
 
579
582
  `target` and `source` use tuple form only: `{ target: [RelationshipClass, innerDSL] }` / `{ source: [RelationshipClass, innerDSL] }`. The first element must be a component that extends `Relationship`; passing a normal component throws. `target` evaluates the inner DSL against the relationship target; `source` evaluates it against each child/source and matches when at least one child/source matches. Because `source` and `children` are non-reactive, use them with `world.filter(...)`, not tracked queries or systems.
580
583
 
581
- Component injection also supports lowercase relationship markers. `up` works in `forEach`, `each`, `enter`, and `exit` injection lists. It follows the relationship target and flattens the requested target components into the callback tuple:
584
+ Component injection also supports lowercase relationship markers. `target` works in `forEach`, `each`, `enter`, and `exit` injection lists. It follows the relationship target and flattens the requested target components into the callback tuple:
582
585
 
583
586
  ```ts
584
587
  world
585
588
  .query("friends")
586
- .query({ target: [FriendOf, Position] })
587
- .forEach([Body, { up: [FriendOf, [Position, Velocity]] }], (e, [body, pos, vel]) => {
589
+ .with({ target: [FriendOf, Position] })
590
+ .forEach([Body, { target: [FriendOf, [Position, Velocity]] }], (e, [body, pos, vel]) => {
588
591
  // body is from e; pos and vel are from e.parent(FriendOf)
589
592
  // target-side injected components are undefined if the target is absent or lacks them.
590
593
  });
591
594
  ```
592
595
 
593
- On `exit`, direct component injection is snapshot-stable when the exiting component was just removed. `up` injection resolves the target live at callback time, so target-side slots can be `undefined` if the exit was caused by the target losing that component.
596
+ On `exit`, direct component injection is snapshot-stable when the exiting component was just removed. `target` injection resolves the target live at callback time, so target-side slots can be `undefined` if the exit was caused by the target losing that component.
594
597
 
595
598
  Lowercase `down` is allowed only in `forEach` and system `each`, where fan-out has a clear meaning. Only one `down` marker is allowed per injection tuple.
596
599
 
597
600
  #### Iter cursor
598
601
 
599
- Pass `Iter` as the first argument to `each`, `forEach`, `enter`, `exit`, `update`, or `sort` to receive a reusable cursor object instead of the bare entity. The cursor exposes:
602
+ Pass `Iter` as the first argument to `each`, `forEach`, `enter`, `exit`, `update`, or `orderBy` to receive a reusable cursor object instead of the bare entity. The cursor exposes:
600
603
 
601
604
  - `it.entity` — the visited entity.
602
- - `it.src` — a same-length array of source entities: the visited entity for a directly-injected component, the relationship target for an `up`-injected one, or the specific child for a `down`-injected one.
605
+ - `it.src` — a same-length array of source entities: the visited entity for a directly-injected component, the relationship target for a `target`-injected one, or the specific child for a `down`-injected one.
603
606
 
604
607
  ```ts
605
- system.each(Iter, [Body, { up: [ChildOf, [Position]] }], (it, [body, pos]) => {
608
+ system.each(Iter, [Body, { target: [ChildOf, [Position]] }], (it, [body, pos]) => {
606
609
  it.entity; // the visited entity
607
610
  it.src[0]; // entity `body` was read from (the visited entity)
608
611
  it.src[1]; // entity `pos` was read from (the ChildOf target)
@@ -611,14 +614,14 @@ system.each(Iter, [Body, { up: [ChildOf, [Position]] }], (it, [body, pos]) => {
611
614
 
612
615
  When `Iter` is **not** requested, the original code path runs with zero per-entity overhead. Dispatch to the cursor or non-cursor path happens once at setup time — not per entity. A single `Iter` instance is mutated before each callback; read what you need inside the callback but do not retain the cursor or its `src` array across callbacks.
613
616
 
614
- `enter` and `exit` allocate a fresh `Iter` per event (they fire reentrantly during command routing). `each` / `forEach` / `update` reuse a single `Iter` instance for the whole pass; `sort` reuses two (one per side of the comparison). Because a plain `Query.update` callback fires synchronously during command routing, a nested mutation triggered from inside it can re-enter `update` and overwrite that reused cursor and tuple mid-callback — snapshot any `it`, `it.src`, or tuple values you need before triggering further mutations.
617
+ `enter` and `exit` allocate a fresh `Iter` per event (they fire reentrantly during command routing). `each` / `forEach` / `update` reuse a single `Iter` instance for the whole pass; `orderBy` reuses two (one per side of the comparison). Because a plain `Query.update` callback fires synchronously during command routing, a nested mutation triggered from inside it can re-enter `update` and overwrite that reused cursor and tuple mid-callback — snapshot any `it`, `it.src`, or tuple values you need before triggering further mutations.
615
618
 
616
619
  Class-valued query terms are components. Register component classes before using them in a `QueryDSL`; an unregistered class throws. Use `{ test: fn }` for arbitrary predicate functions.
617
620
 
618
- **Type inference.** `requires()` records the listed classes as a type parameter `R` on the system. Callbacks in `.sort()`, `.each()`, and `.update()` injection treat those components as non-nullable — no `!` needed. For complex `query()` expressions the type system can't introspect, supply a `_guaranteed` second argument:
621
+ **Type inference.** `with()` records inferrable component classes as a type parameter `R` on the system. Callbacks in `.orderBy()`, `.each()`, and `.update()` injection treat those components as non-nullable — no `!` needed. For complex `with()` expressions the type system can't introspect, supply a `hint` field:
619
622
 
620
623
  ```ts
621
- .query({ all: [Position, Velocity] }, [Position, Velocity])
624
+ .with({ with: { all: [Position, Velocity] }, hint: [Position, Velocity] })
622
625
  .each([Position, Velocity], (e, [pos, vel]) => {
623
626
  pos.x += vel.vx; // pos and vel are non-null
624
627
  });
@@ -646,7 +649,7 @@ Fires once when an entity first matches the system.
646
649
 
647
650
  #### `.exit(callback)` / `.exit(inject, callback)`
648
651
 
649
- Fires when an entity leaves the system (component removed or entity destroyed). Direct components removed in the same frame are still resolvable in `inject`; `up` injection resolves relationship targets live.
652
+ Fires when an entity leaves the system (component removed or entity destroyed). Direct components removed in the same frame are still resolvable in `inject`; `target` injection resolves relationship targets live.
650
653
 
651
654
  ```ts
652
655
  .exit([Sprite], (e, [sprite]) => sprite.destroy());
@@ -664,34 +667,34 @@ Fires when `entity.modified(ComponentClass)` is called for the watched component
664
667
  });
665
668
  ```
666
669
 
667
- If `query()` has not been called, `update` automatically expands the implicit component predicate to require the watched component.
670
+ If `with()` has not been called, `update` automatically expands the implicit component predicate to require the watched component.
668
671
 
669
672
  #### `.each(components, callback)`
670
673
 
671
674
  Fires every tick for **every tracked entity**, regardless of whether anything changed. Use it for per-entity logic that must run every frame. Implies `.track()`. Only one `each` per system.
672
675
 
673
676
  ```ts
674
- .requires(Position, Velocity)
677
+ .with(Position, Velocity)
675
678
  .each([Position, Velocity], (e, [pos, vel]) => {
676
679
  pos.x += vel.vx;
677
680
  });
678
681
  ```
679
682
 
680
- #### `.sort(components, compare)`
683
+ #### `.orderBy(components, compare)`
681
684
 
682
685
  Store matched entities in a custom order determined by `compare`. Implies `.track()`. Iterating the system, `forEach`, and `each` walks entities in sorted order.
683
686
 
684
687
  ```ts
685
688
  world
686
689
  .system("Render")
687
- .requires(Position, Sprite)
688
- .sort([Position], (_entityA, [posA], _entityB, [posB]) => posA.z - posB.z)
690
+ .with(Position, Sprite)
691
+ .orderBy([Position], (_entityA, [posA], _entityB, [posB]) => posA.z - posB.z)
689
692
  .each([Position, Sprite], (e, [pos, sprite]) => sprite.draw(pos.x, pos.y));
690
693
  ```
691
694
 
692
695
  #### `.track()`
693
696
 
694
- Enable entity tracking without an `each` callback — exposes matched entities via `system.count`, `system.has(e)`, and direct iteration. `each` and `sort` imply `track` automatically. When called after `world.start()`, immediately backfills existing matched entities.
697
+ Enable entity tracking without an `each` callback — exposes matched entities via `system.count`, `system.has(e)`, and direct iteration. `each` and `orderBy` imply `track` automatically. When called after `world.start()`, immediately backfills existing matched entities.
695
698
 
696
699
  #### `.run(callback)`
697
700
 
@@ -708,7 +711,7 @@ Fires every tick when the system's phase runs, regardless of entity state. Use f
708
711
  Pause and resume a system at runtime. While disabled the system is effectively invisible: the inbox is cleared immediately, any new `enter`, `exit`, or `update` events are silently dropped, `run` and `each` callbacks do not fire, and the system skips its `_run` entirely. Entity membership in the underlying query is still maintained, so the tracked set remains correct and the system resumes cleanly when re-enabled. Events that occurred while the system was disabled are **not** replayed.
709
712
 
710
713
  ```ts
711
- const ai = world.system("AI").requires(Enemy).run(tickAI);
714
+ const ai = world.system("AI").with(Enemy).run(tickAI);
712
715
 
713
716
  // Pause AI processing during a cutscene:
714
717
  ai.disable();
@@ -732,8 +735,8 @@ Permanently remove this system from the world. Calls `disable()` first (clearing
732
735
  ```ts
733
736
  const projectiles = world
734
737
  .query("Projectiles")
735
- .requires(Position, Velocity)
736
- .sort([Position], (_entityA, [a], _entityB, [b]) => a.z - b.z)
738
+ .with(Position, Velocity)
739
+ .orderBy([Position], (_entityA, [a], _entityB, [b]) => a.z - b.z)
737
740
  .enter([Position], (e, [pos]) => {
738
741
  pos.x = spawnX;
739
742
  });
@@ -747,12 +750,12 @@ console.log(projectiles.count, "active projectiles");
747
750
 
748
751
  | Method | Description |
749
752
  | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
750
- | `.requires(...components)` | Set the membership predicate to require all listed components and start tracking. |
751
- | `.query(expr, _guaranteed?)` | Set the membership predicate using a `QueryDSL` expression. |
753
+ | `.with(...specs)` | Add membership predicates using `QuerySpec` expressions. |
754
+ | `.without(dsl)` | Add a negated membership predicate; shorthand for `.with({ not: dsl })`. |
752
755
  | `.enter(callback)` / `.enter(inject, callback)` | Fires when an entity joins the query. |
753
756
  | `.exit(callback)` / `.exit(inject, callback)` | Fires when an entity leaves the query. |
754
757
  | `.update(C, callback)` / `.update(C, inject, callback)` | Fires when `C` is modified on a tracked entity. Callback receives `(entity, component, injected?)`. |
755
- | `.sort(components, compare)` | Store matched entities in sorted order. Comparator receives `(entityA, tupleA, entityB, tupleB)`. |
758
+ | `.orderBy(components, compare)` | Store matched entities in sorted order. Comparator receives `(entityA, tupleA, entityB, tupleB)`. |
756
759
  | `.track()` | Enable tracking. Backfills when called after `start()`. |
757
760
  | `.belongs(e)` | Returns `true` if the entity satisfies the predicate. |
758
761
  | `.count` | Number of currently tracked entities. |
@@ -767,7 +770,7 @@ console.log(projectiles.count, "active projectiles");
767
770
  `destroy()` permanently removes a standalone query from the world. Entity references are silently purged (no `exit` callbacks fire), the tracked set is cleared, and the `world` reference is set to `undefined`. Any further use of the object is **undefined behavior**.
768
771
 
769
772
  ```ts
770
- const q = world.query("Temporary").requires(Position);
773
+ const q = world.query("Temporary").with(Position);
771
774
  // ... use q.count, q.has(e), or iterate q ...
772
775
  q.destroy();
773
776
  ```
@@ -791,14 +794,14 @@ const f = world.filter([Position, Velocity]);
791
794
 
792
795
  `forEach` runs inside a deferred scope, so mutations made by the callback are batched and become visible after iteration finishes.
793
796
 
794
- **Type inference.** Component classes the type system can extract from the DSL (plain component classes, plain arrays, `only`, and `all` of those) are non-nullable in the callback tuple. For the rest, supply a `_guaranteed` second argument to `world.filter()`:
797
+ **Type inference.** Component classes the type system can extract from the DSL (plain component classes, plain arrays, `only`, and `all` of those) are non-nullable in the callback tuple. For the rest, supply a `hint` field:
795
798
 
796
799
  ```ts
797
800
  // Auto-deduced — both non-null:
798
801
  world.filter([Position, Velocity]).forEach([Position, Velocity], (e, [pos, vel]) => { ... });
799
802
 
800
803
  // Manual hint for any / not / test:
801
- world.filter({ any: [Position, Velocity] }, [Position]).forEach([Position], (e, [pos]) => pos.x);
804
+ world.filter({ with: { any: [Position, Velocity] }, hint: [Position] }).forEach([Position], (e, [pos]) => pos.x);
802
805
  ```
803
806
 
804
807
  A `Filter` holds no tracked set, makes no registration calls, and needs no `destroy()`.
@@ -1,6 +1,6 @@
1
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";
2
+ import type { ComponentInstance, ComponentType } from "./component_meta.js";
3
+ export { CleanupPolicy, ComponentMeta, Relationship, type ComponentClass, type ComponentInstance, type ComponentRef, type ComponentRefArray, type ComponentType, type Hook, } from "./component_meta.js";
4
4
  /** A component entity created by {@link World.component}. */
5
5
  export declare class Component<T extends ComponentType = ComponentType> extends Entity {
6
6
  /**
@@ -19,6 +19,7 @@ export declare class Component<T extends ComponentType = ComponentType> extends
19
19
  * ```
20
20
  */
21
21
  onAdd(handler: (entity: Entity, c: InstanceType<T>) => void): this;
22
+ onAdd(handler: (entity: Entity, c: ComponentInstance) => void): this;
22
23
  /**
23
24
  * Register a callback fired each time this component is **removed** from an
24
25
  * entity, or when the owning entity is destroyed.
@@ -36,6 +37,7 @@ export declare class Component<T extends ComponentType = ComponentType> extends
36
37
  * ```
37
38
  */
38
39
  onRemove(handler: (entity: Entity, c: InstanceType<T>) => void): this;
40
+ onRemove(handler: (entity: Entity, c: ComponentInstance) => void): this;
39
41
  /**
40
42
  * Register a callback fired each time this component's data is **set or
41
43
  * modified**.
@@ -59,4 +61,5 @@ export declare class Component<T extends ComponentType = ComponentType> extends
59
61
  * ```
60
62
  */
61
63
  onSet(handler: (entity: Entity, c: InstanceType<T>) => void): this;
64
+ onSet(handler: (entity: Entity, c: ComponentInstance) => void): this;
62
65
  }
package/dist/component.js CHANGED
@@ -1,70 +1,17 @@
1
1
  import { Entity } from "./entity/index.js";
2
- export { CleanupPolicy, ComponentMeta, } from "./component_meta.js";
2
+ export { CleanupPolicy, ComponentMeta, Relationship, } from "./component_meta.js";
3
3
  /** A component entity created by {@link World.component}. */
4
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
- */
20
5
  onAdd(handler) {
21
- this.ownMeta.onAdd(handler);
6
+ super.onAdd(handler);
22
7
  return this;
23
8
  }
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
- */
40
9
  onRemove(handler) {
41
- this.ownMeta.onRemove(handler);
10
+ super.onRemove(handler);
42
11
  return this;
43
12
  }
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
- */
66
13
  onSet(handler) {
67
- this.ownMeta.onSet(handler);
14
+ super.onSet(handler);
68
15
  return this;
69
16
  }
70
17
  }
@@ -1 +1 @@
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"}
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,EACb,YAAY,GAOb,MAAM,qBAAqB,CAAC;AAE7B,6DAA6D;AAC7D,MAAM,OAAO,SAAmD,SAAQ,MAAM;IAkB5D,KAAK,CAAC,OAAyC;QAC7D,KAAK,CAAC,KAAK,CAAC,OAAyD,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;IAoBe,QAAQ,CAAC,OAAyC;QAChE,KAAK,CAAC,QAAQ,CAAC,OAAyD,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC;IACd,CAAC;IA0Be,KAAK,CAAC,OAAyC;QAC7D,KAAK,CAAC,KAAK,CAAC,OAAyD,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -1,10 +1,14 @@
1
1
  import { BitPtr } from "./util/bitset.js";
2
- import type { Entity, EntityClass } from "./entity/index.js";
2
+ import type { EID, Entity, EntityClass } from "./entity/index.js";
3
3
  export declare enum CleanupPolicy {
4
4
  Throw = "throw",
5
5
  Remove = "remove",
6
6
  Delete = "delete"
7
7
  }
8
+ /** Base class for relationship components that point at another entity. */
9
+ export declare abstract class Relationship {
10
+ target: Entity;
11
+ }
8
12
  /** A component instance. Components are plain objects created with a no-arg constructor. */
9
13
  export type ComponentInstance = object;
10
14
  /** A component constructor used as a component key. */
@@ -12,7 +16,7 @@ export type ComponentType<T extends ComponentInstance = ComponentInstance> = new
12
16
  /** A component class constructor that can be instantiated by entity.add/set. */
13
17
  export type ComponentClass<T extends ComponentInstance = ComponentInstance> = new () => T;
14
18
  /** A component class constructor, component eid, or entity component key. */
15
- export type ComponentRef = number | ComponentType | EntityClass | Entity;
19
+ export type ComponentRef = EID | ComponentType | EntityClass | Entity;
16
20
  /**
17
21
  * Lifecycle hook for a registered component class. Exposed by
18
22
  * {@link World.component}.
@@ -54,10 +58,13 @@ export interface Hook<C extends ComponentInstance = ComponentInstance> {
54
58
  */
55
59
  onRemove(handler: (entity: Entity, c: C) => void): Hook<C>;
56
60
  /**
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
+ * Register a handler invoked when a component's data is set or modified.
62
+ *
63
+ * Fires when:
64
+ * - `entity.set(C, props)` applies data to the component.
65
+ * - `entity.attach(instance)` stores an existing instance.
66
+ * - `entity.modified(C)` is called after in-place mutation.
67
+ * - A system's `getMut(C)` marks the component dirty.
61
68
  *
62
69
  * @param handler - Receives the entity and component instance whose data changed.
63
70
  * @returns This hook, for chaining.
@@ -76,7 +83,7 @@ export declare class ComponentMeta implements Hook<ComponentInstance> {
76
83
  /** The component class constructor this meta represents. */
77
84
  readonly Class: ComponentType;
78
85
  /** Component entity id assigned at registration time. */
79
- readonly eid: number;
86
+ readonly eid: EID;
80
87
  /** Pre-computed bit-pointer into the entity archetype {@link Bitset}. */
81
88
  readonly bitPtr: BitPtr;
82
89
  /** Whether this component is a relationship pointing at another entity. */
@@ -86,7 +93,7 @@ export declare class ComponentMeta implements Hook<ComponentInstance> {
86
93
  /** Applied to entities targeting a deleted entity through this relationship. */
87
94
  onDeleteTarget: CleanupPolicy;
88
95
  private _usageCount;
89
- constructor(Class: ComponentType, eid: number);
96
+ constructor(Class: ComponentType, ceid: EID);
90
97
  /** Number of entities currently carrying this component eid. */
91
98
  get usageCount(): number;
92
99
  /** @inheritdoc */
@@ -1,11 +1,13 @@
1
1
  import { BitPtr } from "./util/bitset.js";
2
- import { Relationship } from "./relationship.js";
3
2
  export var CleanupPolicy;
4
3
  (function (CleanupPolicy) {
5
4
  CleanupPolicy["Throw"] = "throw";
6
5
  CleanupPolicy["Remove"] = "remove";
7
6
  CleanupPolicy["Delete"] = "delete";
8
7
  })(CleanupPolicy || (CleanupPolicy = {}));
8
+ /** Base class for relationship components that point at another entity. */
9
+ export class Relationship {
10
+ }
9
11
  /**
10
12
  * Bookkeeping record produced for each component eid.
11
13
  *
@@ -15,7 +17,7 @@ export var CleanupPolicy;
15
17
  * the meta object.
16
18
  */
17
19
  export class ComponentMeta {
18
- constructor(Class, eid) {
20
+ constructor(Class, ceid) {
19
21
  /** Applied to entities carrying this component when this component entity is deleted. */
20
22
  this.onDelete = CleanupPolicy.Throw;
21
23
  /** Applied to entities targeting a deleted entity through this relationship. */
@@ -28,8 +30,8 @@ export class ComponentMeta {
28
30
  this._exclusive = undefined;
29
31
  this._usageCount = 0;
30
32
  this.Class = Class;
31
- this.eid = eid;
32
- this.bitPtr = new BitPtr(eid);
33
+ this.eid = ceid;
34
+ this.bitPtr = new BitPtr(ceid);
33
35
  this.isRelationship = Class.prototype instanceof Relationship;
34
36
  }
35
37
  /** Number of entities currently carrying this component eid. */
@@ -1 +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"}
1
+ {"version":3,"file":"component_meta.js","sourceRoot":"","sources":["../src/component_meta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,MAAM,CAAN,IAAY,aAIX;AAJD,WAAY,aAAa;IACvB,gCAAe,CAAA;IACf,kCAAiB,CAAA;IACjB,kCAAiB,CAAA;AACnB,CAAC,EAJW,aAAa,KAAb,aAAa,QAIxB;AAED,2EAA2E;AAC3E,MAAM,OAAgB,YAAY;CAEjC;AAyED;;;;;;;GAOG;AACH,MAAM,OAAO,aAAa;IA+BxB,YAAY,KAAoB,EAAE,IAAS;QArB3C,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,IAAI,CAAC;QAChB,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,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"}