@oasys/oecs 0.4.0 → 0.5.1
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 +636 -0
- package/README.md +47 -32
- package/dist/core/ecs/access_check.d.cts +77 -0
- package/dist/core/ecs/access_check.d.ts +8 -8
- package/dist/core/ecs/access_check.d.ts.map +1 -1
- package/dist/core/ecs/archetype.d.cts +486 -0
- package/dist/core/ecs/archetype.d.ts +25 -13
- package/dist/core/ecs/archetype.d.ts.map +1 -1
- package/dist/core/ecs/archetype_graph.d.cts +96 -0
- package/dist/core/ecs/archetype_graph.d.ts +96 -0
- package/dist/core/ecs/archetype_graph.d.ts.map +1 -0
- package/dist/core/ecs/builtin_relations.d.cts +43 -0
- package/dist/core/ecs/builtin_relations.d.ts +8 -8
- package/dist/core/ecs/builtin_relations.d.ts.map +1 -1
- package/dist/core/ecs/command_log.d.cts +116 -0
- package/dist/core/ecs/command_log.d.ts +13 -10
- package/dist/core/ecs/command_log.d.ts.map +1 -1
- package/dist/core/ecs/component.d.cts +201 -0
- package/dist/core/ecs/component.d.ts +100 -5
- package/dist/core/ecs/component.d.ts.map +1 -1
- package/dist/core/ecs/compute_backend.d.cts +37 -0
- package/dist/core/ecs/compute_backend.d.ts +2 -2
- package/dist/core/ecs/debug_names.d.cts +7 -0
- package/dist/core/ecs/debug_names.d.ts +7 -0
- package/dist/core/ecs/debug_names.d.ts.map +1 -0
- package/dist/core/ecs/deferred_commands.d.cts +55 -0
- package/dist/core/ecs/deferred_commands.d.ts +55 -0
- package/dist/core/ecs/deferred_commands.d.ts.map +1 -0
- package/dist/core/ecs/dispatch_trace.d.cts +93 -0
- package/dist/core/ecs/dispatch_trace.d.ts +3 -3
- package/dist/core/ecs/ecs.d.cts +580 -0
- package/dist/core/ecs/ecs.d.ts +340 -293
- package/dist/core/ecs/ecs.d.ts.map +1 -1
- package/dist/core/ecs/ecs_memory.d.cts +179 -0
- package/dist/core/ecs/ecs_memory.d.ts +1 -1
- package/dist/core/ecs/entity.d.cts +34 -0
- package/dist/core/ecs/entity.d.ts +8 -2
- package/dist/core/ecs/entity.d.ts.map +1 -1
- package/dist/core/ecs/entity_allocator.d.cts +59 -0
- package/dist/core/ecs/entity_allocator.d.ts +59 -0
- package/dist/core/ecs/entity_allocator.d.ts.map +1 -0
- package/dist/core/ecs/event.d.cts +79 -0
- package/dist/core/ecs/event.d.ts +36 -11
- package/dist/core/ecs/event.d.ts.map +1 -1
- package/dist/core/ecs/event_registry.d.cts +22 -0
- package/dist/core/ecs/event_registry.d.ts +22 -0
- package/dist/core/ecs/event_registry.d.ts.map +1 -0
- package/dist/core/ecs/facades.d.cts +158 -0
- package/dist/core/ecs/facades.d.ts +158 -0
- package/dist/core/ecs/facades.d.ts.map +1 -0
- package/dist/core/ecs/frame_stepper.d.cts +58 -0
- package/dist/core/ecs/frame_stepper.d.ts +58 -0
- package/dist/core/ecs/frame_stepper.d.ts.map +1 -0
- package/dist/core/ecs/frame_trace.d.cts +133 -0
- package/dist/core/ecs/frame_trace.d.ts +5 -5
- package/dist/core/ecs/frame_trace.d.ts.map +1 -1
- package/dist/core/ecs/host_commands.d.cts +284 -0
- package/dist/core/ecs/host_commands.d.ts +77 -45
- package/dist/core/ecs/host_commands.d.ts.map +1 -1
- package/dist/core/ecs/index.d.cts +46 -0
- package/dist/core/ecs/index.d.ts +45 -40
- package/dist/core/ecs/index.d.ts.map +1 -1
- package/dist/core/ecs/observer.d.cts +173 -0
- package/dist/core/ecs/observer.d.ts +44 -13
- package/dist/core/ecs/observer.d.ts.map +1 -1
- package/dist/core/ecs/query.d.cts +734 -0
- package/dist/core/ecs/query.d.ts +267 -90
- package/dist/core/ecs/query.d.ts.map +1 -1
- package/dist/core/ecs/ref.d.cts +31 -0
- package/dist/core/ecs/ref.d.ts +3 -3
- package/dist/core/ecs/ref.d.ts.map +1 -1
- package/dist/core/ecs/relation.d.cts +243 -0
- package/dist/core/ecs/relation.d.ts +26 -14
- package/dist/core/ecs/relation.d.ts.map +1 -1
- package/dist/core/ecs/relation_service.d.cts +235 -0
- package/dist/core/ecs/relation_service.d.ts +235 -0
- package/dist/core/ecs/relation_service.d.ts.map +1 -0
- package/dist/core/ecs/resource.d.cts +53 -0
- package/dist/core/ecs/resource.d.ts +25 -5
- package/dist/core/ecs/resource.d.ts.map +1 -1
- package/dist/core/ecs/resource_registry.d.cts +20 -0
- package/dist/core/ecs/resource_registry.d.ts +20 -0
- package/dist/core/ecs/resource_registry.d.ts.map +1 -0
- package/dist/core/ecs/resume.d.cts +85 -0
- package/dist/core/ecs/resume.d.ts +6 -6
- package/dist/core/ecs/resume.d.ts.map +1 -1
- package/dist/core/ecs/run_condition.d.cts +81 -0
- package/dist/core/ecs/run_condition.d.ts +16 -10
- package/dist/core/ecs/run_condition.d.ts.map +1 -1
- package/dist/core/ecs/schedule.d.cts +142 -0
- package/dist/core/ecs/schedule.d.ts +15 -6
- package/dist/core/ecs/schedule.d.ts.map +1 -1
- package/dist/core/ecs/snapshot_service.d.cts +94 -0
- package/dist/core/ecs/snapshot_service.d.ts +94 -0
- package/dist/core/ecs/snapshot_service.d.ts.map +1 -0
- package/dist/core/ecs/sparse_store.d.cts +110 -0
- package/dist/core/ecs/sparse_store.d.ts +5 -2
- package/dist/core/ecs/sparse_store.d.ts.map +1 -1
- package/dist/core/ecs/store.d.cts +937 -0
- package/dist/core/ecs/store.d.ts +144 -356
- package/dist/core/ecs/store.d.ts.map +1 -1
- package/dist/core/ecs/store_layout_listener.d.cts +23 -0
- package/dist/core/ecs/system.d.cts +250 -0
- package/dist/core/ecs/system.d.ts +138 -22
- package/dist/core/ecs/system.d.ts.map +1 -1
- package/dist/{utils/arrays.d.ts → core/ecs/utils/arrays.d.cts} +1 -0
- package/dist/core/ecs/utils/error.d.cts +61 -0
- package/dist/core/ecs/utils/error.d.ts +12 -2
- package/dist/core/ecs/utils/error.d.ts.map +1 -1
- package/dist/core/store/action_ring.d.cts +136 -0
- package/dist/core/store/allocator.d.cts +238 -0
- package/dist/core/store/allocator.d.ts.map +1 -1
- package/dist/core/store/buffer_backed_column.d.cts +69 -0
- package/dist/core/store/buffer_backed_column.d.ts +2 -2
- package/dist/core/store/column_store.d.cts +273 -0
- package/dist/core/store/column_store.d.ts +18 -10
- package/dist/core/store/column_store.d.ts.map +1 -1
- package/dist/core/store/command_dispatch.d.cts +52 -0
- package/dist/core/store/command_ring.d.cts +107 -0
- package/dist/core/store/descriptor.d.cts +80 -0
- package/dist/core/store/descriptor.d.ts +1 -1
- package/dist/core/store/descriptor.d.ts.map +1 -1
- package/dist/core/store/entity_index.d.cts +108 -0
- package/dist/core/store/event_ring.d.cts +95 -0
- package/dist/core/store/extend.d.cts +39 -0
- package/dist/core/store/extend.d.ts +3 -73
- package/dist/core/store/extend.d.ts.map +1 -1
- package/dist/core/store/grow.d.cts +34 -0
- package/dist/core/store/grow.d.ts +4 -9
- package/dist/core/store/grow.d.ts.map +1 -1
- package/dist/core/store/header.d.cts +64 -0
- package/dist/core/store/header.d.ts +1 -1
- package/dist/core/store/header.d.ts.map +1 -1
- package/dist/core/store/index.d.cts +17 -0
- package/dist/core/store/index.d.ts +16 -15
- package/dist/core/store/index.d.ts.map +1 -1
- package/dist/core/store/layout_ops.d.cts +152 -0
- package/dist/core/store/layout_ops.d.ts +152 -0
- package/dist/core/store/layout_ops.d.ts.map +1 -0
- package/dist/core/store/region_table.d.cts +74 -0
- package/dist/core/store/region_table.d.ts +1 -1
- package/dist/core/store/region_table.d.ts.map +1 -1
- package/dist/core/store/snapshot.d.cts +43 -0
- package/dist/core/store/snapshot.d.ts +2 -2
- package/dist/core/store/state_hash.d.cts +38 -0
- package/dist/core/store/state_hash.d.ts +1 -1
- package/dist/core/store/store_regions.d.cts +38 -0
- package/dist/core/store/store_regions.d.ts +1 -1
- package/dist/core/store/vendored_abi/abi.d.ts +43 -0
- package/dist/core/store/{__generated__ → vendored_abi}/abi.d.ts.map +1 -1
- package/dist/dev_flag.d.cts +2 -0
- package/dist/dev_flag.d.ts +2 -0
- package/dist/dev_flag.d.ts.map +1 -0
- package/dist/extensions/editor/editor.d.cts +172 -0
- package/dist/extensions/editor/editor.d.ts +65 -42
- package/dist/extensions/editor/editor.d.ts.map +1 -1
- package/dist/extensions/editor/field_handle.d.cts +40 -0
- package/dist/extensions/editor/field_handle.d.ts +10 -5
- package/dist/extensions/editor/field_handle.d.ts.map +1 -1
- package/dist/extensions/editor/index.cjs +1 -1
- package/dist/extensions/editor/index.d.cts +21 -0
- package/dist/extensions/editor/index.d.ts +2 -2
- package/dist/extensions/editor/index.js +130 -100
- package/dist/extensions/reactive/ecs_sync.d.cts +214 -0
- package/dist/extensions/reactive/ecs_sync.d.ts +26 -22
- package/dist/extensions/reactive/ecs_sync.d.ts.map +1 -1
- package/dist/extensions/reactive/index.cjs +1 -1
- package/dist/extensions/reactive/index.d.cts +23 -0
- package/dist/extensions/reactive/index.d.ts +1 -1
- package/dist/extensions/reactive/index.js +106 -116
- package/dist/extensions/solid/index.cjs +1 -1
- package/dist/extensions/solid/index.d.cts +6 -0
- package/dist/extensions/solid/index.d.ts +2 -2
- package/dist/extensions/solid/index.js +8 -4
- package/dist/extensions/solid/kernel_solid.d.cts +45 -0
- package/dist/extensions/solid/kernel_solid.d.ts +6 -3
- package/dist/extensions/solid/kernel_solid.d.ts.map +1 -1
- package/dist/host_commands-BI8pEmjH.js +2326 -0
- package/dist/host_commands-CxhpzMx9.cjs +1 -0
- package/dist/index.cjs +1 -2
- package/dist/index.d.cts +66 -0
- package/dist/index.d.ts +50 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4489 -5898
- package/dist/internal.cjs +2 -0
- package/dist/internal.d.cts +20 -0
- package/dist/internal.d.ts +20 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +141 -0
- package/dist/primitives.cjs +1 -1
- package/dist/primitives.d.cts +18 -0
- package/dist/primitives.d.ts +6 -6
- package/dist/primitives.js +24 -23
- package/dist/reactive/array.d.ts +24 -0
- package/dist/reactive/array.d.ts.map +1 -0
- package/dist/reactive/index.cjs +1 -0
- package/dist/reactive/index.d.cts +11 -0
- package/dist/reactive/index.d.ts +11 -0
- package/dist/reactive/index.d.ts.map +1 -0
- package/dist/reactive/index.js +18 -0
- package/dist/reactive/interop.d.cts +19 -0
- package/dist/{core/reactive → reactive}/interop.d.ts +1 -1
- package/dist/reactive/interop.d.ts.map +1 -0
- package/dist/reactive/kernel.d.cts +73 -0
- package/dist/{core/reactive → reactive}/kernel.d.ts +5 -3
- package/dist/reactive/kernel.d.ts.map +1 -0
- package/dist/reactive/map.d.ts +16 -0
- package/dist/reactive/map.d.ts.map +1 -0
- package/dist/reactive/shallow.d.cts +11 -0
- package/dist/reactive/shallow.d.ts +11 -0
- package/dist/reactive/shallow.d.ts.map +1 -0
- package/dist/reactive/struct.d.cts +10 -0
- package/dist/{core/reactive → reactive}/struct.d.ts +1 -1
- package/dist/reactive/struct.d.ts.map +1 -0
- package/dist/shallow-DQ8aG51_.cjs +1 -0
- package/dist/shallow-DfnAm9vG.js +150 -0
- package/dist/shared-BU1Cd40h.js +103 -0
- package/dist/shared-BymrGTyR.cjs +1 -0
- package/dist/shared.cjs +1 -1
- package/dist/shared.d.cts +22 -0
- package/dist/shared.d.ts +2 -2
- package/dist/shared.js +1 -1
- package/dist/topological_sort-BDvEyb9W.cjs +1 -0
- package/dist/topological_sort-DK6EjpWa.js +135 -0
- package/dist/type_primitives/assertions.d.cts +32 -0
- package/dist/type_primitives/assertions.d.ts +13 -1
- package/dist/type_primitives/assertions.d.ts.map +1 -1
- package/dist/type_primitives/binary_heap/binary_heap.d.cts +37 -0
- package/dist/type_primitives/bitset/bitset.d.cts +54 -0
- package/dist/type_primitives/brand.d.cts +23 -0
- package/dist/type_primitives/error.d.cts +16 -0
- package/dist/type_primitives/error.d.ts +4 -3
- package/dist/type_primitives/error.d.ts.map +1 -1
- package/dist/type_primitives/index.d.cts +13 -0
- package/dist/type_primitives/index.d.ts +9 -9
- package/dist/type_primitives/sparse_map/sparse_map.d.cts +30 -0
- package/dist/type_primitives/sparse_set/sparse_set.d.cts +28 -0
- package/dist/type_primitives/topological_sort/topological_sort.d.cts +29 -0
- package/dist/type_primitives/typed_arrays/typed_arrays.d.cts +127 -0
- package/dist/typed_arrays-BcXcnzB4.js +258 -0
- package/dist/typed_arrays-D3NmwtCG.cjs +1 -0
- package/dist/utils/error.d.cts +6 -0
- package/dist/version.d.cts +10 -0
- package/dist/version.d.ts +10 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +102 -19
- package/dist/array-CxbPyiHO.cjs +0 -1
- package/dist/array-uFR7Q8fU.js +0 -132
- package/dist/core/reactive/array.d.ts.map +0 -1
- package/dist/core/reactive/index.cjs +0 -1
- package/dist/core/reactive/index.d.ts +0 -10
- package/dist/core/reactive/index.d.ts.map +0 -1
- package/dist/core/reactive/index.js +0 -17
- package/dist/core/reactive/interop.d.ts.map +0 -1
- package/dist/core/reactive/kernel.d.ts.map +0 -1
- package/dist/core/reactive/map.d.ts.map +0 -1
- package/dist/core/reactive/struct.d.ts.map +0 -1
- package/dist/log/console_sink.d.ts +0 -4
- package/dist/log/console_sink.d.ts.map +0 -1
- package/dist/log/index.d.ts +0 -3
- package/dist/log/index.d.ts.map +0 -1
- package/dist/log/logger.d.ts +0 -27
- package/dist/log/logger.d.ts.map +0 -1
- package/dist/shared-BXSZnxx4.cjs +0 -1
- package/dist/shared-C678TAPY.js +0 -99
- package/dist/topological_sort-DlRpSrxu.js +0 -391
- package/dist/topological_sort-WAT-VHb-.cjs +0 -1
- package/dist/utils/arrays.d.ts.map +0 -1
- package/dist/utils/constants.d.ts.map +0 -1
- /package/dist/{utils/constants.d.ts → core/ecs/utils/constants.d.cts} +0 -0
- /package/dist/core/store/{__generated__/abi.d.ts → vendored_abi/abi.d.cts} +0 -0
- /package/dist/{core/reactive/array.d.ts → reactive/array.d.cts} +0 -0
- /package/dist/{core/reactive/map.d.ts → reactive/map.d.cts} +0 -0
package/dist/core/ecs/ecs.d.ts
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
|
-
import { Template,
|
|
2
|
-
import { FrameTraceSink } from './frame_trace';
|
|
3
|
-
import { ObserverHandle, EntitySetObserverConfig, ArchetypeSetObserverConfig, StructuralObserverConfig } from './observer';
|
|
4
|
-
import { ColumnStore, ColumnStoreRegionHandle, StoreRegionSpec } from '../store';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { SystemFn, SystemConfig, SystemDescriptor } from './system';
|
|
15
|
-
import { BitSet, TypedArrayTag } from '../../type_primitives';
|
|
16
|
-
import { StoreLayoutListener } from './store_layout_listener';
|
|
17
|
-
import { ComputeBackend } from './compute_backend';
|
|
18
|
-
import { ResolvedECSMemory, ECSMemoryOptions } from './ecs_memory';
|
|
1
|
+
import { Template, TemplateOverrides } from './store.js';
|
|
2
|
+
import { FrameTraceSink } from './frame_trace.js';
|
|
3
|
+
import { ObserverHandle, EntitySetObserverConfig, ArchetypeSetObserverConfig, StructuralObserverConfig } from './observer.js';
|
|
4
|
+
import { ColumnStore, ColumnStoreRegionHandle, StoreRegionSpec } from '../store/index.js';
|
|
5
|
+
import { ECSRelations, ECSEvents, ECSResources, ECSSnapshots } from './facades.js';
|
|
6
|
+
import { SCHEDULE, SystemEntry, SystemSet, SystemSetConfig } from './schedule.js';
|
|
7
|
+
import { Archetype, ArchetypeID } from './archetype.js';
|
|
8
|
+
import { SystemContext, Query, QueryBuilder, QueryCache, QueryResolver } from './query.js';
|
|
9
|
+
import { EntityID } from './entity.js';
|
|
10
|
+
import { ReadonlyComponentRef } from './ref.js';
|
|
11
|
+
import { ComponentDef, ComponentHandle, ComponentRegisterOptions, ComponentSchema, CompleteFieldValues, Bundle, BundleOrDef, StrictBundles, DefsOf } from './component.js';
|
|
12
|
+
import { SparseComponentDef, SparseComponentID } from './sparse_store.js';
|
|
13
|
+
import { RelationDef } from './relation.js';
|
|
14
|
+
import { SystemFn, SystemConfig, SystemDescriptor, TypedSystemConfig, DenseAccessDecl, SpawnsAccessDecl, DespawnsAccessDecl, TransitionsAccessDecl, SparseAccessDecl, RelationsAccessDecl, ResourcesAccessDecl } from './system.js';
|
|
15
|
+
import { BitSet, TypedArrayTag } from '../../type_primitives/index.js';
|
|
16
|
+
import { StoreLayoutListener } from './store_layout_listener.js';
|
|
17
|
+
import { ComputeBackend } from './compute_backend.js';
|
|
18
|
+
import { ResolvedECSMemory, ECSMemoryOptions } from './ecs_memory.js';
|
|
19
19
|
export interface ECSOptions {
|
|
20
20
|
fixedTimestep?: number;
|
|
21
21
|
maxFixedSteps?: number;
|
|
22
|
+
/** Sink for dev-mode engine diagnostics (currently the schedule's
|
|
23
|
+
* dropped-ordering-edge warning). Defaults to `console.warn`. Mirrors the
|
|
24
|
+
* `FrameTraceSink` seam's injectable style — no global logger. */
|
|
25
|
+
onWarn?: (message: string) => void;
|
|
22
26
|
/** How the world's memory is sized and backed (#682) — the single
|
|
23
27
|
* sizing surface, replacing the pre-release `initialCapacity` +
|
|
24
28
|
* `bufferAllocator` pair. Express intent through exactly one arm:
|
|
@@ -64,26 +68,28 @@ export declare class ECS implements QueryResolver {
|
|
|
64
68
|
/** Component observers (#517 §1 / ADR-0013). Inert until `observe(...)` is
|
|
65
69
|
* called — the structural-flush fast path is byte-for-byte unchanged. */
|
|
66
70
|
private readonly _observers;
|
|
71
|
+
/** Relations: register/add/remove/has, wildcard + traversal reads,
|
|
72
|
+
* reverse-index compaction. See `ECSRelations`. */
|
|
73
|
+
readonly relations: ECSRelations;
|
|
74
|
+
/** Host-side event channels + signals: register/registerSignal/emit/read
|
|
75
|
+
* (system-side `ctx.emit` is unchanged). See `ECSEvents`. */
|
|
76
|
+
readonly events: ECSEvents;
|
|
77
|
+
/** World resources: register/get/set/remove/has. See `ECSResources`. */
|
|
78
|
+
readonly resources: ECSResources;
|
|
79
|
+
/** Determinism surface: capture/restore (full + sparse), stateHash,
|
|
80
|
+
* the `deterministic` flag. See `ECSSnapshots`. */
|
|
81
|
+
readonly snapshots: ECSSnapshots;
|
|
67
82
|
private readonly systems;
|
|
68
83
|
private nextSystemId;
|
|
69
84
|
private _tick;
|
|
85
|
+
private _updating;
|
|
70
86
|
private _fixedTimestep;
|
|
71
87
|
private _accumulator;
|
|
72
88
|
private _maxFixedSteps;
|
|
73
|
-
private readonly queryCache;
|
|
74
89
|
private readonly scratchMask;
|
|
75
90
|
private _nextQueryIdCounter;
|
|
76
|
-
|
|
77
|
-
readonly
|
|
78
|
-
readonly _anyOfSingleCache: Map<number, Query<any>>;
|
|
79
|
-
readonly _changedSingleCache: Map<number, ChangedQuery<any>>;
|
|
80
|
-
readonly _withSparseSingleCache: Map<number, Query<any>>;
|
|
81
|
-
readonly _withoutSparseSingleCache: Map<number, Query<any>>;
|
|
82
|
-
readonly _withRelationSingleCache: Map<number, Query<any>>;
|
|
83
|
-
readonly _withoutRelationSingleCache: Map<number, Query<any>>;
|
|
84
|
-
readonly _optionalSingleCache: Map<number, Query<any>>;
|
|
85
|
-
readonly _includeDisabledSingleCache: Map<number, Query<any>>;
|
|
86
|
-
readonly _hierarchySingleCache: Map<number, Query<any>>;
|
|
91
|
+
/** @internal Query-composition caches (QueryResolver seam) — not public API. */
|
|
92
|
+
readonly _caches: QueryCache;
|
|
87
93
|
private readonly _layoutSubscribers;
|
|
88
94
|
private _backend;
|
|
89
95
|
private readonly _memory;
|
|
@@ -98,16 +104,6 @@ export declare class ECS implements QueryResolver {
|
|
|
98
104
|
* share the same bytes. */
|
|
99
105
|
get wasmMemory(): WebAssembly.Memory | null;
|
|
100
106
|
constructor(options?: ECSOptions);
|
|
101
|
-
/** Resolve a consumer-declared SAB region's byte offset by `region_id`, or
|
|
102
|
-
* 0 when absent. Generic, de-gamed replacement (#623) for the removed
|
|
103
|
-
* game-named accessors; pair with the consumer's own region module to
|
|
104
|
-
* materialise a typed view. Delegates to `Store.regionOffset`. */
|
|
105
|
-
regionOffset(regionId: number): number;
|
|
106
|
-
/** A handle (`{ buffer, view, offset, bytes }`) to a consumer-declared SAB
|
|
107
|
-
* region resolved by `region_id`, or `null` when absent. A consumer's
|
|
108
|
-
* region module builds a TypedArray view over the region's span from this.
|
|
109
|
-
* Re-fetch after a SAB grow. Delegates to `Store.regionHandle`. (#623) */
|
|
110
|
-
regionHandle(regionId: number): ColumnStoreRegionHandle | null;
|
|
111
107
|
/** Batch variant of `regionHandle` for hosts wiring several consumer
|
|
112
108
|
* regions at startup: returns the handles in argument order, never null —
|
|
113
109
|
* throws ONE `REGION_NOT_DECLARED` naming every missing region id instead
|
|
@@ -137,44 +133,12 @@ export declare class ECS implements QueryResolver {
|
|
|
137
133
|
* the schedule to the pure-TS path.
|
|
138
134
|
*
|
|
139
135
|
* One backend per ECS: attaching while one is already attached throws in
|
|
140
|
-
* `
|
|
136
|
+
* `DEV` (detach first). The engine never inspects the backend beyond
|
|
141
137
|
* `setLayout` / `run` — it carries no game vocabulary. */
|
|
142
138
|
attachBackend(backend: ComputeBackend): () => void;
|
|
143
|
-
/** Look up the field index a component reserves for `fieldName`. The
|
|
144
|
-
* index is assigned by `registerComponent` in insertion order and is
|
|
145
|
-
* stable for the lifetime of the ECS. Used by systems that need to
|
|
146
|
-
* pass `(component_id, field_id)` pairs across the WASM FFI — the Zig
|
|
147
|
-
* side identifies columns by these numeric IDs. */
|
|
148
|
-
fieldId<S extends Record<string, TypedArrayTag>>(def: ComponentDef<S>, fieldName: Extract<keyof S, string>): number;
|
|
149
|
-
/** Resolve an archetype's row index to the `EntityID` at that slot.
|
|
150
|
-
* A WASM system that drains events from the event ring as
|
|
151
|
-
* `(archId, row, …)` payloads uses this to convert the (archId, row)
|
|
152
|
-
* pair into the `EntityID` the `ctx.emit(...)` API expects.
|
|
153
|
-
* Throws if the (archId, row) pair is out of range. (#250 / Phase 4
|
|
154
|
-
* PR 4D) */
|
|
155
|
-
entityIdAtRow(archetypeId: number, row: number): EntityID;
|
|
156
139
|
get fixedTimestep(): number;
|
|
157
140
|
set fixedTimestep(value: number);
|
|
158
141
|
get fixedAlpha(): number;
|
|
159
|
-
/** The single SAB backing every archetype's column views. Exposed for
|
|
160
|
-
* snapshot/restore, `columnStoreStateHash`-based determinism checks, and
|
|
161
|
-
* Phase 2+ WASM/worker hand-off paths. Mutation flows through the
|
|
162
|
-
* usual `addComponent` / `removeComponent` / `flush` APIs; readers
|
|
163
|
-
* that hold a column view across a grow must consult
|
|
164
|
-
* `header.view_stamp` to detect a republish (#171 §8.1). */
|
|
165
|
-
get columnStore(): ColumnStore;
|
|
166
|
-
/** Count of live archetypes (including the empty one). Surfaces the
|
|
167
|
-
* Store-side `archetype_count` so Phase C tests can assert the
|
|
168
|
-
* pre-warmed closure was materialised; equally useful for diagnostics. */
|
|
169
|
-
get archetypeCount(): number;
|
|
170
|
-
/** Count of registered relations (#471). Surfaces the Store-side count so
|
|
171
|
-
* tests can assert it alongside `archetype_count` when checking the
|
|
172
|
-
* no-transition invariant. */
|
|
173
|
-
get relationCount(): number;
|
|
174
|
-
/** Whether the determinism surface is enabled (#626 / ADR-0020). `false`
|
|
175
|
-
* (the default) ⇒ `stateHash` / `snapshotSparse` / `restoreSparse` throw
|
|
176
|
-
* `DETERMINISM_DISABLED`. Opt in via `new ECS({ deterministic: true })`. */
|
|
177
|
-
get deterministic(): boolean;
|
|
178
142
|
/** Attach (or detach with `null`) a per-world frame-trace sink (ADR-0030):
|
|
179
143
|
* the engine then fires structured `FrameTraceSink` events at each system,
|
|
180
144
|
* flush, command, observer firing, and event during `update()`, so a consumer
|
|
@@ -182,194 +146,128 @@ export declare class ECS implements QueryResolver {
|
|
|
182
146
|
* also receives a `phaseBoundary(phase)` at each phase's post-flush settle
|
|
183
147
|
* point — the safe seam to read `stateHash()` between phases of one frame and
|
|
184
148
|
* bisect a divergence to the exact phase (#797 / ADR-0032). The seam is
|
|
185
|
-
* `
|
|
149
|
+
* `DEV`-gated end to end — in a production build this setter keeps an empty
|
|
186
150
|
* body and the world never retains a sink. The sink only observes; it does not
|
|
187
151
|
* perturb `stateHash`, ordering, or any behaviour. */
|
|
188
152
|
setTrace(sink: FrameTraceSink | null): void;
|
|
189
|
-
/**
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
* (
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* Opt-in (#626 / ADR-0020): throws `DETERMINISM_DISABLED` unless the ECS was
|
|
198
|
-
* constructed with `{ deterministic: true }`. */
|
|
199
|
-
stateHash(): number;
|
|
200
|
-
/** Serialize the sparse stores (out-of-identity components, ADR-0011) to a
|
|
201
|
-
* self-contained byte buffer — the sparse half of a world snapshot, written
|
|
202
|
-
* in canonical entity-index order so it's insertion-order-independent
|
|
203
|
-
* (#470). The dense half is the SAB snapshot (`snapshotColumnStore(columnStore)`).
|
|
204
|
-
* Pairs with `restoreSparse`.
|
|
205
|
-
*
|
|
206
|
-
* Opt-in (#626 / ADR-0020): throws `DETERMINISM_DISABLED` unless the ECS was
|
|
207
|
-
* constructed with `{ deterministic: true }`. */
|
|
208
|
-
snapshotSparse(): Uint8Array;
|
|
209
|
-
/** Repopulate the sparse stores from `snapshotSparse` bytes (full-equality
|
|
210
|
-
* round-trip of membership + data). Sparse components must already be
|
|
211
|
-
* registered in the same order; throws `SparseRestoreError` on a shape or
|
|
212
|
-
* identity mismatch (store/field count, field-identity schema hash, an entity
|
|
213
|
-
* index past `MAX_INDEX`, or a non-canonical frame with trailing bytes).
|
|
214
|
-
*
|
|
215
|
-
* Opt-in (#626 / ADR-0020): throws `DETERMINISM_DISABLED` unless the ECS was
|
|
216
|
-
* constructed with `{ deterministic: true }`. */
|
|
217
|
-
restoreSparse(bytes: Uint8Array): void;
|
|
218
|
-
/** Capture the full live world — dense (SAB columns), sparse + relations, and
|
|
219
|
-
* the host-side bookkeeping the SAB omits (tick, entity recycle free-list,
|
|
220
|
-
* alive count, per-archetype row/enabled counts) — to one self-contained byte
|
|
221
|
-
* buffer that `restoreInto` can mount back onto a live, ticking world
|
|
222
|
-
* ("rewind a running world and keep ticking", #789). Take it at a tick
|
|
223
|
-
* boundary (between `update()`s).
|
|
153
|
+
/**
|
|
154
|
+
* Register a dense component and get back its typed handle. Record syntax
|
|
155
|
+
* gives per-field type control; the array shorthand types every field the
|
|
156
|
+
* same (default `"f64"` — rejected on a `{ deterministic: true }` world
|
|
157
|
+
* (#777), pass an explicit integer type there). An empty schema `{}` is a
|
|
158
|
+
* tag. `opts.name` labels dev-mode diagnostics (`'Pos' (component 5)`
|
|
159
|
+
* instead of `component 5`) — diagnostic only, no behavioural effect.
|
|
224
160
|
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* scheduler baselines (`changed()` queries) — see ADR-0031. */
|
|
228
|
-
snapshot(): Uint8Array;
|
|
229
|
-
/** Mount a `snapshot()` buffer onto this live world and leave it ready to keep
|
|
230
|
-
* ticking (#789). Fails closed on a malformed frame or a registration mismatch
|
|
231
|
-
* (different component/archetype graph, mismatched entity-index capacity, or a
|
|
232
|
-
* divergent sparse-store registration) BEFORE mutating any live state — the
|
|
233
|
-
* guard reads the snapshot's descriptors + sparse-section shape from the bytes,
|
|
234
|
-
* since the dense build reuses (and overwrites) the live in-place backing.
|
|
235
|
-
* Throws `WorldRestoreError` (dense) / `SparseRestoreError` (sparse). Requires a
|
|
236
|
-
* world whose archetype set + column layout match the snapshot's (prewarm so the
|
|
237
|
-
* set is stable).
|
|
161
|
+
* The handle is *callable*: `Pos({ x: 1 })` mints a `Bundle` for the
|
|
162
|
+
* attach surfaces (`spawnBundle`, `ctx.commands.spawn`, `addComponent`).
|
|
238
163
|
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
164
|
+
* @example
|
|
165
|
+
* const Pos = ecs.registerComponent({ x: "f64", y: "f64" });
|
|
166
|
+
* const Hp = ecs.registerComponent(["current", "max"], "i32");
|
|
167
|
+
* const Frozen = ecs.registerComponent({}, { name: "Frozen" }); // tag
|
|
168
|
+
* ecs.getField(e, Pos, "x"); // field names/types flow from the schema
|
|
169
|
+
*/
|
|
170
|
+
registerComponent<S extends Record<string, TypedArrayTag>>(schema: S, opts?: ComponentRegisterOptions): ComponentDef<S>;
|
|
171
|
+
registerComponent<const F extends readonly string[], T extends TypedArrayTag = "f64">(fields: F, type?: T, opts?: ComponentRegisterOptions): ComponentDef<{
|
|
244
172
|
readonly [K in F[number]]: T;
|
|
245
173
|
}>;
|
|
246
|
-
|
|
247
|
-
registerSparseComponent<
|
|
248
|
-
registerSparseComponent<const F extends readonly string[], T extends TypedArrayTag = "f64">(fields: F, type?: T): SparseComponentDef<{
|
|
174
|
+
registerSparseComponent<S extends Record<string, TypedArrayTag>>(schema: S, opts?: ComponentRegisterOptions): SparseComponentDef<S>;
|
|
175
|
+
registerSparseComponent<const F extends readonly string[], T extends TypedArrayTag = "f64">(fields: F, type?: T, opts?: ComponentRegisterOptions): SparseComponentDef<{
|
|
249
176
|
readonly [K in F[number]]: T;
|
|
250
177
|
}>;
|
|
251
|
-
/**
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
setResource<T>(key: ResourceKey<T>, value: T): void;
|
|
258
|
-
/** Drop a resource from the world (#798). Unlike {@link registerResource}
|
|
259
|
-
* — a one-time world-setup op — this is a runtime mutation, so it is access-
|
|
260
|
-
* checked as a *write* (a system removing a resource must declare it in
|
|
261
|
-
* `resourceWrites`, which is what serialises it against readers/writers of the
|
|
262
|
-
* same key). Fails closed on a missing key. Afterwards the key is free to
|
|
263
|
-
* `registerResource` again — the present → absent → present lifecycle.
|
|
264
|
-
* Resources are out of `stateHash` and snapshot/resume, so a remove never
|
|
265
|
-
* perturbs the determinism hash. */
|
|
266
|
-
removeResource<T>(key: ResourceKey<T>): void;
|
|
267
|
-
hasResource<T>(key: ResourceKey<T>): boolean;
|
|
268
|
-
createEntity(): EntityID;
|
|
269
|
-
createEntity<Defs extends readonly ComponentDef[]>(template: Template<Defs>, overrides?: TemplateOverrides<Defs>): EntityID;
|
|
270
|
-
/** Register an archetype template (#462). Resolves the component set +
|
|
271
|
-
* default field values to a target archetype once (creating it if absent —
|
|
272
|
-
* fits the prewarm model), so later `spawn` / `spawnMany` calls land
|
|
273
|
-
* entities directly in that archetype with **zero archetype transitions**.
|
|
178
|
+
/**
|
|
179
|
+
* Spawn an entity, immediately. Bare `spawn()` creates an empty entity —
|
|
180
|
+
* attach components afterward. `spawn(template, overrides?)` lands
|
|
181
|
+
* directly in the template's archetype with zero archetype transitions,
|
|
182
|
+
* applying optional flat per-field overrides on top of the template
|
|
183
|
+
* defaults. Inside a system use `ctx.commands.spawn(...)` instead.
|
|
274
184
|
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
* ]);
|
|
185
|
+
* @example
|
|
186
|
+
* const e = ecs.spawn();
|
|
187
|
+
* ecs.addComponent(e, Pos, { x: 0, y: 0 });
|
|
279
188
|
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
/** Bulk-spawn `count` identical entities from `template`. Field writes are
|
|
286
|
-
* O(columns) (one `TypedArray.fill` per column), not O(count×columns).
|
|
287
|
-
* Returns the new ids in spawn order. */
|
|
288
|
-
createEntities(template: Template, count: number): EntityID[];
|
|
189
|
+
* const Bullet = ecs.template([{ def: Pos, values: { x: 0, y: 0 } }]);
|
|
190
|
+
* const b = ecs.spawn(Bullet, { x: 5 }); // override a template default
|
|
191
|
+
*/
|
|
192
|
+
spawn(): EntityID;
|
|
193
|
+
spawn<Defs extends readonly ComponentDef[]>(template: Template<Defs>, overrides?: TemplateOverrides<Defs>): EntityID;
|
|
289
194
|
/**
|
|
290
195
|
* Spawn an entity from varargs bundles (§bundles) — the immediate
|
|
291
|
-
* host-side analog of `ctx.commands.spawn
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
196
|
+
* host-side analog of `ctx.commands.spawn`, and the same callable-bundle
|
|
197
|
+
* grammar as `addComponents` / `template`. `ecs.spawnBundle(Pos({x,y}),
|
|
198
|
+
* Vel({vx:1}), IsEnemy)` collapses the attach shapes into one; each item is
|
|
199
|
+
* checked against its own def's schema (`StrictBundles`). Bundles are applied
|
|
200
|
+
* immediately; a single combined-archetype insertion (one transition instead
|
|
201
|
+
* of one-per-component) is a later optimization — for now this mirrors the
|
|
202
|
+
* per-component `addComponent` path (unlike `addComponents`, which batches).
|
|
203
|
+
*
|
|
204
|
+
* Immediate — inside a system use the deferred `ctx.commands.spawn(...)`
|
|
205
|
+
* (calling this from a system body throws in DEV). Note the redirect trades
|
|
206
|
+
* timing: `commands.spawn` returns the id now but defers the attaches to the
|
|
207
|
+
* phase flush, so the entity sits in its empty/partial archetype until then —
|
|
208
|
+
* unlike `spawnBundle`'s immediate, fully-populated archetype.
|
|
209
|
+
*/
|
|
210
|
+
spawnBundle<Items extends readonly BundleOrDef[]>(...items: StrictBundles<Items>): EntityID;
|
|
211
|
+
/** Bulk-spawn `count` entities from `template`, optionally applying one
|
|
212
|
+
* shared `overrides` object to every spawned row (same typed keys as
|
|
213
|
+
* `spawn`). Field writes are O(columns) (one `TypedArray.fill` per
|
|
214
|
+
* column), not O(count×columns). Returns the new ids in spawn order.
|
|
215
|
+
* Immediate — inside a system use `ctx.commands.spawn` per entity (calling
|
|
216
|
+
* this from a system body throws in DEV). */
|
|
217
|
+
spawnMany<Defs extends readonly ComponentDef[]>(template: Template<Defs>, count: number, overrides?: TemplateOverrides<Defs>): EntityID[];
|
|
218
|
+
/** DEV-only: throw when an *immediate* host structural mutator is called
|
|
219
|
+
* from inside one of THIS world's system bodies (or an observer / onAdded
|
|
220
|
+
* hook — they run in the same access spans). One rule for every host
|
|
221
|
+
* structural mutator — despawn, add/remove(Components), batchAdd/Remove,
|
|
222
|
+
* disable/enable, AND the spawn family (spawn/spawnBundle/spawnMany): an
|
|
223
|
+
* immediate structural op mid-schedule can move or swap rows a running query
|
|
224
|
+
* is walking — or, for a spawn-append into that archetype, trip a column
|
|
225
|
+
* realloc under it — and it is invisible to observers. The archetype-level
|
|
226
|
+
* `_iterDepth` guard only catches mutations touching the archetype currently
|
|
227
|
+
* being iterated (and the append paths skip even that), so an op landing
|
|
228
|
+
* elsewhere would silently skip observers; the receiver rule ("inside a
|
|
229
|
+
* system, use ctx.commands") is enforced wholesale here.
|
|
230
|
+
*
|
|
231
|
+
* `_updating` scopes the guard to THIS world: the accessCheck slot is
|
|
232
|
+
* process-global, so without it a system of world A mutating world B (a
|
|
233
|
+
* supported #785 pattern — B is not mid-iteration) would false-throw. */
|
|
234
|
+
private _assertHostMutationOutsideSystem;
|
|
235
|
+
/** Immediately destroy an entity — `ecs.despawn(e); ecs.isAlive(e)` is
|
|
236
|
+
* `false` on the next line, matching the immediacy of every other host
|
|
237
|
+
* facade mutation. Inside a system the buffered path is
|
|
238
|
+
* `ctx.commands.despawn` (applied at the phase flush); calling this from
|
|
239
|
+
* a system body throws in DEV, since an immediate destroy mid-iteration
|
|
240
|
+
* can invalidate rows the running query is walking. */
|
|
241
|
+
despawn(entityId: EntityID): this;
|
|
242
|
+
/** Disable `entityId` (idempotent). Excluded from default queries until re-enabled. */
|
|
243
|
+
disable(entityId: EntityID): this;
|
|
244
|
+
/** Re-enable a disabled `entityId` (idempotent). */
|
|
245
|
+
enable(entityId: EntityID): this;
|
|
246
|
+
/**
|
|
247
|
+
* Attach a component to an entity, immediately (inside a system, use the
|
|
248
|
+
* deferred `ctx.commands.add`). Three shapes: a bare def attaches a tag; a
|
|
249
|
+
* bundle (`Pos({ x: 1 })`) zero-fills omitted fields; the explicit
|
|
250
|
+
* `(e, def, values)` form demands every field, so a typo'd or missing
|
|
251
|
+
* field is a compile error.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ecs.addComponent(e, Frozen); // tag
|
|
255
|
+
* ecs.addComponent(e, Pos({ x: 1 })); // bundle — y zero-fills
|
|
256
|
+
* ecs.addComponent(e, Pos, { x: 1, y: 2 }); // complete values
|
|
296
257
|
*/
|
|
297
|
-
spawnBundle(...items: BundleOrDef[]): EntityID;
|
|
298
|
-
/** Buffer an entity for deferred destruction (applied at the next phase
|
|
299
|
-
* flush — matches the semantics of `SystemContext.destroyEntity`). The
|
|
300
|
-
* ECS surface is unsuffixed because the context (`ECS` vs Store) already
|
|
301
|
-
* implies the mode; `Store.destroyEntity` is the immediate path. */
|
|
302
|
-
destroyEntity(id: EntityID): void;
|
|
303
|
-
isAlive(id: EntityID): boolean;
|
|
304
|
-
get entityCount(): number;
|
|
305
258
|
addComponent(entityId: EntityID, def: ComponentDef<Record<string, never>>): this;
|
|
306
|
-
addComponent<S extends ComponentSchema>(entityId: EntityID,
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
259
|
+
addComponent<S extends ComponentSchema>(entityId: EntityID, bundle: Bundle<S>): this;
|
|
260
|
+
addComponent<S extends ComponentSchema>(entityId: EntityID, def: ComponentDef<S>, values: CompleteFieldValues<S>): this;
|
|
261
|
+
/** Batch-attach several components in one archetype transition. Takes the
|
|
262
|
+
* same callable-bundle varargs as `spawnBundle` — `world.addComponents(e,
|
|
263
|
+
* Pos({ x, y }), Vel({ vx }), Frozen)` — each item checked against its own
|
|
264
|
+
* def's schema (a misspelled or cross-component field is a compile error;
|
|
265
|
+
* tags refuse values). Omitted fields zero-fill. */
|
|
266
|
+
addComponents<Items extends readonly BundleOrDef[]>(entityId: EntityID, ...items: StrictBundles<Items>): this;
|
|
311
267
|
removeComponent(entityId: EntityID, def: ComponentDef): this;
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
disable(id: EntityID): this;
|
|
316
|
-
/** Re-enable a disabled `id` (idempotent). */
|
|
317
|
-
enable(id: EntityID): this;
|
|
318
|
-
/** Whether `id` is currently disabled. */
|
|
319
|
-
isDisabled(id: EntityID): boolean;
|
|
320
|
-
addSparse(entityId: EntityID, def: SparseComponentDef<Record<string, never>>): this;
|
|
321
|
-
addSparse<S extends ComponentSchema>(entityId: EntityID, def: SparseComponentDef<S>, values: FieldValues<S>): this;
|
|
322
|
-
removeSparse(entityId: EntityID, def: SparseComponentDef): this;
|
|
323
|
-
hasSparse(entityId: EntityID, def: SparseComponentDef): boolean;
|
|
324
|
-
getSparseField<S extends ComponentSchema>(entityId: EntityID, def: SparseComponentDef<S>, field: string & keyof S): number;
|
|
325
|
-
setSparseField<S extends ComponentSchema>(entityId: EntityID, def: SparseComponentDef<S>, field: string & keyof S, value: number): void;
|
|
326
|
-
/** Register a relation kind. Exclusive (default) stores one target per
|
|
327
|
-
* source in a backing sparse component; `{ multi: true }` stores a target
|
|
328
|
-
* set per source. `{ onDeleteTarget: "delete" | "clear" | "orphan" }`
|
|
329
|
-
* selects what happens to a relation's sources when a target is destroyed
|
|
330
|
-
* (default `orphan`, #473). See `registerRelation` on `Store` / ADR-0011. */
|
|
331
|
-
registerRelation(opts?: RelationOptions): RelationDef;
|
|
332
|
-
/** Add a `(R, tgt)` pair to `src`. Exclusive replaces the existing target;
|
|
333
|
-
* multi adds to the set. No archetype transition. */
|
|
334
|
-
addRelation(src: EntityID, def: RelationDef, tgt: EntityID): this;
|
|
335
|
-
/** Remove a `(R, tgt)` pair from `src`. For multi, omitting `tgt` removes
|
|
336
|
-
* all of `src`'s targets. No archetype transition. */
|
|
337
|
-
removeRelation(src: EntityID, def: RelationDef, tgt?: EntityID): this;
|
|
338
|
-
/** The single target of `src` under an exclusive relation, or `undefined`. */
|
|
339
|
-
targetOf(src: EntityID, def: RelationDef): EntityID | undefined;
|
|
340
|
-
/** All targets of `src` under `R`, ascending by id. */
|
|
341
|
-
targetsOf(src: EntityID, def: RelationDef): EntityID[];
|
|
342
|
-
/** Sources pointing at `tgt` under `R` (the reverse index), ascending by id. */
|
|
343
|
-
sourcesOf(def: RelationDef, tgt: EntityID): EntityID[];
|
|
344
|
-
/** Whether `src` holds any pair under `R`. */
|
|
345
|
-
hasRelation(src: EntityID, def: RelationDef): boolean;
|
|
346
|
-
/** All `(source, target)` pairs of relation `R` — the `(R, *)` wildcard
|
|
347
|
-
* (#472). Sources in canonical entity-index order; a multi source's targets
|
|
348
|
-
* ascending by id. Cold path. */
|
|
349
|
-
pairsOf(def: RelationDef): [EntityID, EntityID][];
|
|
350
|
-
/** Every `(relation, source)` pointing at `tgt`, across all relation kinds —
|
|
351
|
-
* the `(*, T)` wildcard (#472). Ordered by relation id then source id. The
|
|
352
|
-
* single-relation form is `sourcesOf(def, tgt)`. */
|
|
353
|
-
sourcesOfAny(tgt: EntityID): [RelationDef, EntityID][];
|
|
354
|
-
/** Reclaim relation reverse-index memory: drop every reverse entry whose
|
|
355
|
-
* target has been destroyed, returning the total dropped (#491). Under the
|
|
356
|
-
* default `orphan` policy a destroyed target's reverse entry lingers until
|
|
357
|
-
* each source re-targets or dies, so orphan-pointing at a churn of
|
|
358
|
-
* short-lived targets grows the index without bound. A purely cold-path
|
|
359
|
-
* reclaim — no observable state change (forward links stay dangling per
|
|
360
|
-
* `orphan`, `stateHash` is unaffected) — call it at scene/snapshot
|
|
361
|
-
* boundaries. */
|
|
362
|
-
compactRelations(): number;
|
|
363
|
-
/** Walk relation `R` up from `src` to its chain root, returning
|
|
364
|
-
* `[src, parent, …, root]` (nearest-ancestor-first). Exclusive only. */
|
|
365
|
-
ancestorsOf(src: EntityID, def: RelationDef): EntityID[];
|
|
366
|
-
/** The root of `src`'s `R`-chain (`src` itself when it has no target).
|
|
367
|
-
* Exclusive only. */
|
|
368
|
-
rootOf(src: EntityID, def: RelationDef): EntityID;
|
|
369
|
-
/** Walk relation `R` down from `root` over the reverse index, returning the
|
|
370
|
-
* subtree (including `root`) breadth-first — parents before children (the
|
|
371
|
-
* `cascade` order). Exclusive only. */
|
|
372
|
-
cascadeOf(root: EntityID, def: RelationDef): EntityID[];
|
|
268
|
+
/** Detach several components in one archetype transition — the varargs
|
|
269
|
+
* mirror of `addComponents` (bare defs; removing needs no values). */
|
|
270
|
+
removeComponents(entityId: EntityID, ...defs: ComponentDef[]): this;
|
|
373
271
|
/**
|
|
374
272
|
* Bulk add a component to ALL entities in the given archetype.
|
|
375
273
|
* O(columns) via TypedArray.set() instead of O(N×columns).
|
|
@@ -377,31 +275,215 @@ export declare class ECS implements QueryResolver {
|
|
|
377
275
|
* Takes an `ArchetypeID` (from `ArchetypeView.id`) rather than a concrete
|
|
378
276
|
* `Archetype` — the concrete type is internal (issue #378).
|
|
379
277
|
*/
|
|
380
|
-
batchAddComponent(src: ArchetypeID, def: ComponentDef<Record<string, never>>):
|
|
381
|
-
batchAddComponent<S extends ComponentSchema>(src: ArchetypeID, def: ComponentDef<S>, values:
|
|
278
|
+
batchAddComponent(src: ArchetypeID, def: ComponentDef<Record<string, never>>): this;
|
|
279
|
+
batchAddComponent<S extends ComponentSchema>(src: ArchetypeID, def: ComponentDef<S>, values: CompleteFieldValues<S>): this;
|
|
382
280
|
/**
|
|
383
281
|
* Bulk remove a component from ALL entities in the given archetype.
|
|
384
282
|
* O(columns) via TypedArray.set() instead of O(N×columns).
|
|
385
283
|
*
|
|
386
284
|
* Takes an `ArchetypeID` (from `ArchetypeView.id`); see `batchAddComponent`.
|
|
387
285
|
*/
|
|
388
|
-
batchRemoveComponent(src: ArchetypeID, def: ComponentDef):
|
|
286
|
+
batchRemoveComponent(src: ArchetypeID, def: ComponentDef): this;
|
|
389
287
|
getField<S extends ComponentSchema>(entityId: EntityID, def: ComponentDef<S>, field: string & keyof S): number;
|
|
288
|
+
/** Host-side parity with `SystemContext.refRead` (POLISH_AUDIT M7): a
|
|
289
|
+
* read-only whole-component view for tooling/tests, instead of reading
|
|
290
|
+
* field-by-field. Same advisory-`readonly` semantics as the ctx variant;
|
|
291
|
+
* no `_changedTick` bump. Dev-throws on a dead entity, or when the entity
|
|
292
|
+
* doesn't hold the component (tags included — no fields, nothing to ref).
|
|
293
|
+
*
|
|
294
|
+
* **Staleness:** unlike ctx refs (protected by deferred structural changes
|
|
295
|
+
* until the phase flush), host-side structural mutations apply immediately —
|
|
296
|
+
* any `addComponent`/`removeComponent`/`despawn` after creating the ref can
|
|
297
|
+
* row-swap so the old ref silently reads *another entity's* data. The ref is
|
|
298
|
+
* only valid until the next structural mutation; treat it as an immediate
|
|
299
|
+
* single-expression read and re-create it after any structural change. */
|
|
300
|
+
refRead<S extends ComponentSchema>(def: ComponentDef<S>, entityId: EntityID): ReadonlyComponentRef<S>;
|
|
301
|
+
/** Total sibling of {@link getField} (POLISH_AUDIT #9): `undefined` when the
|
|
302
|
+
* entity is dead or doesn't hold the component, instead of a dev throw /
|
|
303
|
+
* prod garbage read. The safe way to probe-and-read in one call:
|
|
304
|
+
* `ecs.tryGetField(e, Health, "current") ?? 0`. */
|
|
305
|
+
tryGetField<S extends ComponentSchema>(entityId: EntityID, def: ComponentDef<S>, field: string & keyof S): number | undefined;
|
|
390
306
|
setField<S extends ComponentSchema>(entityId: EntityID, def: ComponentDef<S>, field: string & keyof S, value: number): void;
|
|
391
307
|
/** Read-modify-write one field: `updateField(e, Gold, "value", v => v - cost)`
|
|
392
308
|
* is the one-line form of the `getField` → compute → `setField` round trip.
|
|
393
309
|
* Returns the written value. Same access-check and observer semantics as the
|
|
394
310
|
* two calls it composes. */
|
|
395
311
|
updateField<S extends ComponentSchema>(entityId: EntityID, def: ComponentDef<S>, field: string & keyof S, fn: (current: number) => number): number;
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
312
|
+
/**
|
|
313
|
+
* Get the live, cached query matching entities that have **all** of
|
|
314
|
+
* `defs`. Queries are deduplicated by mask — calling this twice with the
|
|
315
|
+
* same terms returns the same instance — so build once at setup and reuse;
|
|
316
|
+
* the view stays live as archetypes appear. Refine with `.and()` /
|
|
317
|
+
* `.without()` / `.anyOf()`; iterate with `eachChunk` (mutating hot path),
|
|
318
|
+
* `forEach` (per-archetype), or `forEachEntity` (per-entity).
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* const movers = ecs.query(Pos, Vel);
|
|
322
|
+
* movers.eachChunk((cols, count) => {
|
|
323
|
+
* const { x, y } = cols.mut(Pos);
|
|
324
|
+
* const { vx, vy } = cols.read(Vel);
|
|
325
|
+
* for (let i = 0; i < count; i++) { x[i] += vx[i]; y[i] += vy[i]; }
|
|
326
|
+
* });
|
|
327
|
+
*/
|
|
399
328
|
query<T extends ComponentDef[]>(...defs: T): Query<T>;
|
|
329
|
+
_nextQueryId(): number;
|
|
330
|
+
/** QueryResolver implementation — creates or retrieves a cached Query. */
|
|
331
|
+
_resolveQuery(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, defs: readonly ComponentDef[]): Query<any>;
|
|
332
|
+
/**
|
|
333
|
+
* Register a system and get its scheduling handle. The config form is the
|
|
334
|
+
* production shape: it declares the access surface (`reads` / `writes` are
|
|
335
|
+
* mandatory; `spawns` / `despawns` / resource and sparse/relation terms
|
|
336
|
+
* optional), which is enforced at runtime in dev *and* narrows `ctx` at
|
|
337
|
+
* the type level so undeclared access fails to compile. Registration does
|
|
338
|
+
* not schedule — pass the returned descriptor to
|
|
339
|
+
* `ecs.addSystems(SCHEDULE.UPDATE, ...)`.
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* // Full config — declared access, dev-checked and compile-checked
|
|
343
|
+
* const move = ecs.registerSystem({
|
|
344
|
+
* reads: [Vel],
|
|
345
|
+
* writes: [Pos],
|
|
346
|
+
* fn(ctx, dt) {
|
|
347
|
+
* movers.eachChunk((cols, count) => { ... });
|
|
348
|
+
* },
|
|
349
|
+
* });
|
|
350
|
+
* ecs.addSystems(SCHEDULE.UPDATE, move);
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* // Bare function (no declared access — any component touch throws in dev)
|
|
354
|
+
* ecs.registerSystem((ctx, dt) => { ... });
|
|
355
|
+
* // Function + query builder (query resolved at registration time)
|
|
356
|
+
* ecs.registerSystem((q, ctx, dt) => { q.forEach((arch) => { ... }); }, (qb) => qb.with(Pos, Vel));
|
|
357
|
+
*/
|
|
358
|
+
registerSystem(fn: SystemFn): SystemDescriptor;
|
|
359
|
+
registerSystem<Defs extends readonly ComponentDef[]>(fn: (q: Query<Defs>, ctx: SystemContext, dt: number) => void, queryFn: (qb: QueryBuilder) => Query<Defs>): SystemDescriptor;
|
|
360
|
+
/** `exclusive: true` grants full world access at runtime (§system.ts), so
|
|
361
|
+
* the context stays fully permissive at the type layer too. Declared BEFORE
|
|
362
|
+
* the typed-config overload so exclusive configs never get narrowed. */
|
|
363
|
+
registerSystem(config: SystemConfig & {
|
|
364
|
+
readonly exclusive: true;
|
|
365
|
+
}): SystemDescriptor;
|
|
366
|
+
/** Config form (§typestate, system.ts): the declaration lists are inferred
|
|
367
|
+
* as literal tuples and `fn` / `onAdded` receive
|
|
368
|
+
* `SystemContext<DeclaredAccess<…>>` — undeclared access fails to compile
|
|
369
|
+
* with the same taxonomy the runtime `accessCheck` throws with in
|
|
370
|
+
* `DEV`. A config VALUE typed as plain `SystemConfig` (dynamically
|
|
371
|
+
* built) still matches: its erased declaration lists compute a permissive
|
|
372
|
+
* access record. Escape hatch: annotate `fn(ctx: SystemContext, dt)`
|
|
373
|
+
* explicitly to keep a system permissive at compile time. */
|
|
374
|
+
registerSystem<R extends DenseAccessDecl, W extends DenseAccessDecl, Sp extends SpawnsAccessDecl = readonly never[], De extends DespawnsAccessDecl = readonly never[], Tr extends TransitionsAccessDecl = readonly never[], SR extends SparseAccessDecl = readonly never[], SW extends SparseAccessDecl = readonly never[], RR extends RelationsAccessDecl = readonly never[], RW extends RelationsAccessDecl = readonly never[], QR extends ResourcesAccessDecl = readonly never[], QW extends ResourcesAccessDecl = readonly never[]>(config: TypedSystemConfig<R, W, Sp, De, Tr, SR, SW, RR, RW, QR, QW>): SystemDescriptor;
|
|
375
|
+
removeSystem(system: SystemDescriptor): this;
|
|
376
|
+
get systemCount(): number;
|
|
377
|
+
/**
|
|
378
|
+
* Run the startup phases, once, before the first `update()`. Prewarms
|
|
379
|
+
* every archetype the registered systems/observers can produce, runs each
|
|
380
|
+
* system's `onAdded` hook, then the `PRE_STARTUP` → `STARTUP` →
|
|
381
|
+
* `POST_STARTUP` schedule. Events emitted during startup are drained at
|
|
382
|
+
* its tail — they do not leak into frame 1.
|
|
383
|
+
*
|
|
384
|
+
* @example
|
|
385
|
+
* ecs.addSystems(SCHEDULE.UPDATE, move);
|
|
386
|
+
* ecs.startup();
|
|
387
|
+
* ecs.update(1 / 60); // now tick every frame
|
|
388
|
+
*/
|
|
389
|
+
startup(): void;
|
|
390
|
+
/** Compute the archetype closure from every registered system's AND
|
|
391
|
+
* observer's `spawns` + `transitions` and ask the store to plant the
|
|
392
|
+
* whole set in one `extendColumnStore` call. Observers carry the same
|
|
393
|
+
* access shape systems do (a synthesized `SystemDescriptor`), so an
|
|
394
|
+
* observer that spawns/transitions gets its target archetype prewarmed
|
|
395
|
+
* too rather than first-touching lazily mid-tick (#768). Exposed as
|
|
396
|
+
* `private` because the only caller is `startup()`; visible to tests via
|
|
397
|
+
* the `archetype_count` delta on the public ECS facade. */
|
|
398
|
+
private prewarmArchetypes;
|
|
399
|
+
/**
|
|
400
|
+
* Advance the world one frame. Runs the fixed-timestep accumulator loop
|
|
401
|
+
* (`FIXED_UPDATE`, when any fixed system is registered), then
|
|
402
|
+
* `PRE_UPDATE` → `UPDATE` → `POST_UPDATE`, flushing deferred structural
|
|
403
|
+
* commands at each phase boundary. Events emitted this tick are readable
|
|
404
|
+
* for the rest of the tick and cleared at the tail. `dt` is in seconds.
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* let last = performance.now();
|
|
408
|
+
* function frame(now: number) {
|
|
409
|
+
* ecs.update((now - last) / 1000);
|
|
410
|
+
* last = now;
|
|
411
|
+
* requestAnimationFrame(frame);
|
|
412
|
+
* }
|
|
413
|
+
* requestAnimationFrame(frame);
|
|
414
|
+
*/
|
|
415
|
+
update(dt: number): void;
|
|
416
|
+
dispose(): void;
|
|
417
|
+
/** Register an archetype template (#462). Resolves the component set +
|
|
418
|
+
* default field values to a target archetype once (creating it if absent —
|
|
419
|
+
* fits the prewarm model), so later `spawn` / `spawnMany` calls land
|
|
420
|
+
* entities directly in that archetype with **zero archetype transitions**.
|
|
421
|
+
*
|
|
422
|
+
* const Bullet = ecs.template(Position({ x: 0, y: 0 }), Velocity({ vx: 0, vy: 0 }));
|
|
423
|
+
*
|
|
424
|
+
* Takes the same callable-bundle varargs as `spawnBundle` / `addComponents`
|
|
425
|
+
* (each item schema-checked against its own def); the resulting
|
|
426
|
+
* `Template<[Position, Velocity]>` keeps the typed key set that `spawn`'s
|
|
427
|
+
* `overrides` map over. Not a pass-through — it normalizes bundles to the
|
|
428
|
+
* store's entry shape, so it lives here with the other real logic, not in the
|
|
429
|
+
* delegation band. The big win is multi-component entities and bulk spawns; a
|
|
430
|
+
* single-component spawn is no faster than `spawn` + `addComponent`, which
|
|
431
|
+
* already bump-allocates a fresh entity into the target archetype. See
|
|
432
|
+
* ADR-0010. */
|
|
433
|
+
template<Items extends readonly BundleOrDef[]>(...items: StrictBundles<Items>): Template<DefsOf<Items>>;
|
|
434
|
+
/** Resolve a consumer-declared SAB region's byte offset by `region_id`, or
|
|
435
|
+
* 0 when absent. Generic, de-gamed replacement (#623) for the removed
|
|
436
|
+
* game-named accessors; pair with the consumer's own region module to
|
|
437
|
+
* materialise a typed view. Delegates to `Store.regionOffset`. */
|
|
438
|
+
regionOffset(regionId: number): number;
|
|
439
|
+
/** A handle (`{ buffer, view, offset, bytes }`) to a consumer-declared SAB
|
|
440
|
+
* region resolved by `region_id`, or `null` when absent. A consumer's
|
|
441
|
+
* region module builds a TypedArray view over the region's span from this.
|
|
442
|
+
* Re-fetch after a SAB grow. Delegates to `Store.regionHandle`. (#623) */
|
|
443
|
+
regionHandle(regionId: number): ColumnStoreRegionHandle | null;
|
|
444
|
+
/** Look up the field index a component reserves for `fieldName`. The
|
|
445
|
+
* index is assigned by `registerComponent` in insertion order and is
|
|
446
|
+
* stable for the lifetime of the ECS. Used by systems that need to
|
|
447
|
+
* pass `(component_id, field_id)` pairs across the WASM FFI — the Zig
|
|
448
|
+
* side identifies columns by these numeric IDs. */
|
|
449
|
+
fieldId<S extends Record<string, TypedArrayTag>>(def: ComponentDef<S>, fieldName: Extract<keyof S, string>): number;
|
|
450
|
+
/** Resolve an archetype's row index to the `EntityID` at that slot.
|
|
451
|
+
* A WASM system that drains events from the event ring as
|
|
452
|
+
* `(archId, row, …)` payloads uses this to convert the (archId, row)
|
|
453
|
+
* pair into the `EntityID` the `ctx.emit(...)` API expects.
|
|
454
|
+
* Throws if the (archId, row) pair is out of range. (#250 / Phase 4
|
|
455
|
+
* PR 4D) */
|
|
456
|
+
entityIdAtRow(archetypeId: number, row: number): EntityID;
|
|
457
|
+
/** The single SAB backing every archetype's column views. Exposed for
|
|
458
|
+
* snapshot/restore, `columnStoreStateHash`-based determinism checks, and
|
|
459
|
+
* Phase 2+ WASM/worker hand-off paths. Mutation flows through the
|
|
460
|
+
* usual `addComponent` / `removeComponent` / `flush` APIs; readers
|
|
461
|
+
* that hold a column view across a grow must consult
|
|
462
|
+
* `header.view_stamp` to detect a republish (#171 §8.1). */
|
|
463
|
+
get columnStore(): ColumnStore;
|
|
464
|
+
/** Count of live archetypes (including the empty one). Surfaces the
|
|
465
|
+
* Store-side `archetype_count` so Phase C tests can assert the
|
|
466
|
+
* pre-warmed closure was materialised; equally useful for diagnostics. */
|
|
467
|
+
get archetypeCount(): number;
|
|
468
|
+
registerTag(): ComponentDef<Record<string, never>>;
|
|
469
|
+
/** Register a sparse tag (empty schema) — membership only, no data. */
|
|
470
|
+
registerSparseTag(): SparseComponentDef<Record<string, never>>;
|
|
471
|
+
isAlive(entityId: EntityID): boolean;
|
|
472
|
+
get entityCount(): number;
|
|
473
|
+
hasComponent(entityId: EntityID, def: ComponentDef): boolean;
|
|
474
|
+
/** Whether `entityId` is currently disabled. Toggle via `disable` / `enable`
|
|
475
|
+
* (immediate, above the band — they carry the in-system dev guard). */
|
|
476
|
+
isDisabled(entityId: EntityID): boolean;
|
|
477
|
+
addSparse(entityId: EntityID, def: SparseComponentDef<Record<string, never>>): this;
|
|
478
|
+
addSparse<S extends ComponentSchema>(entityId: EntityID, def: SparseComponentDef<S>, values: CompleteFieldValues<S>): this;
|
|
479
|
+
removeSparse(entityId: EntityID, def: SparseComponentDef): this;
|
|
480
|
+
hasSparse(entityId: EntityID, def: SparseComponentDef): boolean;
|
|
481
|
+
getSparseField<S extends ComponentSchema>(entityId: EntityID, def: SparseComponentDef<S>, field: string & keyof S): number;
|
|
482
|
+
setSparseField<S extends ComponentSchema>(entityId: EntityID, def: SparseComponentDef<S>, field: string & keyof S, value: number): void;
|
|
400
483
|
_getLastRunTick(): number;
|
|
401
484
|
/** Current ECS write tick — the tick `eachChunk` stamps via `cols.mut` (§eachChunk). */
|
|
402
485
|
_getCurrentTick(): number;
|
|
403
486
|
_getQueryDirtyEpoch(): number;
|
|
404
|
-
_nextQueryId(): number;
|
|
405
487
|
/** QueryResolver implementation — sparse-membership match path (#469). */
|
|
406
488
|
_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;
|
|
407
489
|
/** QueryResolver implementation — backing sparse id of a relation, for the
|
|
@@ -411,27 +493,6 @@ export declare class ECS implements QueryResolver {
|
|
|
411
493
|
_forEachRelationTargetMatch(target: EntityID, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
|
|
412
494
|
/** QueryResolver implementation — depth-ordered hierarchy match path (#581). */
|
|
413
495
|
_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;
|
|
414
|
-
/** QueryResolver implementation — creates or retrieves a cached Query. */
|
|
415
|
-
_resolveQuery(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, defs: readonly ComponentDef[]): Query<any>;
|
|
416
|
-
private _findCached;
|
|
417
|
-
/**
|
|
418
|
-
* Register a system.
|
|
419
|
-
*
|
|
420
|
-
* // Bare function (no query, no lifecycle hooks)
|
|
421
|
-
* world.registerSystem((ctx, dt) => { ... });
|
|
422
|
-
*
|
|
423
|
-
* // Function + query builder (query resolved at registration time)
|
|
424
|
-
* world.registerSystem(
|
|
425
|
-
* (q, ctx, dt) => { q.forEach((arch) => { ... }); },
|
|
426
|
-
* (qb) => qb.with(Pos, Vel),
|
|
427
|
-
* );
|
|
428
|
-
*
|
|
429
|
-
* // Full config — declares reads/writes (dev-checked) + optional lifecycle hooks
|
|
430
|
-
* world.registerSystem({ reads: [Pos, Vel], writes: [Pos], fn(ctx, dt) { ... } });
|
|
431
|
-
*/
|
|
432
|
-
registerSystem(fn: SystemFn): SystemDescriptor;
|
|
433
|
-
registerSystem<Defs extends readonly ComponentDef[]>(fn: (q: Query<Defs>, ctx: SystemContext, dt: number) => void, queryFn: (qb: QueryBuilder) => Query<Defs>): SystemDescriptor;
|
|
434
|
-
registerSystem(config: SystemConfig): SystemDescriptor;
|
|
435
496
|
addSystems(label: SCHEDULE, ...entries: (SystemDescriptor | SystemEntry)[]): this;
|
|
436
497
|
/**
|
|
437
498
|
* Configure a `SystemSet` (#576) — the shared run condition and/or ordering
|
|
@@ -439,8 +500,6 @@ export declare class ECS implements QueryResolver {
|
|
|
439
500
|
* `addSystems`: see `Schedule.configureSet`. Returns `this` to chain.
|
|
440
501
|
*/
|
|
441
502
|
configureSet(set: SystemSet, config: SystemSetConfig): this;
|
|
442
|
-
removeSystem(system: SystemDescriptor): void;
|
|
443
|
-
get systemCount(): number;
|
|
444
503
|
/**
|
|
445
504
|
* Register a per-component observer (#517 §1 / ADR-0013). Reactions that were
|
|
446
505
|
* hand-polled every tick — "on `Death` added → spawn corpse", "on `HexPos`
|
|
@@ -455,8 +514,8 @@ export declare class ECS implements QueryResolver {
|
|
|
455
514
|
* when an entity carrying the component is *disabled* / *enabled* (#577,
|
|
456
515
|
* ADR-0023), once per net transition, for every component the entity carries
|
|
457
516
|
* (a disable is a soft remove of the whole mask from default queries). Like
|
|
458
|
-
* `onAdd`/`onRemove`, an *immediate* `
|
|
459
|
-
* the deferred `ctx.disable()` toggle does. `yieldExisting` seeds enabled
|
|
517
|
+
* `onAdd`/`onRemove`, an *immediate* `ecs.disable()` does not fire — only
|
|
518
|
+
* the deferred `ctx.commands.disable()` toggle does. `yieldExisting` seeds enabled
|
|
460
519
|
* members only, so a disabled entity is correctly absent at seed.
|
|
461
520
|
* - **`onSet`** fires at the post-update detection point. Default
|
|
462
521
|
* `granularity: "archetype"` fires `(arch, ctx)` once per changed
|
|
@@ -469,24 +528,13 @@ export declare class ECS implements QueryResolver {
|
|
|
469
528
|
*
|
|
470
529
|
* Observer callbacks that touch ECS state must declare it via `access`
|
|
471
530
|
* (merged over an all-empty declaration) — undeclared access throws in
|
|
472
|
-
* `
|
|
531
|
+
* `DEV`, and those decls drive the firing order. `yieldExisting` replays
|
|
473
532
|
* `onAdd` over current matches on registration. Register at world-build time
|
|
474
533
|
* (before `startup()`); the returned handle's `dispose()` unregisters.
|
|
475
534
|
*/
|
|
476
|
-
observe
|
|
477
|
-
observe
|
|
478
|
-
observe
|
|
479
|
-
startup(): void;
|
|
480
|
-
/** Compute the archetype closure from every registered system's AND
|
|
481
|
-
* observer's `spawns` + `transitions` and ask the store to plant the
|
|
482
|
-
* whole set in one `extendColumnStore` call. Observers carry the same
|
|
483
|
-
* access shape systems do (a synthesized `SystemDescriptor`), so an
|
|
484
|
-
* observer that spawns/transitions gets its target archetype prewarmed
|
|
485
|
-
* too rather than first-touching lazily mid-tick (#768). Exposed as
|
|
486
|
-
* `private` because the only caller is `startup()`; visible to tests via
|
|
487
|
-
* the `archetype_count` delta on the public ECS facade. */
|
|
488
|
-
private prewarmArchetypes;
|
|
489
|
-
update(dt: number): void;
|
|
535
|
+
observe(def: ComponentHandle, config: StructuralObserverConfig): ObserverHandle;
|
|
536
|
+
observe(def: ComponentHandle, config: EntitySetObserverConfig): ObserverHandle;
|
|
537
|
+
observe(def: ComponentHandle, config: ArchetypeSetObserverConfig): ObserverHandle;
|
|
490
538
|
/**
|
|
491
539
|
* Stamp every SAB-backed archetype's live `length` into its SAB
|
|
492
540
|
* descriptor's `row_count` field. **You usually don't need to call
|
|
@@ -501,7 +549,6 @@ export declare class ECS implements QueryResolver {
|
|
|
501
549
|
*/
|
|
502
550
|
publishArchetypeRowCounts(): void;
|
|
503
551
|
flush(): void;
|
|
504
|
-
dispose(): void;
|
|
505
552
|
}
|
|
506
553
|
/** Phase C of issue #213 — archetype closure from a descriptor set.
|
|
507
554
|
*
|