@oasys/oecs 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +208 -14
- package/README.md +198 -145
- package/dist/core/ecs/access_check.d.cts +3 -3
- package/dist/core/ecs/access_check.d.ts +3 -3
- package/dist/core/ecs/archetype.d.cts +103 -43
- package/dist/core/ecs/archetype.d.ts +103 -43
- package/dist/core/ecs/archetype.d.ts.map +1 -1
- package/dist/core/ecs/archetype_graph.d.cts +8 -8
- package/dist/core/ecs/archetype_graph.d.ts +8 -8
- package/dist/core/ecs/archetype_graph.d.ts.map +1 -1
- package/dist/core/ecs/builtin_relations.d.cts +1 -1
- package/dist/core/ecs/builtin_relations.d.ts +1 -1
- package/dist/core/ecs/command_log.d.cts +4 -4
- package/dist/core/ecs/command_log.d.ts +4 -4
- package/dist/core/ecs/command_log.d.ts.map +1 -1
- package/dist/core/ecs/component.d.cts +4 -4
- package/dist/core/ecs/component.d.ts +4 -4
- package/dist/core/ecs/deferred_commands.d.cts +1 -1
- package/dist/core/ecs/deferred_commands.d.ts +1 -1
- package/dist/core/ecs/deferred_commands.d.ts.map +1 -1
- package/dist/core/ecs/ecs.d.cts +85 -43
- package/dist/core/ecs/ecs.d.ts +85 -43
- package/dist/core/ecs/ecs.d.ts.map +1 -1
- package/dist/core/ecs/ecs_memory.d.cts +15 -15
- package/dist/core/ecs/ecs_memory.d.ts +15 -15
- package/dist/core/ecs/ecs_memory.d.ts.map +1 -1
- package/dist/core/ecs/entity_allocator.d.cts +6 -6
- package/dist/core/ecs/entity_allocator.d.ts +6 -6
- package/dist/core/ecs/entity_allocator.d.ts.map +1 -1
- package/dist/core/ecs/event.d.cts +2 -2
- package/dist/core/ecs/event.d.ts +2 -2
- package/dist/core/ecs/event_registry.d.cts +1 -1
- package/dist/core/ecs/event_registry.d.ts +1 -1
- package/dist/core/ecs/event_registry.d.ts.map +1 -1
- package/dist/core/ecs/facades.d.cts +15 -15
- package/dist/core/ecs/facades.d.ts +15 -15
- package/dist/core/ecs/facades.d.ts.map +1 -1
- package/dist/core/ecs/frame_trace.d.cts +2 -2
- package/dist/core/ecs/frame_trace.d.ts +2 -2
- package/dist/core/ecs/host_commands.d.cts +12 -12
- package/dist/core/ecs/host_commands.d.ts +12 -12
- package/dist/core/ecs/host_commands.d.ts.map +1 -1
- package/dist/core/ecs/index.d.cts +1 -1
- package/dist/core/ecs/index.d.ts +1 -1
- package/dist/core/ecs/index.d.ts.map +1 -1
- package/dist/core/ecs/observer.d.cts +9 -9
- package/dist/core/ecs/observer.d.ts +9 -9
- package/dist/core/ecs/observer.d.ts.map +1 -1
- package/dist/core/ecs/query.d.cts +91 -70
- package/dist/core/ecs/query.d.ts +91 -70
- package/dist/core/ecs/query.d.ts.map +1 -1
- package/dist/core/ecs/ref.d.cts +53 -1
- package/dist/core/ecs/ref.d.ts +53 -1
- package/dist/core/ecs/ref.d.ts.map +1 -1
- package/dist/core/ecs/relation.d.cts +15 -15
- package/dist/core/ecs/relation.d.ts +15 -15
- package/dist/core/ecs/relation.d.ts.map +1 -1
- package/dist/core/ecs/relation_service.d.cts +14 -14
- package/dist/core/ecs/relation_service.d.ts +14 -14
- package/dist/core/ecs/relation_service.d.ts.map +1 -1
- package/dist/core/ecs/resource.d.cts +1 -1
- package/dist/core/ecs/resource.d.ts +1 -1
- package/dist/core/ecs/resource_registry.d.cts +2 -2
- package/dist/core/ecs/resource_registry.d.ts +2 -2
- package/dist/core/ecs/resume.d.cts +3 -3
- package/dist/core/ecs/resume.d.ts +3 -3
- package/dist/core/ecs/resume.d.ts.map +1 -1
- package/dist/core/ecs/schedule.d.cts +22 -9
- package/dist/core/ecs/schedule.d.ts +22 -9
- package/dist/core/ecs/schedule.d.ts.map +1 -1
- package/dist/core/ecs/snapshot_service.d.cts +3 -3
- package/dist/core/ecs/snapshot_service.d.ts +3 -3
- package/dist/core/ecs/sparse_store.d.cts +6 -6
- package/dist/core/ecs/sparse_store.d.ts +6 -6
- package/dist/core/ecs/sparse_store.d.ts.map +1 -1
- package/dist/core/ecs/store.d.cts +189 -110
- package/dist/core/ecs/store.d.ts +189 -110
- package/dist/core/ecs/store.d.ts.map +1 -1
- package/dist/core/ecs/store_layout_listener.d.cts +2 -2
- package/dist/core/ecs/store_layout_listener.d.ts +2 -2
- package/dist/core/ecs/system.d.cts +8 -8
- package/dist/core/ecs/system.d.ts +8 -8
- package/dist/core/ecs/system.d.ts.map +1 -1
- package/dist/core/ecs/utils/error.d.cts +7 -0
- package/dist/core/ecs/utils/error.d.ts +7 -0
- package/dist/core/ecs/utils/error.d.ts.map +1 -1
- package/dist/core/store/action_ring.d.cts +7 -8
- package/dist/core/store/action_ring.d.ts +7 -8
- package/dist/core/store/action_ring.d.ts.map +1 -1
- package/dist/core/store/allocator.d.cts +58 -35
- package/dist/core/store/allocator.d.ts +58 -35
- package/dist/core/store/allocator.d.ts.map +1 -1
- package/dist/core/store/buffer_backed_column.d.cts +5 -6
- package/dist/core/store/buffer_backed_column.d.ts +5 -6
- package/dist/core/store/buffer_backed_column.d.ts.map +1 -1
- package/dist/core/store/column_store.d.cts +23 -23
- package/dist/core/store/column_store.d.ts +23 -23
- package/dist/core/store/column_store.d.ts.map +1 -1
- package/dist/core/store/command_dispatch.d.cts +1 -1
- package/dist/core/store/command_dispatch.d.ts +1 -1
- package/dist/core/store/command_ring.d.cts +6 -7
- package/dist/core/store/command_ring.d.ts +6 -7
- package/dist/core/store/command_ring.d.ts.map +1 -1
- package/dist/core/store/descriptor.d.cts +2 -2
- package/dist/core/store/descriptor.d.ts +2 -2
- package/dist/core/store/entity_index.d.cts +3 -3
- package/dist/core/store/entity_index.d.ts +3 -3
- package/dist/core/store/event_ring.d.cts +7 -7
- package/dist/core/store/event_ring.d.ts +7 -7
- package/dist/core/store/extend.d.cts +2 -2
- package/dist/core/store/extend.d.ts +2 -2
- package/dist/core/store/extend.d.ts.map +1 -1
- package/dist/core/store/grow.d.cts +1 -1
- package/dist/core/store/grow.d.ts +1 -1
- package/dist/core/store/grow.d.ts.map +1 -1
- package/dist/core/store/header.d.cts +9 -9
- package/dist/core/store/header.d.ts +9 -9
- package/dist/core/store/header.d.ts.map +1 -1
- package/dist/core/store/layout_ops.d.cts +25 -7
- package/dist/core/store/layout_ops.d.ts +25 -7
- package/dist/core/store/layout_ops.d.ts.map +1 -1
- package/dist/core/store/state_hash.d.cts +3 -3
- package/dist/core/store/state_hash.d.ts +3 -3
- package/dist/extensions/editor/editor.d.cts +4 -4
- package/dist/extensions/editor/editor.d.ts +4 -4
- package/dist/extensions/editor/editor.d.ts.map +1 -1
- package/dist/extensions/editor/field_handle.d.cts +1 -1
- package/dist/extensions/editor/field_handle.d.ts +1 -1
- package/dist/extensions/editor/index.d.cts +2 -2
- package/dist/extensions/editor/index.d.ts +2 -2
- package/dist/extensions/editor/index.development.js +4 -4
- package/dist/extensions/editor/index.js +4 -4
- package/dist/extensions/reactive/ecs_sync.d.cts +4 -4
- package/dist/extensions/reactive/ecs_sync.d.ts +4 -4
- package/dist/extensions/reactive/index.d.cts +4 -4
- package/dist/extensions/reactive/index.d.ts +4 -4
- package/dist/extensions/reactive/index.development.js +3 -3
- package/dist/extensions/reactive/index.js +3 -3
- package/dist/extensions/solid/index.d.cts +1 -1
- package/dist/extensions/solid/index.d.ts +1 -1
- package/dist/extensions/solid/index.development.js +1 -1
- package/dist/extensions/solid/index.js +1 -1
- package/dist/extensions/solid/kernel_solid.d.cts +1 -1
- package/dist/extensions/solid/kernel_solid.d.ts +1 -1
- package/dist/extensions/solid/kernel_solid.d.ts.map +1 -1
- package/dist/{host_commands-BI8pEmjH.js → host_commands-BlR3oZ3x.js} +473 -393
- package/dist/host_commands-C2cpU3yC.cjs +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.development.cjs +1 -1
- package/dist/index.development.js +3345 -2963
- package/dist/index.js +1496 -1131
- package/dist/{internal-BMDgWZbt.js → internal-BoxWl4dG.js} +410 -330
- package/dist/internal-CGBEwfeB.cjs +2 -0
- package/dist/internal.cjs +1 -1
- package/dist/internal.development.cjs +1 -1
- package/dist/internal.development.js +1 -1
- package/dist/internal.js +1 -1
- package/dist/primitives.development.js +1 -1
- package/dist/primitives.js +1 -1
- package/dist/reactive/index.d.cts +2 -2
- package/dist/reactive/index.d.ts +2 -2
- package/dist/reactive/index.development.js +1 -1
- package/dist/reactive/index.js +1 -1
- package/dist/reactive/kernel.d.cts +5 -5
- package/dist/reactive/kernel.d.ts +5 -5
- package/dist/reactive/shallow.d.cts +1 -1
- package/dist/reactive/shallow.d.ts +1 -1
- package/dist/{shallow-DfnAm9vG.js → shallow-Bs39EPh1.js} +1 -1
- package/dist/{shallow-9S1pY_Iw.js → shallow-CiFC70Dz.js} +1 -1
- package/dist/{shared-BU1Cd40h.js → shared-B4v0L1cw.js} +41 -35
- package/dist/shared-DU78k0pU.cjs +1 -0
- package/dist/shared.cjs +1 -1
- package/dist/shared.d.cts +1 -1
- package/dist/shared.d.ts +1 -1
- package/dist/shared.development.cjs +1 -1
- package/dist/shared.development.js +1 -1
- package/dist/shared.js +1 -1
- package/dist/type_primitives/typed_arrays/typed_arrays.d.cts +2 -2
- package/dist/type_primitives/typed_arrays/typed_arrays.d.ts +2 -2
- package/dist/{typed_arrays-BcXcnzB4.js → typed_arrays-DIVwVy5_.js} +1 -1
- package/dist/version.d.cts +2 -2
- package/dist/version.d.ts +2 -2
- package/package.json +1 -1
- package/dist/host_commands-CxhpzMx9.cjs +0 -1
- package/dist/internal-LiTSB_tG.cjs +0 -2
- package/dist/shared-BymrGTyR.cjs +0 -1
|
@@ -6,7 +6,7 @@ import { SystemContext } from './query.cjs';
|
|
|
6
6
|
import { StructuralObserverEvents } from './store.cjs';
|
|
7
7
|
import { SystemAccessDeclaration, SystemDescriptor } from './system.cjs';
|
|
8
8
|
/** What the observer registry needs from `Store` — the typed seam replacing
|
|
9
|
-
* bare underscore-convention reach-through
|
|
9
|
+
* bare underscore-convention reach-through. `Store` implements this; the
|
|
10
10
|
* registry holds only this view, so the compiler bounds what observer dispatch
|
|
11
11
|
* can touch. Underscore names are kept so `Store`'s members stay one
|
|
12
12
|
* declaration (they read as "internal" at every other call site). */
|
|
@@ -40,12 +40,12 @@ export type ArchetypeObserverFn = (arch: ArchetypeView, ctx: SystemContext) => v
|
|
|
40
40
|
interface ObserverConfigBase {
|
|
41
41
|
onAdd?: ObserverFn;
|
|
42
42
|
onRemove?: ObserverFn;
|
|
43
|
-
/** Fires when an entity carrying this component is *disabled*
|
|
44
|
-
* deferred toggle drain, once per net transition
|
|
43
|
+
/** Fires when an entity carrying this component is *disabled* — at the
|
|
44
|
+
* deferred toggle drain, once per net transition. Mirrors `onRemove`:
|
|
45
45
|
* a disable is a soft remove of the whole mask from default queries. An immediate
|
|
46
46
|
* host-side `ecs.disable()` does not fire (like immediate `addComponent`). */
|
|
47
47
|
onDisable?: ObserverFn;
|
|
48
|
-
/** Fires when an entity carrying this component is *enabled
|
|
48
|
+
/** Fires when an entity carrying this component is *enabled*, symmetric
|
|
49
49
|
* with `onDisable` / `onAdd`. */
|
|
50
50
|
onEnable?: ObserverFn;
|
|
51
51
|
/** Access surface the callbacks touch (reads / writes / spawns / …). Partial:
|
|
@@ -56,7 +56,7 @@ interface ObserverConfigBase {
|
|
|
56
56
|
* semantics), for order-independence of register-vs-spawn. */
|
|
57
57
|
yieldExisting?: boolean;
|
|
58
58
|
/** Diagnostic label for this observer, surfaced by the frame-trace seam
|
|
59
|
-
*
|
|
59
|
+
* as the `observer_fired.observer` field — the same role a system's
|
|
60
60
|
* `name` plays. Optional and observe-only: it never touches `stateHash` or
|
|
61
61
|
* dispatch. Defaults to `observer(<component debug name>)` when the component
|
|
62
62
|
* was registered with a name, else `observer(<cid>)`. */
|
|
@@ -64,7 +64,7 @@ interface ObserverConfigBase {
|
|
|
64
64
|
}
|
|
65
65
|
/** Per-entity onSet: `onSet(eid, ctx)` fires once per changed entity, drained
|
|
66
66
|
* from the opt-in per-row dirty list (registering this enables dirty tracking
|
|
67
|
-
* for the component — the
|
|
67
|
+
* for the component — the dirty list + dedup bit). */
|
|
68
68
|
export interface EntitySetObserverConfig extends ObserverConfigBase {
|
|
69
69
|
onSet: ObserverFn;
|
|
70
70
|
granularity: "entity";
|
|
@@ -115,7 +115,7 @@ export declare class ObserverRegistry {
|
|
|
115
115
|
* registration order (`dispose()` splices entries out, so none are stale).
|
|
116
116
|
* Fed into the `startup()` archetype-prewarm closure so an observer's declared
|
|
117
117
|
* `spawns` / `transitions` create their target archetypes eagerly, exactly as a
|
|
118
|
-
* system's do
|
|
118
|
+
* system's do. Without this an observer-spawned/-transitioned archetype
|
|
119
119
|
* first-touches lazily mid-tick — the one asymmetry left in the otherwise
|
|
120
120
|
* uniform "no lazy archetypes" prewarm. */
|
|
121
121
|
descriptors(): SystemDescriptor[];
|
|
@@ -163,8 +163,8 @@ export declare class ObserverRegistry {
|
|
|
163
163
|
/**
|
|
164
164
|
* O(K) LSD radix sort of entity ids by their 20-bit dense index (two 10-bit
|
|
165
165
|
* passes), in place. This is the canonical within-observer order — *never* a
|
|
166
|
-
* comparator `Array.sort`, which the bench measured
|
|
167
|
-
*
|
|
166
|
+
* comparator `Array.sort`, which the bench measured as much slower than the
|
|
167
|
+
* entire flush. Distinct live entities have distinct indices,
|
|
168
168
|
* so index order is a total canonical order. `out` is scratch (grown to length);
|
|
169
169
|
* `c0` / `c1` are 1024-entry histograms (reused).
|
|
170
170
|
*/
|
|
@@ -6,7 +6,7 @@ import { SystemContext } from './query.js';
|
|
|
6
6
|
import { StructuralObserverEvents } from './store.js';
|
|
7
7
|
import { SystemAccessDeclaration, SystemDescriptor } from './system.js';
|
|
8
8
|
/** What the observer registry needs from `Store` — the typed seam replacing
|
|
9
|
-
* bare underscore-convention reach-through
|
|
9
|
+
* bare underscore-convention reach-through. `Store` implements this; the
|
|
10
10
|
* registry holds only this view, so the compiler bounds what observer dispatch
|
|
11
11
|
* can touch. Underscore names are kept so `Store`'s members stay one
|
|
12
12
|
* declaration (they read as "internal" at every other call site). */
|
|
@@ -40,12 +40,12 @@ export type ArchetypeObserverFn = (arch: ArchetypeView, ctx: SystemContext) => v
|
|
|
40
40
|
interface ObserverConfigBase {
|
|
41
41
|
onAdd?: ObserverFn;
|
|
42
42
|
onRemove?: ObserverFn;
|
|
43
|
-
/** Fires when an entity carrying this component is *disabled*
|
|
44
|
-
* deferred toggle drain, once per net transition
|
|
43
|
+
/** Fires when an entity carrying this component is *disabled* — at the
|
|
44
|
+
* deferred toggle drain, once per net transition. Mirrors `onRemove`:
|
|
45
45
|
* a disable is a soft remove of the whole mask from default queries. An immediate
|
|
46
46
|
* host-side `ecs.disable()` does not fire (like immediate `addComponent`). */
|
|
47
47
|
onDisable?: ObserverFn;
|
|
48
|
-
/** Fires when an entity carrying this component is *enabled
|
|
48
|
+
/** Fires when an entity carrying this component is *enabled*, symmetric
|
|
49
49
|
* with `onDisable` / `onAdd`. */
|
|
50
50
|
onEnable?: ObserverFn;
|
|
51
51
|
/** Access surface the callbacks touch (reads / writes / spawns / …). Partial:
|
|
@@ -56,7 +56,7 @@ interface ObserverConfigBase {
|
|
|
56
56
|
* semantics), for order-independence of register-vs-spawn. */
|
|
57
57
|
yieldExisting?: boolean;
|
|
58
58
|
/** Diagnostic label for this observer, surfaced by the frame-trace seam
|
|
59
|
-
*
|
|
59
|
+
* as the `observer_fired.observer` field — the same role a system's
|
|
60
60
|
* `name` plays. Optional and observe-only: it never touches `stateHash` or
|
|
61
61
|
* dispatch. Defaults to `observer(<component debug name>)` when the component
|
|
62
62
|
* was registered with a name, else `observer(<cid>)`. */
|
|
@@ -64,7 +64,7 @@ interface ObserverConfigBase {
|
|
|
64
64
|
}
|
|
65
65
|
/** Per-entity onSet: `onSet(eid, ctx)` fires once per changed entity, drained
|
|
66
66
|
* from the opt-in per-row dirty list (registering this enables dirty tracking
|
|
67
|
-
* for the component — the
|
|
67
|
+
* for the component — the dirty list + dedup bit). */
|
|
68
68
|
export interface EntitySetObserverConfig extends ObserverConfigBase {
|
|
69
69
|
onSet: ObserverFn;
|
|
70
70
|
granularity: "entity";
|
|
@@ -115,7 +115,7 @@ export declare class ObserverRegistry {
|
|
|
115
115
|
* registration order (`dispose()` splices entries out, so none are stale).
|
|
116
116
|
* Fed into the `startup()` archetype-prewarm closure so an observer's declared
|
|
117
117
|
* `spawns` / `transitions` create their target archetypes eagerly, exactly as a
|
|
118
|
-
* system's do
|
|
118
|
+
* system's do. Without this an observer-spawned/-transitioned archetype
|
|
119
119
|
* first-touches lazily mid-tick — the one asymmetry left in the otherwise
|
|
120
120
|
* uniform "no lazy archetypes" prewarm. */
|
|
121
121
|
descriptors(): SystemDescriptor[];
|
|
@@ -163,8 +163,8 @@ export declare class ObserverRegistry {
|
|
|
163
163
|
/**
|
|
164
164
|
* O(K) LSD radix sort of entity ids by their 20-bit dense index (two 10-bit
|
|
165
165
|
* passes), in place. This is the canonical within-observer order — *never* a
|
|
166
|
-
* comparator `Array.sort`, which the bench measured
|
|
167
|
-
*
|
|
166
|
+
* comparator `Array.sort`, which the bench measured as much slower than the
|
|
167
|
+
* entire flush. Distinct live entities have distinct indices,
|
|
168
168
|
* so index order is a total canonical order. `out` is scratch (grown to length);
|
|
169
169
|
* `c0` / `c1` are 1024-entry histograms (reused).
|
|
170
170
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/observer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/observer.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,13 +6,13 @@ import { ComponentDef, ComponentHandle, ComponentID, MutableColumnsForSchema, Co
|
|
|
6
6
|
import { SparseComponentDef, SparseComponentID, SparseSchemaOf } from './sparse_store.cjs';
|
|
7
7
|
import { RelationDef } from './relation.cjs';
|
|
8
8
|
import { SystemAccess, DeclaredRead, DeclaredWrite, DeclaredAdd, DeclaredRemove, DeclaredSparseRead, DeclaredSparseWrite, DeclaredRelationRead, DeclaredRelationWrite, DeclaredResourceRead, DeclaredResourceWrite, DespawnArg } from './system.cjs';
|
|
9
|
-
import { ComponentRef, ReadonlyComponentRef } from './ref.cjs';
|
|
9
|
+
import { ComponentCursor, ComponentRef, ReadonlyComponentCursor, ReadonlyComponentRef } from './ref.cjs';
|
|
10
10
|
import { EventKey, EventReader, EventShape, SignalKey } from './event.cjs';
|
|
11
11
|
import { ResourceKey, ResourceValueOf } from './resource.cjs';
|
|
12
12
|
import { BitSet } from '../../type_primitives/index.cjs';
|
|
13
13
|
/** The query-driver seam on `Store` — the typed contract behind the
|
|
14
|
-
* underscore members `ecs.ts` and the query internals reach
|
|
15
|
-
* implements this; when the cache/driver layer is extracted
|
|
14
|
+
* underscore members `ecs.ts` and the query internals reach. `Store`
|
|
15
|
+
* implements this; when the cache/driver layer is extracted the
|
|
16
16
|
* interface retargets at the collaborator without touching consumers.
|
|
17
17
|
* `_tick` / `_trace` are deliberately mutable: `ECS.update()` advances the
|
|
18
18
|
* change tick and `ECS.setTrace` installs the sink through this seam. */
|
|
@@ -25,7 +25,7 @@ export interface QueryHost {
|
|
|
25
25
|
* gates `_noteSet` at every write site. */
|
|
26
26
|
readonly _anyDirtyTracked: boolean;
|
|
27
27
|
/** Bumped when an archetype crosses empty↔non-empty — cached query
|
|
28
|
-
* archetype lists rebuild when their observed epoch is stale
|
|
28
|
+
* archetype lists rebuild when their observed epoch is stale. */
|
|
29
29
|
readonly _queryDirtyEpoch: number;
|
|
30
30
|
/** Record a per-entity onSet dirty mark for `def` (gated by
|
|
31
31
|
* `_anyDirtyTracked` at the call site). */
|
|
@@ -33,11 +33,11 @@ export interface QueryHost {
|
|
|
33
33
|
/** Dev-only: buffered event count across dirty channels (mid-update emit
|
|
34
34
|
* detection in `ECS.update()`). */
|
|
35
35
|
_devBufferedEventCount(): number;
|
|
36
|
-
/** Second query-match path: sparse-term intersection
|
|
36
|
+
/** Second query-match path: sparse-term intersection. */
|
|
37
37
|
_forEachSparseMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], denseArchetypes: readonly Archetype[], cb: (entityId: EntityID) => void, includeDisabled: boolean): void;
|
|
38
|
-
/** Third query-match path: the `(*, T)` wildcard
|
|
38
|
+
/** Third query-match path: the `(*, T)` wildcard. */
|
|
39
39
|
_forEachRelationTargetMatch(target: EntityID, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
|
|
40
|
-
/** Fourth query-match path: hierarchy depth ordering
|
|
40
|
+
/** Fourth query-match path: hierarchy depth ordering. */
|
|
41
41
|
_forEachHierarchyMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], denseArchetypes: readonly Archetype[], relation: RelationDef, maxDepth: number, includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
|
|
42
42
|
}
|
|
43
43
|
export interface QueryCacheEntry {
|
|
@@ -46,7 +46,7 @@ export interface QueryCacheEntry {
|
|
|
46
46
|
anyOfMask: BitSet | null;
|
|
47
47
|
query: Query<any>;
|
|
48
48
|
}
|
|
49
|
-
/** One owner for every query-resolution cache
|
|
49
|
+
/** One owner for every query-resolution cache. Previously the dedup
|
|
50
50
|
* bucket map lived on `ECS` while `Query` populated eleven composition maps
|
|
51
51
|
* declared on the resolver interface — ownership split across two modules.
|
|
52
52
|
* All entries are structural (a query is minted once per unique term set and
|
|
@@ -84,10 +84,10 @@ export interface QueryResolver {
|
|
|
84
84
|
_getCurrentTick(): number;
|
|
85
85
|
_getQueryDirtyEpoch(): number;
|
|
86
86
|
_nextQueryId(): number;
|
|
87
|
-
/** All query-resolution caches — dedup + composition
|
|
87
|
+
/** All query-resolution caches — dedup + composition. One owner; see
|
|
88
88
|
* `QueryCache` for the per-map keying/id-space notes. */
|
|
89
89
|
readonly _caches: QueryCache;
|
|
90
|
-
/** Second query-match path
|
|
90
|
+
/** Second query-match path: drive iteration by sparse
|
|
91
91
|
* membership rather than the archetype mask, yielding entities — sparse
|
|
92
92
|
* members are scattered across archetypes, so there is no archetype-column
|
|
93
93
|
* span to hand back. With a sparse require term, drive from the smallest
|
|
@@ -95,18 +95,18 @@ export interface QueryResolver {
|
|
|
95
95
|
* archetype list and skip excluded rows; with neither, walk dense entities.
|
|
96
96
|
* Only entered via `Query.forEachEntity`, so dense `forEach` never pays.
|
|
97
97
|
* `includeDisabled` widens the per-archetype row scan from enabled rows to
|
|
98
|
-
* all rows
|
|
98
|
+
* all rows. */
|
|
99
99
|
_forEachSparseMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], denseArchetypes: readonly Archetype[], cb: (entityId: EntityID) => void, includeDisabled: boolean): void;
|
|
100
100
|
/** Backing sparse id of a relation — resolves a `(R, *)` wildcard term
|
|
101
|
-
* (`withRelation
|
|
101
|
+
* (`withRelation`) to the membership store the sparse-match path
|
|
102
102
|
* already drives. */
|
|
103
103
|
_relationBackingSparseId(def: RelationDef): SparseComponentID;
|
|
104
|
-
/** Third query-match path
|
|
104
|
+
/** Third query-match path: `(*, T)` — drive iteration from the union of
|
|
105
105
|
* every relation's `sourcesOf(target)` (dedup + canonical sort), intersected
|
|
106
106
|
* with the dense mask + sparse terms + the enabled-row filter. Only entered via
|
|
107
107
|
* `Query.forEachRelatedTo`. */
|
|
108
108
|
_forEachRelationTargetMatch(target: EntityID, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
|
|
109
|
-
/** Fourth query-match path
|
|
109
|
+
/** Fourth query-match path: yield the matched entities (dense mask +
|
|
110
110
|
* sparse terms + enabled-row filter, exactly the `_forEachSparseMatch`
|
|
111
111
|
* intersection) in canonical **hierarchy depth order** over exclusive relation
|
|
112
112
|
* `relation` — depth ascending (parents before children), entity index
|
|
@@ -115,10 +115,10 @@ export interface QueryResolver {
|
|
|
115
115
|
* on a query carrying a `.hierarchy(R)` term. */
|
|
116
116
|
_forEachHierarchyMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], denseArchetypes: readonly Archetype[], relation: RelationDef, maxDepth: number, includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
|
|
117
117
|
}
|
|
118
|
-
/** No depth limit on a `.hierarchy(R)` term
|
|
118
|
+
/** No depth limit on a `.hierarchy(R)` term — yield every matched entity
|
|
119
119
|
* regardless of its depth in the tree. The default `maxDepth`. */
|
|
120
120
|
export declare const HIERARCHY_UNBOUNDED: number;
|
|
121
|
-
/** A `.hierarchy(R)` depth-ordering term
|
|
121
|
+
/** A `.hierarchy(R)` depth-ordering term. Records the exclusive relation
|
|
122
122
|
* whose tree defines the order and the (optional) max depth to yield. Stored on
|
|
123
123
|
* the Query and consumed by the `forEachEntity` hierarchy match path; absent
|
|
124
124
|
* (`null`) for the common case. */
|
|
@@ -143,10 +143,10 @@ export declare class ChunkColumns<out Defs extends readonly ComponentDef<any>[]
|
|
|
143
143
|
/** @internal */ _arch: Archetype;
|
|
144
144
|
/** @internal */ _tick: number;
|
|
145
145
|
/** Mutable column group — `const { x, y } = cols.mut(Pos)`. Stamps the tick.
|
|
146
|
-
* `def` must be a term of the iterating query
|
|
146
|
+
* `def` must be a term of the iterating query. */
|
|
147
147
|
mut<D extends ComponentDef<any>>(def: D & DeclaredQueryTerm<Defs, D>): MutableColumnsForSchema<SchemaOf<D>>;
|
|
148
148
|
/** Read-only column group — `const { vx, vy } = cols.read(Vel)`. No tick bump.
|
|
149
|
-
* `def` must be a term of the iterating query
|
|
149
|
+
* `def` must be a term of the iterating query. */
|
|
150
150
|
read<D extends ComponentDef<any>>(def: D & DeclaredQueryTerm<Defs, D>): ColumnsForSchema<SchemaOf<D>>;
|
|
151
151
|
}
|
|
152
152
|
export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
@@ -173,7 +173,7 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
173
173
|
* sparse-derived query they'd **fail open** — returning the unfiltered dense
|
|
174
174
|
* result instead of the sparse-filtered one. Throw in `DEV` (compiled
|
|
175
175
|
* out of prod) steering the caller to `forEachEntity`, the only path that
|
|
176
|
-
* honors sparse membership
|
|
176
|
+
* honors sparse membership. Mirrors `ChangedQuery`'s dev-guard on its
|
|
177
177
|
* include-mask invariant. */
|
|
178
178
|
private _assertDenseOnly;
|
|
179
179
|
/** Whether this query carries only dense terms — the precondition for the
|
|
@@ -181,7 +181,7 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
181
181
|
private _isDenseOnly;
|
|
182
182
|
/** First matching entity, or `undefined` when the query matches none — the
|
|
183
183
|
* singleton read (`player`, `camera`) without hand-rolling a forEach +
|
|
184
|
-
* closure capture
|
|
184
|
+
* closure capture. Dense-only queries answer from the
|
|
185
185
|
* first non-empty archetype in O(archetypes); queries with sparse /
|
|
186
186
|
* relation / hierarchy terms fall back to a full `forEachEntity` walk.
|
|
187
187
|
* "First" is iteration order, not spawn order — with more than one match
|
|
@@ -197,16 +197,16 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
197
197
|
/** Number of matching archetypes (including empty ones). */
|
|
198
198
|
get archetypeCount(): number;
|
|
199
199
|
/** Total entity count across all matching archetypes — enabled rows only by
|
|
200
|
-
* default, or all rows when `includeDisabled
|
|
200
|
+
* default, or all rows when `includeDisabled`. Reads the partition
|
|
201
201
|
* fields directly (not the archetype's flag-dependent `entityCount`
|
|
202
202
|
* getter). */
|
|
203
203
|
get entityCount(): number;
|
|
204
204
|
get archetypes(): readonly ArchetypeView<Defs>[];
|
|
205
|
-
/** Carry this query's non-dense terms — optional fetch-if-present
|
|
206
|
-
* sparse membership
|
|
205
|
+
/** Carry this query's non-dense terms — optional fetch-if-present and
|
|
206
|
+
* sparse membership — onto a freshly composed dense query. `and` /
|
|
207
207
|
* `not` / `anyOf` build the new dense mask via `_resolveQuery`, which is
|
|
208
208
|
* keyed on the mask alone and so hands back a query carrying NONE of these
|
|
209
|
-
* terms;
|
|
209
|
+
* terms; an earlier version silently dropped them, which made composition
|
|
210
210
|
* order-dependent (`q.optional(V).and(H)` lost `V`; `q.and(H).optional(V)`
|
|
211
211
|
* kept it). When this query carries no non-dense terms (the common case)
|
|
212
212
|
* `base` is already correct and returned as-is, preserving the mask-cached
|
|
@@ -216,7 +216,7 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
216
216
|
private _carryNondense;
|
|
217
217
|
/** Extend required component set. Returns a new (cached) Query. */
|
|
218
218
|
and<D extends ComponentDef[]>(...comps: D): Query<[...Defs, ...D]>;
|
|
219
|
-
/** @internal — cold cache-miss path for single-arg `and`, split out
|
|
219
|
+
/** @internal — cold cache-miss path for single-arg `and`, split out so
|
|
220
220
|
* the hot `and` body is just key-compute + cache hit. The miss path runs once
|
|
221
221
|
* per unique composition, then every repeat is a cache hit; keeping it out of
|
|
222
222
|
* line shrinks `and`'s inlined footprint when several composes share one hot
|
|
@@ -225,9 +225,9 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
225
225
|
private _andMiss;
|
|
226
226
|
/** Exclude archetypes that have any of these components. */
|
|
227
227
|
without(...comps: ComponentDef[]): Query<Defs>;
|
|
228
|
-
/** @internal — cold cache-miss path for single-arg `not
|
|
228
|
+
/** @internal — cold cache-miss path for single-arg `not`; see `_andMiss`. */
|
|
229
229
|
private _notMiss;
|
|
230
|
-
/** Require a sparse component
|
|
230
|
+
/** Require a sparse component: match only entities that hold it,
|
|
231
231
|
* across every archetype. A sparse term doesn't touch the dense mask, so
|
|
232
232
|
* the returned (cached) query reuses this one's live archetype list; it is
|
|
233
233
|
* iterated via `forEachEntity`, never `forEach` (sparse members are
|
|
@@ -237,11 +237,11 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
237
237
|
* the resolver's shared single-term map. Both the single- and multi-arg public
|
|
238
238
|
* forms fold over this, so all sparse-require composition is deduplicated. */
|
|
239
239
|
private _withSparseOne;
|
|
240
|
-
/** Exclude a sparse component
|
|
240
|
+
/** Exclude a sparse component: drop entities that hold it. Same
|
|
241
241
|
* dense-list reuse and `forEachEntity` iteration as `withSparse`. */
|
|
242
242
|
withoutSparse(...defs: SparseComponentDef[]): Query<Defs>;
|
|
243
243
|
/** One-id `withoutSparse` composition, cached on `(parent_id, sparseId)`. The
|
|
244
|
-
* multi-arg form folds over this
|
|
244
|
+
* multi-arg form folds over this — mirrors `_withSparseOne`. */
|
|
245
245
|
private _withoutSparseOne;
|
|
246
246
|
/** Build a derived query carrying new sparse terms. Reuses this query's
|
|
247
247
|
* dense state by reference — the masks are never mutated in place (`and` /
|
|
@@ -250,19 +250,19 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
250
250
|
* Carries the existing `_optional` terms through unchanged (the two axes
|
|
251
251
|
* compose). */
|
|
252
252
|
private _deriveSparse;
|
|
253
|
-
/** Require the `(R, *)` wildcard
|
|
253
|
+
/** Require the `(R, *)` wildcard: match only sources that hold **any**
|
|
254
254
|
* target under relation `R`. "Has any `(R, *)` pair" is exactly membership in
|
|
255
255
|
* R's backing sparse store (exclusive `{target}` row / multi tag), so this is a
|
|
256
256
|
* relation-typed front door over `withSparse` — it pushes R's backing sparse
|
|
257
257
|
* id onto `_sparseInclude` and reuses the `forEachEntity` sparse-match path
|
|
258
258
|
* (insertion order; canonical sorting is reserved for `stateHash`/snapshot, and
|
|
259
|
-
* costs
|
|
259
|
+
* costs much more here for no determinism benefit).
|
|
260
260
|
* Membership semantics: each source once; fetch its targets with
|
|
261
261
|
* `ctx.targetsOf(e, R)`. Requires `relationReads: [R]` (checked at iteration).
|
|
262
|
-
* Cached per `(parent_id, relation_id)` like the sparse terms
|
|
262
|
+
* Cached per `(parent_id, relation_id)` like the sparse terms. */
|
|
263
263
|
withRelation(...defs: RelationDef[]): Query<Defs>;
|
|
264
264
|
private _withRelationOne;
|
|
265
|
-
/** Exclude the `(R, *)` wildcard
|
|
265
|
+
/** Exclude the `(R, *)` wildcard: drop sources that hold any target
|
|
266
266
|
* under `R`. Mirror of `withRelation` on the exclude side (pushes R's
|
|
267
267
|
* backing sparse id onto `_sparseExclude`). */
|
|
268
268
|
withoutRelation(...defs: RelationDef[]): Query<Defs>;
|
|
@@ -274,7 +274,7 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
274
274
|
private _deriveRelation;
|
|
275
275
|
/** Order this query's matched entities in **hierarchy depth order** over the
|
|
276
276
|
* exclusive relation `R` — parents before children — and (optionally) drop any
|
|
277
|
-
* deeper than `maxDepth` (
|
|
277
|
+
* deeper than `maxDepth` (flecs `cascade` / bitECS `Hierarchy()`). The
|
|
278
278
|
* matched *set* is unchanged (still the dense mask + sparse + `(R, *)` + disabled
|
|
279
279
|
* terms); `.hierarchy(R)` only **reorders** + depth-limits it, so an entity with
|
|
280
280
|
* no `R`-parent is a root at depth 0 and still yielded (first). The canonical
|
|
@@ -284,8 +284,8 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
284
284
|
*
|
|
285
285
|
* Iterate with `forEachEntity`: members scatter across archetypes, so there is
|
|
286
286
|
* no SoA column span — `forEach` / `count` reject a hierarchy query (like a
|
|
287
|
-
* sparse term). **Exclusive relations only** (matches the traversal
|
|
288
|
-
*
|
|
287
|
+
* sparse term). **Exclusive relations only** (matches the traversal
|
|
288
|
+
* constraint); a multi relation throws `RELATION_MODE_MISMATCH` at iteration, and a
|
|
289
289
|
* cycle is a loud `RELATION_CYCLE` in `DEV` (a safe break in production).
|
|
290
290
|
* Requires `relationReads: [R]` (checked at iteration). Carried through
|
|
291
291
|
* `and`/`not`/`anyOf` like the sparse terms (`_carryNondense`).
|
|
@@ -298,13 +298,13 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
298
298
|
* reference (the matched set is unchanged) — same rationale as `_deriveSparse`. */
|
|
299
299
|
private _deriveHierarchy;
|
|
300
300
|
/** Assert every `(R, *)` wildcard term on this query was declared in the
|
|
301
|
-
* system's `relationReads
|
|
301
|
+
* system's `relationReads`. Iteration-time (`forEachEntity` /
|
|
302
302
|
* `forEachRelatedTo`), not construction-time, so it is robust to queries
|
|
303
303
|
* built outside a system — same rationale as the data-op checks. `DEV` only;
|
|
304
304
|
* outside a system `checkRelationRead` is a no-op. */
|
|
305
305
|
private _checkRelationAccess;
|
|
306
306
|
/** Iterate every source related to `target` under **any** relation — the
|
|
307
|
-
* `(*, T)` wildcard
|
|
307
|
+
* `(*, T)` wildcard — intersected with this query's dense + sparse +
|
|
308
308
|
* `(R, *)` + disabled predicate, each source yielded once in ascending-EntityID
|
|
309
309
|
* order (the `sourcesOf` / `sourcesOfAny` convention). `target` is supplied
|
|
310
310
|
* here rather than as a chained term because it is a runtime `EntityID`: baking
|
|
@@ -315,13 +315,13 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
315
315
|
* `relationReads: [ANY_RELATION]` (plus `[R]` for any composed `withRelation`).
|
|
316
316
|
* Cold/structural — not a per-tick hot loop over many targets. */
|
|
317
317
|
forEachRelatedTo(target: EntityID, cb: (entityId: EntityID) => void): void;
|
|
318
|
-
/** Add optional fetch-if-present terms
|
|
318
|
+
/** Add optional fetch-if-present terms. Does NOT narrow the matched
|
|
319
319
|
* set — the dense mask is untouched, so iteration still spans archetypes with
|
|
320
320
|
* and without each `T`. Read each column per archetype span via
|
|
321
321
|
* `arch.getOptionalColumnRead(T, field)` (column when present, `undefined`
|
|
322
322
|
* when absent). `.optional(T)` is the *declaration* that authorizes that fetch:
|
|
323
323
|
* inside `forEach`, `getOptionalColumnRead` throws in `DEV` if `T` was
|
|
324
|
-
* not declared here
|
|
324
|
+
* not declared here — the read-side analog of `reads:[T]`, which is also
|
|
325
325
|
* still required for access coverage (both checks fire, even on the absent
|
|
326
326
|
* span). The term is carried through `and`/`not`/`anyOf` (see
|
|
327
327
|
* `_carryNondense`), so it survives composition in any order. Returns a new
|
|
@@ -338,7 +338,7 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
338
338
|
* dense state by reference (the matched set is unchanged) and carries the
|
|
339
339
|
* existing sparse terms through unchanged — same rationale as `_deriveSparse`. */
|
|
340
340
|
private _deriveOptional;
|
|
341
|
-
/** Opt this query back in to disabled entities
|
|
341
|
+
/** Opt this query back in to disabled entities. By default a query
|
|
342
342
|
* excludes disabled entities (the iteration bound `arch.entityCount` is the
|
|
343
343
|
* enabled-row count). The returned (cached) query spans disabled rows too:
|
|
344
344
|
* `forEach` publishes the all-rows flag so the SoA loop's `arch.entityCount`
|
|
@@ -347,8 +347,8 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
347
347
|
* carried through `and`/`not`/`anyOf` like the sparse/optional terms. */
|
|
348
348
|
includeDisabled(): Query<Defs>;
|
|
349
349
|
forEach(cb: (arch: ArchetypeView<Defs>) => void): void;
|
|
350
|
-
/** @internal — cold `includeDisabled` wrapper for `forEach
|
|
351
|
-
*
|
|
350
|
+
/** @internal — cold `includeDisabled` wrapper for `forEach`, split out
|
|
351
|
+
* so the all-rows flag dance (`_setIterAllRows` + try/finally) stays
|
|
352
352
|
* out of `forEach`'s inlined hot body. The default (enabled-only) query never
|
|
353
353
|
* reaches here, so V8 leaves this uninlined and `forEach` shrinks accordingly. */
|
|
354
354
|
private _forEachIncludeDisabled;
|
|
@@ -399,15 +399,15 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
399
399
|
forEachUntil(cb: (arch: ArchetypeView<Defs>) => boolean): boolean;
|
|
400
400
|
/** @internal — shared body for `forEachUntil`'s default and
|
|
401
401
|
* `includeDisabled` paths. Same dev-mode optional-term scope as
|
|
402
|
-
* `forEach
|
|
402
|
+
* `forEach`. */
|
|
403
403
|
private _forEachUntilInner;
|
|
404
|
-
/** @internal — the `includeDisabled` delegate for `forEach
|
|
404
|
+
/** @internal — the `includeDisabled` delegate for `forEach`. The
|
|
405
405
|
* default (enabled-only) path inlines this body directly into `forEach`
|
|
406
|
-
*
|
|
406
|
+
* to dodge a megamorphic delegate hop; this copy survives only for the
|
|
407
407
|
* rare all-rows path, which needs the `_setIterAllRows` try/finally wrap. */
|
|
408
408
|
private _forEachInner;
|
|
409
409
|
/** Iterate the entities this query matches, yielding each `EntityID`
|
|
410
|
-
* (
|
|
410
|
+
* (the sparse-membership match path). Use this whenever the query
|
|
411
411
|
* carries a `withSparse` / `withoutSparse` term: members are scattered
|
|
412
412
|
* across archetypes, so there is no SoA column span to hand back — read
|
|
413
413
|
* fields via `ctx.getField` (dense) or `ctx.getSparseField` (sparse) on
|
|
@@ -428,7 +428,7 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
428
428
|
* Store has bumped its dirty epoch since our last rebuild, return cached result.
|
|
429
429
|
*
|
|
430
430
|
* Rebuild allocates a *fresh* array and swaps it in rather than truncating
|
|
431
|
-
* the cached one in place
|
|
431
|
+
* the cached one in place. `forEach`/`count`/`ChangedQuery.forEach`
|
|
432
432
|
* bind the returned array once and walk it; an in-place `dst.length = 0` +
|
|
433
433
|
* re-push would corrupt that walk if the query is re-entrantly iterated —
|
|
434
434
|
* i.e. the callback runs an immediate-mode mutation that crosses a
|
|
@@ -441,7 +441,7 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
441
441
|
* iteration never triggers a rebuild mid-loop: deferred mutations settle the
|
|
442
442
|
* epoch during `flushStructural`, between systems. */
|
|
443
443
|
_nonEmpty(): Archetype[];
|
|
444
|
-
/** @internal — cold rebuild path for `_nonEmpty`, split out
|
|
444
|
+
/** @internal — cold rebuild path for `_nonEmpty`, split out so the
|
|
445
445
|
* hot `_nonEmpty` body is just an epoch check + cached return. Keeping the
|
|
446
446
|
* filter loops here shrinks `_nonEmpty`'s inlined bytecode footprint, which
|
|
447
447
|
* matters when several composed queries iterate inside one hot function (the
|
|
@@ -450,7 +450,7 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
450
450
|
private _rebuildNonEmpty;
|
|
451
451
|
/** Require at least one of these components. */
|
|
452
452
|
anyOf(...comps: ComponentDef[]): Query<Defs>;
|
|
453
|
-
/** @internal — cold cache-miss path for single-arg `anyOf
|
|
453
|
+
/** @internal — cold cache-miss path for single-arg `anyOf`; see `_andMiss`. */
|
|
454
454
|
private _anyOfMiss;
|
|
455
455
|
/** Create a ChangedQuery that filters archetypes by change tick.
|
|
456
456
|
*
|
|
@@ -461,11 +461,11 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
|
|
|
461
461
|
* Use cases that need row-level granularity should compare per-row
|
|
462
462
|
* state explicitly inside the callback.
|
|
463
463
|
*
|
|
464
|
-
* The returned ChangedQuery is composable
|
|
464
|
+
* The returned ChangedQuery is composable: `and`/`without`/`anyOf`/
|
|
465
465
|
* `optional` refine it further, so `q.changed(Pos).without(Dead)` works — and
|
|
466
466
|
* is the same set as `q.without(Dead).changed(Pos)`. */
|
|
467
467
|
changed(...defs: ComponentDef[]): ChangedQuery<Defs>;
|
|
468
|
-
/** @internal — cold cache-miss path for single-arg `changed
|
|
468
|
+
/** @internal — cold cache-miss path for single-arg `changed`; see `_andMiss`. */
|
|
469
469
|
private _changedMiss;
|
|
470
470
|
/** @internal — reads lastRunTick from the resolver (ECS). */
|
|
471
471
|
_ctxLastRunTick(): number;
|
|
@@ -508,7 +508,7 @@ export type DeclaredBundleOrDef<D> = [D] extends [unknown] ? D extends Component
|
|
|
508
508
|
readonly values: Readonly<Partial<FieldValues<SchemaOf<D>>>>;
|
|
509
509
|
} : never : never;
|
|
510
510
|
/**
|
|
511
|
-
* Deferred structural-command facade (
|
|
511
|
+
* Deferred structural-command facade (Bevy `Commands`).
|
|
512
512
|
* Namespaces the deferred structural ops so the call site is self-documenting:
|
|
513
513
|
* `ctx.commands.add(e, …)` is *always* deferred (applied at the phase flush),
|
|
514
514
|
* ending the collision where `ecs.addComponent` (immediate) and a bare
|
|
@@ -553,7 +553,7 @@ export declare class Commands<out A extends SystemAccess = SystemAccess> {
|
|
|
553
553
|
remove<D extends ComponentDef<any>>(entityId: EntityID, def: D & DeclaredRemove<A, D>): this;
|
|
554
554
|
/** Destroy an entity (deferred). */
|
|
555
555
|
despawn(entityId: DespawnArg<A>): this;
|
|
556
|
-
/** Buffer `entityId` to be disabled at the phase flush (idempotent
|
|
556
|
+
/** Buffer `entityId` to be disabled at the phase flush (idempotent).
|
|
557
557
|
* Deferred because a toggle is an in-archetype row swap, which would corrupt
|
|
558
558
|
* a `forEach` SoA loop iterating that archetype if applied mid-system (it
|
|
559
559
|
* reorders the dense columns being read). A disabled entity is excluded from
|
|
@@ -583,11 +583,11 @@ export declare class Commands<out A extends SystemAccess = SystemAccess> {
|
|
|
583
583
|
export declare class SystemContext<out A extends SystemAccess = SystemAccess> {
|
|
584
584
|
private readonly store;
|
|
585
585
|
lastRunTick: number;
|
|
586
|
-
/** Deferred structural-command facade
|
|
586
|
+
/** Deferred structural-command facade. */
|
|
587
587
|
readonly commands: Commands<A>;
|
|
588
588
|
/** Current ECS tick. Use this for write ticks in getColumn. */
|
|
589
589
|
get ecsTick(): number;
|
|
590
|
-
/** The world's frame-trace sink
|
|
590
|
+
/** The world's frame-trace sink, or `null`. Lets the schedule
|
|
591
591
|
* fire `systemStart`/`flush*` without reaching into the private store.
|
|
592
592
|
* Read only under `if (DEV)`; the seam is dead-code-eliminated in prod. */
|
|
593
593
|
get _trace(): FrameTraceSink | null;
|
|
@@ -596,7 +596,7 @@ export declare class SystemContext<out A extends SystemAccess = SystemAccess> {
|
|
|
596
596
|
hasComponent(entityId: EntityID, def: ComponentDef): boolean;
|
|
597
597
|
getField<D extends ComponentDef<any>>(entityId: EntityID, def: D & DeclaredRead<A, D>, field: string & keyof SchemaOf<D>): number;
|
|
598
598
|
/** Total sibling of {@link getField}, mirroring `ecs.tryGetField`
|
|
599
|
-
|
|
599
|
+
*: `undefined` when the entity is dead or doesn't hold
|
|
600
600
|
* the component, instead of a dev throw / prod garbage read. The safe way
|
|
601
601
|
* to probe-and-read in one call: `ctx.tryGetField(e, Health, "current") ?? 0`. */
|
|
602
602
|
tryGetField<D extends ComponentDef<any>>(entityId: EntityID, def: D & DeclaredRead<A, D>, field: string & keyof SchemaOf<D>): number | undefined;
|
|
@@ -609,8 +609,8 @@ export declare class SystemContext<out A extends SystemAccess = SystemAccess> {
|
|
|
609
609
|
* still generic cannot call them without casts). */
|
|
610
610
|
updateField<D extends ComponentDef<any>>(entityId: EntityID, def: D & DeclaredWrite<A, D>, field: string & keyof SchemaOf<D>, fn: (current: number) => number): number;
|
|
611
611
|
/**
|
|
612
|
-
* Record an entity as changed for a component's per-entity `onSet` observer
|
|
613
|
-
*
|
|
612
|
+
* Record an entity as changed for a component's per-entity `onSet` observer.
|
|
613
|
+
* The SoA write idiom — `const col = arch.getColumn(D,
|
|
614
614
|
* f, tick); col[i] = v` in a tight loop — bypasses the deferred buffer and the
|
|
615
615
|
* engine never sees the per-element writes, so a per-entity `onSet` consumer
|
|
616
616
|
* pushes the row here (the bench's winning `tick+list`: raw write + an int
|
|
@@ -631,11 +631,32 @@ export declare class SystemContext<out A extends SystemAccess = SystemAccess> {
|
|
|
631
631
|
* is an *advisory* compile-time barrier (no `_changedTick` bump): the
|
|
632
632
|
* `readonly` typing blocks field writes at the type layer, but the
|
|
633
633
|
* underlying accessor shares its prototype with `ref()` and can still be
|
|
634
|
-
* written through a
|
|
634
|
+
* written through a deliberate cast. See ref.ts.
|
|
635
635
|
*/
|
|
636
636
|
refRead<D extends ComponentDef<any>>(def: D & DeclaredRead<A, D>, entityId: EntityID): ReadonlyComponentRef<SchemaOf<D>>;
|
|
637
|
+
/**
|
|
638
|
+
* A re-pointable single-entity cursor over `def` — the in-system twin of
|
|
639
|
+
* {@link ECS.cursor}, and the accessor to reach for when a system touches many
|
|
640
|
+
* entities **by id** rather than by query span.
|
|
641
|
+
*
|
|
642
|
+
* `ctx.ref` allocates one accessor for each entity. That allocation is the
|
|
643
|
+
* largest part of the cost of a read of one field by id, because to make an
|
|
644
|
+
* accessor costs much more than to move one. Make the cursor one time,
|
|
645
|
+
* outside the loop:
|
|
646
|
+
*
|
|
647
|
+
* const p = ctx.cursor(Pos);
|
|
648
|
+
* for (const e of hits) { p.at(e); p.x += p.y * dt; }
|
|
649
|
+
*
|
|
650
|
+
* Mutable: every `at()` stamps the change tick. Still prefer `eachChunk` when
|
|
651
|
+
* a query can express the entity set — a cursor removes the per-entity
|
|
652
|
+
* allocation, not the per-entity archetype resolution.
|
|
653
|
+
*/
|
|
654
|
+
cursor<D extends ComponentDef<any>>(def: D & DeclaredWrite<A, D>): ComponentCursor<SchemaOf<D>>;
|
|
655
|
+
/** Read-only {@link cursor}: no change-tick stamp on `at()`. Advisory only,
|
|
656
|
+
* same caveat as `ctx.refRead`. */
|
|
657
|
+
cursorRead<D extends ComponentDef<any>>(def: D & DeclaredRead<A, D>): ReadonlyComponentCursor<SchemaOf<D>>;
|
|
637
658
|
/** Whether `entityId` is currently disabled (immediate read). Toggling is
|
|
638
|
-
* deferred — `ctx.commands.disable` / `ctx.commands.enable
|
|
659
|
+
* deferred — `ctx.commands.disable` / `ctx.commands.enable`. */
|
|
639
660
|
isDisabled(entityId: EntityID): boolean;
|
|
640
661
|
/** Tags take no values argument; valued schemas require a complete one. */
|
|
641
662
|
addSparse<D extends SparseComponentDef<any>>(entityId: EntityID, def: D & DeclaredSparseWrite<A, D>, ...values: AttachValuesArg<SparseSchemaOf<D>>): this;
|
|
@@ -660,12 +681,12 @@ export declare class SystemContext<out A extends SystemAccess = SystemAccess> {
|
|
|
660
681
|
* destructions. Republishes archetype row counts into the SAB
|
|
661
682
|
* descriptor at the end so any WASM scan running in the next phase
|
|
662
683
|
* sees fresh `row_count` fields. This is one of two publish sites —
|
|
663
|
-
* `ECS.update()` also republishes once at tick start
|
|
664
|
-
*
|
|
684
|
+
* `ECS.update()` also republishes once at tick start, which covers
|
|
685
|
+
* host-side mutations between updates. The publish walks
|
|
665
686
|
* descriptors only — it doesn't touch column data — and benches at
|
|
666
687
|
* sub-microsecond per archetype, so paying it once per phase boundary
|
|
667
|
-
* is materially cheaper than the
|
|
668
|
-
* WASM-using system per tick.
|
|
688
|
+
* is materially cheaper than the earlier pattern of paying it per
|
|
689
|
+
* WASM-using system per tick. The descriptor walk is now gated
|
|
669
690
|
* on a dirty flag, so read-only phases skip the walk entirely. */
|
|
670
691
|
flush(): void;
|
|
671
692
|
/**
|
|
@@ -702,7 +723,7 @@ export declare class SystemContext<out A extends SystemAccess = SystemAccess> {
|
|
|
702
723
|
* already names it. */
|
|
703
724
|
getResource<K extends ResourceKey<any>>(key: K & DeclaredResourceRead<A, K>): ResourceValueOf<K>;
|
|
704
725
|
setResource<K extends ResourceKey<any>>(key: K & DeclaredResourceWrite<A, K>, value: ResourceValueOf<NoInfer<K>>): void;
|
|
705
|
-
/** Drop a resource mid-tick
|
|
726
|
+
/** Drop a resource mid-tick. A lifecycle mutation, so it is access-
|
|
706
727
|
* checked as a *write* — the system must declare the key in `resourceWrites`,
|
|
707
728
|
* which serialises it against readers/writers of the same resource. Fails
|
|
708
729
|
* closed on a missing key. */
|
|
@@ -722,11 +743,11 @@ export declare class ChangedQuery<Defs extends readonly ComponentDef[]> {
|
|
|
722
743
|
/** Permit optional-component data access in the loop (mirrors `Query.optional`). */
|
|
723
744
|
optional(...defs: ComponentDef[]): ChangedQuery<Defs>;
|
|
724
745
|
forEach(cb: (arch: ArchetypeView<Defs>) => void): void;
|
|
725
|
-
/** @internal — cold `includeDisabled` wrapper
|
|
726
|
-
*
|
|
746
|
+
/** @internal — cold `includeDisabled` wrapper, split out of `forEach`
|
|
747
|
+
* so the all-rows flag dance stays out of the inlined hot body. */
|
|
727
748
|
private _forEachIncludeDisabled;
|
|
728
|
-
/** @internal — the `includeDisabled` delegate for `forEach
|
|
729
|
-
* default path inlines this body directly into `forEach`
|
|
749
|
+
/** @internal — the `includeDisabled` delegate for `forEach`. The
|
|
750
|
+
* default path inlines this body directly into `forEach` to dodge a
|
|
730
751
|
* megamorphic delegate hop; this copy survives only for the rare all-rows
|
|
731
752
|
* path, which needs the `_setIterAllRows` try/finally wrap. */
|
|
732
753
|
private _forEachInner;
|