@oasys/oecs 0.3.1 → 0.4.0
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/README.md +196 -267
- package/dist/array-CxbPyiHO.cjs +1 -0
- package/dist/array-uFR7Q8fU.js +132 -0
- package/dist/core/ecs/access_check.d.ts +77 -0
- package/dist/core/ecs/access_check.d.ts.map +1 -0
- package/dist/core/ecs/archetype.d.ts +474 -0
- package/dist/core/ecs/archetype.d.ts.map +1 -0
- package/dist/core/ecs/builtin_relations.d.ts +43 -0
- package/dist/core/ecs/builtin_relations.d.ts.map +1 -0
- package/dist/core/ecs/command_log.d.ts +113 -0
- package/dist/core/ecs/command_log.d.ts.map +1 -0
- package/dist/core/ecs/component.d.ts +106 -0
- package/dist/core/ecs/component.d.ts.map +1 -0
- package/dist/core/ecs/compute_backend.d.ts +37 -0
- package/dist/core/ecs/compute_backend.d.ts.map +1 -0
- package/dist/core/ecs/dispatch_trace.d.ts +93 -0
- package/dist/core/ecs/dispatch_trace.d.ts.map +1 -0
- package/dist/core/ecs/ecs.d.ts +533 -0
- package/dist/core/ecs/ecs.d.ts.map +1 -0
- package/dist/core/ecs/ecs_memory.d.ts +179 -0
- package/dist/core/ecs/ecs_memory.d.ts.map +1 -0
- package/dist/core/ecs/entity.d.ts +28 -0
- package/dist/core/ecs/entity.d.ts.map +1 -0
- package/dist/core/ecs/event.d.ts +54 -0
- package/dist/core/ecs/event.d.ts.map +1 -0
- package/dist/core/ecs/frame_trace.d.ts +133 -0
- package/dist/core/ecs/frame_trace.d.ts.map +1 -0
- package/dist/core/ecs/host_commands.d.ts +252 -0
- package/dist/core/ecs/host_commands.d.ts.map +1 -0
- package/dist/core/ecs/index.d.ts +41 -0
- package/dist/core/ecs/index.d.ts.map +1 -0
- package/dist/core/ecs/observer.d.ts +142 -0
- package/dist/core/ecs/observer.d.ts.map +1 -0
- package/dist/core/ecs/query.d.ts +557 -0
- package/dist/core/ecs/query.d.ts.map +1 -0
- package/dist/core/ecs/ref.d.ts +31 -0
- package/dist/core/ecs/ref.d.ts.map +1 -0
- package/dist/core/ecs/relation.d.ts +231 -0
- package/dist/core/ecs/relation.d.ts.map +1 -0
- package/dist/core/ecs/resource.d.ts +33 -0
- package/dist/core/ecs/resource.d.ts.map +1 -0
- package/dist/core/ecs/resume.d.ts +85 -0
- package/dist/core/ecs/resume.d.ts.map +1 -0
- package/dist/core/ecs/run_condition.d.ts +75 -0
- package/dist/core/ecs/run_condition.d.ts.map +1 -0
- package/dist/core/ecs/schedule.d.ts +133 -0
- package/dist/core/ecs/schedule.d.ts.map +1 -0
- package/dist/core/ecs/sparse_store.d.ts +107 -0
- package/dist/core/ecs/sparse_store.d.ts.map +1 -0
- package/dist/core/ecs/store.d.ts +1149 -0
- package/dist/core/ecs/store.d.ts.map +1 -0
- package/dist/core/ecs/store_layout_listener.d.ts +23 -0
- package/dist/core/ecs/store_layout_listener.d.ts.map +1 -0
- package/dist/core/ecs/system.d.ts +134 -0
- package/dist/core/ecs/system.d.ts.map +1 -0
- package/dist/core/ecs/utils/arrays.d.ts +7 -0
- package/dist/core/ecs/utils/arrays.d.ts.map +1 -0
- package/dist/core/ecs/utils/constants.d.ts +12 -0
- package/dist/core/ecs/utils/constants.d.ts.map +1 -0
- package/dist/core/ecs/utils/error.d.ts +51 -0
- package/dist/core/ecs/utils/error.d.ts.map +1 -0
- package/dist/core/reactive/array.d.ts +24 -0
- package/dist/core/reactive/array.d.ts.map +1 -0
- package/dist/core/reactive/index.cjs +1 -0
- package/dist/core/reactive/index.d.ts +10 -0
- package/dist/core/reactive/index.d.ts.map +1 -0
- package/dist/core/reactive/index.js +17 -0
- package/dist/core/reactive/interop.d.ts +19 -0
- package/dist/core/reactive/interop.d.ts.map +1 -0
- package/dist/core/reactive/kernel.d.ts +71 -0
- package/dist/core/reactive/kernel.d.ts.map +1 -0
- package/dist/core/reactive/map.d.ts +16 -0
- package/dist/core/reactive/map.d.ts.map +1 -0
- package/dist/core/reactive/struct.d.ts +10 -0
- package/dist/core/reactive/struct.d.ts.map +1 -0
- package/dist/core/store/__generated__/abi.d.ts +43 -0
- package/dist/core/store/__generated__/abi.d.ts.map +1 -0
- package/dist/core/store/action_ring.d.ts +136 -0
- package/dist/core/store/action_ring.d.ts.map +1 -0
- package/dist/core/store/allocator.d.ts +238 -0
- package/dist/core/store/allocator.d.ts.map +1 -0
- package/dist/core/store/buffer_backed_column.d.ts +69 -0
- package/dist/core/store/buffer_backed_column.d.ts.map +1 -0
- package/dist/core/store/column_store.d.ts +265 -0
- package/dist/core/store/column_store.d.ts.map +1 -0
- package/dist/core/store/command_dispatch.d.ts +52 -0
- package/dist/core/store/command_dispatch.d.ts.map +1 -0
- package/dist/core/store/command_ring.d.ts +107 -0
- package/dist/core/store/command_ring.d.ts.map +1 -0
- package/dist/core/store/descriptor.d.ts +80 -0
- package/dist/core/store/descriptor.d.ts.map +1 -0
- package/dist/core/store/entity_index.d.ts +108 -0
- package/dist/core/store/entity_index.d.ts.map +1 -0
- package/dist/core/store/event_ring.d.ts +95 -0
- package/dist/core/store/event_ring.d.ts.map +1 -0
- package/dist/core/store/extend.d.ts +109 -0
- package/dist/core/store/extend.d.ts.map +1 -0
- package/dist/core/store/grow.d.ts +39 -0
- package/dist/core/store/grow.d.ts.map +1 -0
- package/dist/core/store/header.d.ts +64 -0
- package/dist/core/store/header.d.ts.map +1 -0
- package/dist/core/store/index.d.ts +16 -0
- package/dist/core/store/index.d.ts.map +1 -0
- package/dist/core/store/region_table.d.ts +74 -0
- package/dist/core/store/region_table.d.ts.map +1 -0
- package/dist/core/store/snapshot.d.ts +43 -0
- package/dist/core/store/snapshot.d.ts.map +1 -0
- package/dist/core/store/state_hash.d.ts +38 -0
- package/dist/core/store/state_hash.d.ts.map +1 -0
- package/dist/core/store/store_regions.d.ts +38 -0
- package/dist/core/store/store_regions.d.ts.map +1 -0
- package/dist/extensions/editor/editor.d.ts +149 -0
- package/dist/extensions/editor/editor.d.ts.map +1 -0
- package/dist/extensions/editor/field_handle.d.ts +35 -0
- package/dist/extensions/editor/field_handle.d.ts.map +1 -0
- package/dist/extensions/editor/index.cjs +1 -0
- package/dist/extensions/editor/index.d.ts +21 -0
- package/dist/extensions/editor/index.d.ts.map +1 -0
- package/dist/extensions/editor/index.js +209 -0
- package/dist/extensions/reactive/ecs_sync.d.ts +210 -0
- package/dist/extensions/reactive/ecs_sync.d.ts.map +1 -0
- package/dist/extensions/reactive/index.cjs +1 -0
- package/dist/extensions/reactive/index.d.ts +23 -0
- package/dist/extensions/reactive/index.d.ts.map +1 -0
- package/dist/extensions/reactive/index.js +225 -0
- package/dist/extensions/solid/index.cjs +1 -0
- package/dist/extensions/solid/index.d.ts +6 -0
- package/dist/extensions/solid/index.d.ts.map +1 -0
- package/dist/extensions/solid/index.js +32 -0
- package/dist/extensions/solid/kernel_solid.d.ts +42 -0
- package/dist/extensions/solid/kernel_solid.d.ts.map +1 -0
- package/dist/index.cjs +2 -1
- package/dist/index.d.ts +16 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8565 -1310
- package/dist/interop-CT-REx0W.cjs +1 -0
- package/dist/interop-CcY6ASQc.js +18 -0
- package/dist/kernel-DgyrLFjW.js +227 -0
- package/dist/kernel-yWV3XnAb.cjs +1 -0
- package/dist/log/console_sink.d.ts +4 -0
- package/dist/log/console_sink.d.ts.map +1 -0
- package/dist/log/index.d.ts +3 -0
- package/dist/log/index.d.ts.map +1 -0
- package/dist/log/logger.d.ts +27 -0
- package/dist/log/logger.d.ts.map +1 -0
- package/dist/primitives.cjs +1 -0
- package/dist/primitives.d.ts +18 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +44 -0
- package/dist/shared-BXSZnxx4.cjs +1 -0
- package/dist/shared-C678TAPY.js +99 -0
- package/dist/shared.cjs +1 -0
- package/dist/shared.d.ts +22 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +7 -0
- package/dist/topological_sort-DlRpSrxu.js +391 -0
- package/dist/topological_sort-WAT-VHb-.cjs +1 -0
- package/dist/type_primitives/assertions.d.ts +12 -8
- package/dist/type_primitives/assertions.d.ts.map +1 -1
- package/dist/type_primitives/binary_heap/binary_heap.d.ts +6 -2
- package/dist/type_primitives/binary_heap/binary_heap.d.ts.map +1 -1
- package/dist/type_primitives/bitset/bitset.d.ts +16 -4
- package/dist/type_primitives/bitset/bitset.d.ts.map +1 -1
- package/dist/type_primitives/brand.d.ts +6 -1
- package/dist/type_primitives/brand.d.ts.map +1 -1
- package/dist/type_primitives/error.d.ts +4 -0
- package/dist/type_primitives/error.d.ts.map +1 -1
- package/dist/type_primitives/index.d.ts +3 -0
- package/dist/type_primitives/index.d.ts.map +1 -1
- package/dist/type_primitives/sparse_map/sparse_map.d.ts +7 -3
- package/dist/type_primitives/sparse_map/sparse_map.d.ts.map +1 -1
- package/dist/type_primitives/sparse_set/sparse_set.d.ts +4 -0
- package/dist/type_primitives/sparse_set/sparse_set.d.ts.map +1 -1
- package/dist/type_primitives/topological_sort/topological_sort.d.ts +7 -3
- package/dist/type_primitives/topological_sort/topological_sort.d.ts.map +1 -1
- package/dist/type_primitives/typed_arrays/typed_arrays.d.ts +53 -16
- package/dist/type_primitives/typed_arrays/typed_arrays.d.ts.map +1 -1
- package/dist/utils/arrays.d.ts +1 -1
- package/dist/utils/arrays.d.ts.map +1 -1
- package/dist/utils/error.d.ts +2 -20
- package/dist/utils/error.d.ts.map +1 -1
- package/package.json +36 -9
- package/dist/archetype.d.ts +0 -108
- package/dist/archetype.d.ts.map +0 -1
- package/dist/component.d.ts +0 -45
- package/dist/component.d.ts.map +0 -1
- package/dist/ecs.d.ts +0 -104
- package/dist/ecs.d.ts.map +0 -1
- package/dist/entity.d.ts +0 -11
- package/dist/entity.d.ts.map +0 -1
- package/dist/event.d.ts +0 -30
- package/dist/event.d.ts.map +0 -1
- package/dist/query.d.ts +0 -94
- package/dist/query.d.ts.map +0 -1
- package/dist/ref.d.ts +0 -23
- package/dist/ref.d.ts.map +0 -1
- package/dist/resource.d.ts +0 -23
- package/dist/resource.d.ts.map +0 -1
- package/dist/schedule.d.ts +0 -45
- package/dist/schedule.d.ts.map +0 -1
- package/dist/store.d.ts +0 -118
- package/dist/store.d.ts.map +0 -1
- package/dist/system.d.ts +0 -16
- package/dist/system.d.ts.map +0 -1
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { Brand } from '../../type_primitives';
|
|
2
|
+
import { EntityID } from './entity';
|
|
3
|
+
import { SparseComponentDef, SparseComponentStore } from './sparse_store';
|
|
4
|
+
/** Relation handle id. A separate id space from `ComponentID` and
|
|
5
|
+
* `SparseComponentID` — it indexes `Store`'s relation registry. The numeric
|
|
6
|
+
* value is the registration order, stable for the lifetime of the ECS. */
|
|
7
|
+
export type RelationID = Brand<number, "relation_id">;
|
|
8
|
+
declare const __relationBrand: unique symbol;
|
|
9
|
+
export type RelationDef = RelationID & {
|
|
10
|
+
readonly [__relationBrand]: "relation";
|
|
11
|
+
};
|
|
12
|
+
/** Access sentinel for the `(*, T)` wildcard query iteration
|
|
13
|
+
* (`Query.forEachRelatedTo`, #579). A `(*, T)` term reads **every** registered
|
|
14
|
+
* relation's reverse index to find sources of `T`, so it can't name a specific
|
|
15
|
+
* relation in `relationReads` the way `withRelation(R)` (`(R, *)`) can. A
|
|
16
|
+
* system that iterates a `(*, T)` wildcard lists `ANY_RELATION` in `relationReads`
|
|
17
|
+
* instead; `accessCheck.checkRelationReadAny` honors it. The numeric value is a
|
|
18
|
+
* reserved sentinel far past any real registration-order relation id (relations are
|
|
19
|
+
* minted from 0 upward), so it can never collide with a registered relation. */
|
|
20
|
+
export declare const ANY_RELATION: RelationDef;
|
|
21
|
+
/** Cleanup policy applied to a relation's **sources** when one of its
|
|
22
|
+
* **targets** is destroyed (#473). Chosen per-relation at registration, run at
|
|
23
|
+
* destroy-flush (and the immediate-destroy path) off the reverse index:
|
|
24
|
+
*
|
|
25
|
+
* - **`delete`** — cascade: destroy every source of the dead target too,
|
|
26
|
+
* recursively for chains/trees (the canonical ChildOf case).
|
|
27
|
+
* - **`clear`** — remove the relation from every source; the sources survive.
|
|
28
|
+
* - **`orphan`** — leave the link intact but dangling. Reads stay safe (the
|
|
29
|
+
* reverse index is `EntityID`-keyed, so the dead handle never aliases a
|
|
30
|
+
* recycled slot); `targetOf` returns a dead handle until the source
|
|
31
|
+
* re-targets or is removed. This is the pre-#473 behaviour and the default.
|
|
32
|
+
*/
|
|
33
|
+
export type OnDeleteTarget = "delete" | "clear" | "orphan";
|
|
34
|
+
/** Default on-target-delete policy: leave the link dangling (pre-#473
|
|
35
|
+
* behaviour, zero change for callers that don't opt in). */
|
|
36
|
+
export declare const DEFAULT_ON_DELETE_TARGET: OnDeleteTarget;
|
|
37
|
+
/** Registration options. `exclusive` (one target per source) is the default;
|
|
38
|
+
* pass `{ multi: true }` for a multi-target relation. The two are mutually
|
|
39
|
+
* exclusive — passing both throws. `onDeleteTarget` selects the cleanup
|
|
40
|
+
* policy applied to sources when a target is destroyed (default `orphan`). */
|
|
41
|
+
export interface RelationOptions {
|
|
42
|
+
readonly exclusive?: boolean;
|
|
43
|
+
readonly multi?: boolean;
|
|
44
|
+
readonly onDeleteTarget?: OnDeleteTarget;
|
|
45
|
+
}
|
|
46
|
+
/** Field name carrying the target `EntityID` on an exclusive relation's backing
|
|
47
|
+
* sparse component. Field 0 of a single-field schema. */
|
|
48
|
+
export declare const RELATION_TARGET_FIELD = "target";
|
|
49
|
+
/** Receives one canonical `(source index, sorted targets)` set during a fold
|
|
50
|
+
* over a multi relation's forward sets. Targets are ascending by id; empty sets
|
|
51
|
+
* are never yielded (see `forEachCanonicalTargetSet`). */
|
|
52
|
+
export type CanonicalTargetSetFn = (sourceIndex: number, targets: readonly EntityID[]) => void;
|
|
53
|
+
/** Receives one canonical `(source, target)` pair during a fold over a
|
|
54
|
+
* relation's forward links. Sources ascend by entity index, each source's
|
|
55
|
+
* targets ascend by id — the #470 determinism order. */
|
|
56
|
+
export type CanonicalPairFn = (source: EntityID, target: EntityID) => void;
|
|
57
|
+
/** Maps a source entity **index** to its full `EntityID` (generation from the
|
|
58
|
+
* live slot). Supplied by `Store`, which owns entity generations. */
|
|
59
|
+
export type MakeSourceID = (index: number) => EntityID;
|
|
60
|
+
/** One relation's derived side state. **Abstract over cardinality (#498):** the
|
|
61
|
+
* base owns the cardinality-agnostic **reverse index** (target → sources, keyed
|
|
62
|
+
* by full `EntityID` so a recycled slot can't alias a dead target's sources) and
|
|
63
|
+
* a handle on the backing `SparseComponentStore`; the forward representation and
|
|
64
|
+
* its sparse interaction are owned by the concrete `ExclusiveRelationStore` /
|
|
65
|
+
* `MultiRelationStore` (built by `makeRelationStore`).
|
|
66
|
+
*
|
|
67
|
+
* `Store` owns what is genuinely its own — entity liveness, registration, and
|
|
68
|
+
* destroy orchestration — and drives a relation through the virtual `link` /
|
|
69
|
+
* `unlink` / `purgeSource` / `forEachCanonicalPair` / … without ever
|
|
70
|
+
* branching on cardinality. Each cardinality keeps forward link + reverse index
|
|
71
|
+
* + sparse membership in lockstep inside one method on one class, so the
|
|
72
|
+
* lockstep can't be broken by missing a scattered `if (rs.exclusive)` site. */
|
|
73
|
+
export declare abstract class RelationStore {
|
|
74
|
+
/** `true` → one target per source (target in the sparse field); `false` →
|
|
75
|
+
* a set of targets per source. The cardinality discriminant survives as a
|
|
76
|
+
* field because it is part of the snapshot header and the traversal/`targetOf`
|
|
77
|
+
* mode guards — but the forward *mechanics* are virtual, not branched on it. */
|
|
78
|
+
readonly exclusive: boolean;
|
|
79
|
+
/** Backing sparse component def: `{ target: f64 }` when exclusive, a tag when
|
|
80
|
+
* multi. Carries membership (and the target, when exclusive). */
|
|
81
|
+
readonly sparse: SparseComponentDef;
|
|
82
|
+
/** Cleanup policy applied to this relation's sources when a target is
|
|
83
|
+
* destroyed (#473). `orphan` (the default) is a no-op — the link dangles
|
|
84
|
+
* safely. `Store` reads this at destroy-flush off `sourcesOf`. */
|
|
85
|
+
readonly onDeleteTarget: OnDeleteTarget;
|
|
86
|
+
/** The backing sparse store instance. Owned for registration/liveness by
|
|
87
|
+
* `Store`, but the relation drives the forward/membership rows on it directly
|
|
88
|
+
* — that is the cardinality interaction this class now encapsulates (#498). */
|
|
89
|
+
protected readonly _store: SparseComponentStore;
|
|
90
|
+
/** target `EntityID` → set of source `EntityID`s. Keyed by the full id, not
|
|
91
|
+
* the index, so a recycled target slot can't alias a dead target's sources.
|
|
92
|
+
* An entry is dropped the moment its set empties (`unlinkReverse`). */
|
|
93
|
+
private readonly _reverse;
|
|
94
|
+
constructor(exclusive: boolean, sparse: SparseComponentDef, store: SparseComponentStore, onDeleteTarget: OnDeleteTarget);
|
|
95
|
+
/** Record that `src` points at `tgt` in the reverse index. */
|
|
96
|
+
protected linkReverse(tgt: EntityID, src: EntityID): void;
|
|
97
|
+
/** Drop the `src → tgt` edge from the reverse index, removing the target's
|
|
98
|
+
* entry entirely once its last source is gone (so a dead-target key doesn't
|
|
99
|
+
* linger with an empty set). */
|
|
100
|
+
protected unlinkReverse(tgt: EntityID, src: EntityID): void;
|
|
101
|
+
/** Drop every reverse-index entry whose **target** is no longer alive,
|
|
102
|
+
* returning the count dropped (#491). The `orphan` policy intentionally
|
|
103
|
+
* leaves a destroyed target's reverse entry intact (the link dangles
|
|
104
|
+
* safely), so a long-lived source that orphan-points at a stream of
|
|
105
|
+
* short-lived targets and never re-targets/dies accumulates dead-target keys
|
|
106
|
+
* without bound. This is the reclaim primitive behind `Store.compactRelations`
|
|
107
|
+
* — a cold path the host calls at scene/snapshot boundaries. It is
|
|
108
|
+
* cardinality-free (reverse-index only), so it lives on the base unchanged.
|
|
109
|
+
*
|
|
110
|
+
* Pure index reclaim: the **forward** links (the exclusive sparse target
|
|
111
|
+
* field, the multi forward set) are left untouched, so `targetOf` /
|
|
112
|
+
* `targetsOf` still return the dangling dead handle exactly as `orphan`
|
|
113
|
+
* promises. The reverse index is derived, so dropping a dead-target entry
|
|
114
|
+
* changes nothing observable except `sourcesOf` on that dead handle (which
|
|
115
|
+
* goes from the dangling sources to `[]` — meaningless either way, the target
|
|
116
|
+
* is gone) and is faithfully rebuilt by snapshot/restore from the surviving
|
|
117
|
+
* forward links. Only the **target** role can leak here: a destroyed *source*
|
|
118
|
+
* is already unlinked from every reverse set by `purgeSource`, so a live
|
|
119
|
+
* target's set never holds a dead source. `isAlive` is supplied by `Store`,
|
|
120
|
+
* which owns entity liveness. Deleting during `Map` key iteration is
|
|
121
|
+
* well-defined — already-visited and not-yet-reached keys are unaffected. */
|
|
122
|
+
pruneDeadReverse(isAlive: (id: EntityID) => boolean): number;
|
|
123
|
+
/** Sources that point at `tgt`, ascending by id (deterministic, cold-path
|
|
124
|
+
* sort) — empty when none. */
|
|
125
|
+
sourcesOf(tgt: EntityID): EntityID[];
|
|
126
|
+
/** Drop every derived side index — the reverse index and (for multi) the
|
|
127
|
+
* forward target sets. Restore path only (`restoreRelations`): the side
|
|
128
|
+
* indices are rebuilt from scratch, so they're cleared first to stay
|
|
129
|
+
* idempotent when restoring into a dirty world. The backing sparse store is
|
|
130
|
+
* cleared separately by `restoreSparseStores`. */
|
|
131
|
+
resetIndices(): void;
|
|
132
|
+
/** Clear this relation's forward representation (multi: the side map;
|
|
133
|
+
* exclusive: nothing — its forward links live in the sparse store, cleared by
|
|
134
|
+
* `restoreSparseStores`). */
|
|
135
|
+
protected abstract _resetForward(): void;
|
|
136
|
+
/** Add a `(R, tgt)` link from `src`, keeping forward link + membership +
|
|
137
|
+
* reverse index in lockstep. Exclusive: replaces any existing target
|
|
138
|
+
* (idempotent if `tgt` is already the target). Multi: adds to the set
|
|
139
|
+
* (idempotent on a duplicate), establishing the membership tag on the first
|
|
140
|
+
* target. `src` must be live — `Store` checks before delegating (#495). */
|
|
141
|
+
abstract link(src: EntityID, tgt: EntityID): void;
|
|
142
|
+
/** Remove `(R, tgt)` from `src` — or, when `tgt` is omitted, every target of
|
|
143
|
+
* `src` — keeping forward link + membership + reverse index in lockstep. A
|
|
144
|
+
* no-op when the link isn't present. */
|
|
145
|
+
abstract unlink(src: EntityID, tgt?: EntityID): void;
|
|
146
|
+
/** Purge a destroyed **source**: drop its forward link(s) and unlink it from
|
|
147
|
+
* every target's reverse set, but leave the sparse **membership** row alone —
|
|
148
|
+
* `Store._purgeSparse` drops that (for every store) right after, so this
|
|
149
|
+
* runs first and must not double-remove. */
|
|
150
|
+
abstract purgeSource(src: EntityID): void;
|
|
151
|
+
/** The single target of source `index`, or `undefined`. Exclusive reads the
|
|
152
|
+
* sparse field; multi has no single target and returns `undefined` (matching
|
|
153
|
+
* the production `targetOf`-on-multi read, which the `__DEV__` guard rejects). */
|
|
154
|
+
abstract singleTarget(index: number): EntityID | undefined;
|
|
155
|
+
/** All targets of source `index`, ascending by id — one or zero for
|
|
156
|
+
* exclusive, the full sorted set for multi. The symmetric counterpart to
|
|
157
|
+
* `sourcesOf` (#498 item 4). */
|
|
158
|
+
abstract targetsOf(index: number): EntityID[];
|
|
159
|
+
/** Whether source `index` holds any target under this relation (sparse
|
|
160
|
+
* membership). */
|
|
161
|
+
abstract has(index: number): boolean;
|
|
162
|
+
/** Fold `cb` over this relation's **multi** forward target sets in canonical
|
|
163
|
+
* order (sources ascending by index, each source's targets ascending by id),
|
|
164
|
+
* skipping empty sets. The single source of truth for the canonical multi
|
|
165
|
+
* traversal shared by `stateHash`, `snapshotRelations`, and `pairsOf`
|
|
166
|
+
* (#498 item 1). Exclusive relations contribute via the sparse store, so this
|
|
167
|
+
* is a no-op for them. */
|
|
168
|
+
abstract forEachCanonicalTargetSet(cb: CanonicalTargetSetFn): void;
|
|
169
|
+
/** Fold `cb` over every `(source, target)` pair of this relation in canonical
|
|
170
|
+
* order — the `(R, *)` wildcard drive order (#472). `makeId` maps a source
|
|
171
|
+
* index to its full `EntityID`. Exclusive rides the backing store's
|
|
172
|
+
* `canonicalIndices`; multi rides `forEachCanonicalTargetSet`. */
|
|
173
|
+
abstract forEachCanonicalPair(makeId: MakeSourceID, cb: CanonicalPairFn): void;
|
|
174
|
+
/** Rebuild the reverse index from the forward links after a restore.
|
|
175
|
+
* Exclusive reads it back from the just-restored sparse target field (the
|
|
176
|
+
* reverse index is never serialized); multi already rebuilt its reverse edges
|
|
177
|
+
* in `restoreAddTarget`, so this is a no-op for it. `makeId` maps a source
|
|
178
|
+
* index to its full `EntityID`. */
|
|
179
|
+
abstract rebuildReverseFromForward(makeId: MakeSourceID): void;
|
|
180
|
+
/** Restore one decoded multi forward edge `(source index → tgt)` plus its
|
|
181
|
+
* reverse edge (the source's full `EntityID` is `src`). Multi only — the
|
|
182
|
+
* snapshot header guards exclusive relations out before this is reached, so
|
|
183
|
+
* the exclusive override throws defensively. */
|
|
184
|
+
abstract restoreAddTarget(index: number, tgt: EntityID, src: EntityID): void;
|
|
185
|
+
}
|
|
186
|
+
/** Build the right `RelationStore` for a cardinality. The only construction
|
|
187
|
+
* site is `Store.registerRelation`, which resolves the backing sparse store and
|
|
188
|
+
* hands it in so the relation can drive forward/membership rows directly. */
|
|
189
|
+
export declare function makeRelationStore(exclusive: boolean, sparse: SparseComponentDef, store: SparseComponentStore, onDeleteTarget: OnDeleteTarget): RelationStore;
|
|
190
|
+
/** Serialize the relation side data that does **not** live in the sparse store
|
|
191
|
+
* — i.e. each **multi** relation's forward target sets (`Map<source index,
|
|
192
|
+
* Set<target>>`). Exclusive relations store their target in the backing sparse
|
|
193
|
+
* field, so they ride `snapshotSparseStores` and contribute only a header
|
|
194
|
+
* here. The reverse index is fully derivable (from the sparse store for
|
|
195
|
+
* exclusive, from these sets for multi), so it is never serialized — it is
|
|
196
|
+
* rebuilt by `restoreRelations` + the caller's exclusive-reverse pass.
|
|
197
|
+
*
|
|
198
|
+
* Members are emitted in canonical order (sources ascending by entity index,
|
|
199
|
+
* each source's targets ascending by id) so the bytes are independent of
|
|
200
|
+
* add/remove history — the same byte-level determinism invariant the sparse
|
|
201
|
+
* snapshot holds (#470). Layout (integers little-endian):
|
|
202
|
+
*
|
|
203
|
+
* u32 relationCount
|
|
204
|
+
* repeat relationCount times (registration / id order):
|
|
205
|
+
* u32 isMulti
|
|
206
|
+
* if multi:
|
|
207
|
+
* u32 sourceCount
|
|
208
|
+
* repeat sourceCount times (ascending source index):
|
|
209
|
+
* u32 sourceIndex
|
|
210
|
+
* u32 targetCount
|
|
211
|
+
* f64 × targetCount (target EntityIDs, ascending) */
|
|
212
|
+
export declare function snapshotRelations(relations: readonly RelationStore[]): Uint8Array;
|
|
213
|
+
/** Rebuild every relation's side indices from a `snapshotRelations` buffer and
|
|
214
|
+
* the already-restored sparse stores. Each relation's indices are reset first
|
|
215
|
+
* (idempotent into a dirty world), then:
|
|
216
|
+
*
|
|
217
|
+
* - **multi** — forward target sets and their reverse edges are rebuilt from
|
|
218
|
+
* `bytes` (the sets aren't in the sparse store, so the bytes are the only
|
|
219
|
+
* source). `makeId` maps a source entity index to its full `EntityID`
|
|
220
|
+
* (generation from the live slot) so reverse edges key correctly.
|
|
221
|
+
* - **exclusive** — only the reset happens here; the reverse index is rebuilt
|
|
222
|
+
* by the caller from the backing sparse store (which already round-tripped
|
|
223
|
+
* through `restoreSparseStores`), since this function can't read it.
|
|
224
|
+
*
|
|
225
|
+
* Throws `SparseRestoreError` on any shape mismatch (relation count, an
|
|
226
|
+
* exclusive/multi flag that disagrees with the registered relation, a multi
|
|
227
|
+
* source index past `MAX_INDEX`, or a truncated / over-long buffer) rather than
|
|
228
|
+
* silently building a corrupt index. */
|
|
229
|
+
export declare function restoreRelations(relations: readonly RelationStore[], bytes: Uint8Array, makeId: (index: number) => EntityID): void;
|
|
230
|
+
export {};
|
|
231
|
+
//# sourceMappingURL=relation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relation.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/relation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/***
|
|
2
|
+
* Resource — Typed singleton key-value storage.
|
|
3
|
+
*
|
|
4
|
+
* Resources are global singletons that don't belong to any entity.
|
|
5
|
+
* Think: time, input state, camera config, game settings.
|
|
6
|
+
*
|
|
7
|
+
* Each resource is identified by a unique symbol (ResourceKey<T>) and
|
|
8
|
+
* stores an arbitrary typed value. The key carries the value type as a
|
|
9
|
+
* phantom type parameter, so reads are type-safe at compile time.
|
|
10
|
+
*
|
|
11
|
+
* Lifecycle (#798). A resource is register-once *until removed*: a second
|
|
12
|
+
* `registerResource` for a live key throws RESOURCE_ALREADY_REGISTERED, but
|
|
13
|
+
* `removeResource(key)` drops it (failing closed on a missing key) and frees the
|
|
14
|
+
* key to be registered again — the present → absent → present axis. Removal is
|
|
15
|
+
* access-checked as a *write* (a system must declare the key in `resourceWrites`),
|
|
16
|
+
* and resources stay out of `stateHash` and snapshot/resume regardless, so a
|
|
17
|
+
* lifecycle change never perturbs the determinism hash.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
*
|
|
21
|
+
* const TimeRes = resourceKey<{ delta: number; elapsed: number }>("Time");
|
|
22
|
+
* world.registerResource(TimeRes, { delta: 0, elapsed: 0 });
|
|
23
|
+
* const time = world.resource(TimeRes);
|
|
24
|
+
* // time.delta → number, time.elapsed → number
|
|
25
|
+
* world.removeResource(TimeRes); // present → absent
|
|
26
|
+
* world.registerResource(TimeRes, { delta: 0, elapsed: 0 }); // → present again
|
|
27
|
+
*
|
|
28
|
+
***/
|
|
29
|
+
export type ResourceKey<T> = symbol & {
|
|
30
|
+
readonly __phantom: T;
|
|
31
|
+
};
|
|
32
|
+
export declare function resourceKey<T>(name: string): ResourceKey<T>;
|
|
33
|
+
//# sourceMappingURL=resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2BK;AAIL,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,MAAM,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAA;CAAE,CAAC;AAEhE,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAE3D"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ArchetypeViews } from '../store';
|
|
2
|
+
/** Magic for the combined world-snapshot frame (`"WRS0"` little-endian). Distinct
|
|
3
|
+
* from the SAB `STORE_MAGIC` so a bare dense snapshot fed to `restoreInto` is
|
|
4
|
+
* rejected with a clear error instead of being mis-parsed as a combined frame. */
|
|
5
|
+
export declare const WORLD_SNAPSHOT_MAGIC = 810766935;
|
|
6
|
+
/** Combined-frame format version. Bumped if the section framing or host-state
|
|
7
|
+
* layout changes. Independent of `SIM_ABI_VERSION` (which gates the dense bytes). */
|
|
8
|
+
export declare const WORLD_SNAPSHOT_VERSION = 1;
|
|
9
|
+
/** Thrown by `Store.restoreInto` (and the helpers here) when a combined snapshot
|
|
10
|
+
* is malformed, carries the wrong magic/version, or targets a world whose
|
|
11
|
+
* archetype/component registration doesn't match the snapshot. Mirrors
|
|
12
|
+
* `StoreRestoreError` / `SparseRestoreError` so callers see one error class per
|
|
13
|
+
* restore failure mode. */
|
|
14
|
+
export declare class WorldRestoreError extends Error {
|
|
15
|
+
constructor(message: string);
|
|
16
|
+
}
|
|
17
|
+
/** Per-archetype host-side row bookkeeping the SAB doesn't carry authoritatively. */
|
|
18
|
+
export interface ArchetypeRowState {
|
|
19
|
+
readonly archetypeId: number;
|
|
20
|
+
/** Total live rows (enabled + disabled). */
|
|
21
|
+
readonly length: number;
|
|
22
|
+
/** Enabled-row partition boundary (#577): rows `[0, enabledCount)` enabled. */
|
|
23
|
+
readonly enabledCount: number;
|
|
24
|
+
}
|
|
25
|
+
/** The host-side state a snapshot captures alongside the dense + sparse bytes. */
|
|
26
|
+
export interface HostState {
|
|
27
|
+
/** World tick at snapshot time (`Store._tick`). */
|
|
28
|
+
readonly tick: number;
|
|
29
|
+
/** Entity-index high-water (count of slots ever issued). Also mirrored in the
|
|
30
|
+
* SAB region's `length` header; carried here for a cross-check on restore. */
|
|
31
|
+
readonly entityHighWater: number;
|
|
32
|
+
/** Live entity count. */
|
|
33
|
+
readonly entityAliveCount: number;
|
|
34
|
+
/** Recycle free-list in live order (LIFO: the last element is the next slot
|
|
35
|
+
* `createEntity` hands out). */
|
|
36
|
+
readonly freeIndices: readonly number[];
|
|
37
|
+
/** Per-archetype row state, one entry per SAB-backed archetype. */
|
|
38
|
+
readonly archetypeRows: readonly ArchetypeRowState[];
|
|
39
|
+
}
|
|
40
|
+
/** Serialize host-state to a self-contained little-endian byte buffer. Layout:
|
|
41
|
+
*
|
|
42
|
+
* [u32 tick][u32 highWater][u32 alive_count]
|
|
43
|
+
* [u32 freeCount][u32 free_index × freeCount]
|
|
44
|
+
* [u32 archCount][(u32 id, u32 length, u32 enabled_count) × archCount]
|
|
45
|
+
*/
|
|
46
|
+
export declare function serializeHostState(hs: HostState): Uint8Array;
|
|
47
|
+
/** Parse host-state bytes produced by `serializeHostState`. Throws
|
|
48
|
+
* `WorldRestoreError` on truncation or a trailing-byte (non-canonical) buffer. */
|
|
49
|
+
export declare function parseHostState(bytes: Uint8Array): HostState;
|
|
50
|
+
/** Assemble the combined world-snapshot frame from its three sections. Layout:
|
|
51
|
+
*
|
|
52
|
+
* [u32 magic][u32 version][u32 denseLen][u32 sparseLen][u32 hostLen]
|
|
53
|
+
* [dense][sparse][host]
|
|
54
|
+
*/
|
|
55
|
+
export declare function frameWorldSnapshot(dense: Uint8Array, sparse: Uint8Array, host: Uint8Array): Uint8Array;
|
|
56
|
+
/** The three sections of a combined frame, as zero-copy subviews over `bytes`. */
|
|
57
|
+
export interface WorldSnapshotSections {
|
|
58
|
+
readonly dense: Uint8Array;
|
|
59
|
+
readonly sparse: Uint8Array;
|
|
60
|
+
readonly host: Uint8Array;
|
|
61
|
+
}
|
|
62
|
+
/** Split a combined frame back into its sections. Validates magic, version, and
|
|
63
|
+
* an exact (no trailing bytes) frame; throws `WorldRestoreError` otherwise. */
|
|
64
|
+
export declare function unframeWorldSnapshot(bytes: Uint8Array): WorldSnapshotSections;
|
|
65
|
+
/**
|
|
66
|
+
* Fail-closed registration guard, read **directly from the snapshot's dense
|
|
67
|
+
* bytes** so it can run BEFORE the dense backing is touched. `restoreInto`
|
|
68
|
+
* builds the restored store through the live world's in-place allocator
|
|
69
|
+
* (ADR-0008), which reuses the live backing buffer — so validating a
|
|
70
|
+
* *materialised* `ColumnStore` would already have overwritten live column data
|
|
71
|
+
* (the buffer is overwritten inside `restoreColumnStore`, before any post-build
|
|
72
|
+
* check could run). Parsing the descriptors off the raw `dense` `Uint8Array`
|
|
73
|
+
* keeps the check non-mutating, so a mismatch leaves the live world untouched.
|
|
74
|
+
*
|
|
75
|
+
* Asserts: the dense section's SAB magic + ABI, that its archetype set +
|
|
76
|
+
* per-archetype `componentMask` + per-column `(componentId, fieldId, typeTag)`
|
|
77
|
+
* match the live store's exactly (so every live `Archetype.refreshViews` finds
|
|
78
|
+
* its region and no snapshot archetype is orphaned), and that the entity-index
|
|
79
|
+
* capacity matches (the region is sized once at construction). The archetype
|
|
80
|
+
* graph is rebuilt from registration code, not the snapshot (mirroring
|
|
81
|
+
* `restoreSparse`'s "registered in the same order" contract). Throws
|
|
82
|
+
* `WorldRestoreError` on any mismatch / malformed section.
|
|
83
|
+
*/
|
|
84
|
+
export declare function assertDenseLayoutMatchesLive(dense: Uint8Array, live: ReadonlyMap<number, ArchetypeViews>, liveEntityIndexCapacity: number): void;
|
|
85
|
+
//# sourceMappingURL=resume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/resume.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAUN,KAAK,cAAc,EACnB,MAAM,UAAU,CAAC;AAElB;;kFAEkF;AAClF,eAAO,MAAM,oBAAoB,YAAa,CAAC;AAE/C;qFACqF;AACrF,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC;;;;2BAI2B;AAC3B,qBAAa,iBAAkB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI3B;AAED,qFAAqF;AACrF,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC9B;AAED,kFAAkF;AAClF,MAAM,WAAW,SAAS;IACzB,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;kFAC8E;IAC9E,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,yBAAyB;IACzB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC;oCACgC;IAChC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,mEAAmE;IACnE,QAAQ,CAAC,aAAa,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACrD;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,SAAS,GAAG,UAAU,CAwB5D;AAED;kFACkF;AAClF,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAqC3D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,GACd,UAAU,CAaZ;AAED,kFAAkF;AAClF,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;CAC1B;AAED;+EAC+E;AAC/E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,qBAAqB,CAuC7E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,4BAA4B,CAC3C,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,EACzC,uBAAuB,EAAE,MAAM,GAC7B,IAAI,CAoGN"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ComponentDef } from './component';
|
|
2
|
+
import { ResourceKey } from './resource';
|
|
3
|
+
import { Query } from './query';
|
|
4
|
+
/**
|
|
5
|
+
* The read-only slice of `SystemContext` a run condition is handed. Deliberately
|
|
6
|
+
* narrow — a condition can read the ECS tick and resources, but has no path to
|
|
7
|
+
* mutate the world or read component columns directly (component reads go
|
|
8
|
+
* through a captured `Query`). `SystemContext` structurally satisfies this, so
|
|
9
|
+
* the schedule passes the live context unchanged.
|
|
10
|
+
*/
|
|
11
|
+
export interface ConditionContext {
|
|
12
|
+
/** Current ECS tick — the deterministic clock built-ins key off. */
|
|
13
|
+
readonly ecsTick: number;
|
|
14
|
+
/** Read a resource value (checked against `resourceReads` in `__DEV__`). */
|
|
15
|
+
resource<T>(key: ResourceKey<T>): T;
|
|
16
|
+
/** Membership probe for a resource — unchecked, mirrors `hasComponent`. */
|
|
17
|
+
hasResource<T>(key: ResourceKey<T>): boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A per-tick gate. `evaluate` returns `true` to run the gated system(s), `false`
|
|
21
|
+
* to skip them this tick. `reads` / `resourceReads` declare the predicate's
|
|
22
|
+
* read surface for `accessCheck` (dev) and the future parallel scheduler's
|
|
23
|
+
* read-edge graph; both are optional (absent reads as empty).
|
|
24
|
+
*/
|
|
25
|
+
export interface RunCondition {
|
|
26
|
+
/** Human-readable label, surfaced in dev access-violation diagnostics. */
|
|
27
|
+
readonly name: string;
|
|
28
|
+
/** Pure, deterministic predicate. See the two hard rules in the file header. */
|
|
29
|
+
readonly evaluate: (ctx: ConditionContext) => boolean;
|
|
30
|
+
/** Components the predicate reads (via a captured query). Forward-looking
|
|
31
|
+
* metadata — `ConditionContext` exposes no direct column read, so this is
|
|
32
|
+
* not runtime-checkable today, but it is the read-edge a parallel scheduler
|
|
33
|
+
* will consume. */
|
|
34
|
+
readonly reads?: readonly ComponentDef[];
|
|
35
|
+
/** Resources the predicate reads. Validated at runtime in `__DEV__` when the
|
|
36
|
+
* condition evaluates inside `accessCheck.enterCondition`. */
|
|
37
|
+
readonly resourceReads?: readonly ResourceKey<unknown>[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Run the gated system(s) only while a resource equals `expected` (strict `===`,
|
|
41
|
+
* so reference identity for objects). The canonical "feature flag / game phase"
|
|
42
|
+
* gate — flip `world.setResource(key, …)` and the whole group toggles.
|
|
43
|
+
*/
|
|
44
|
+
export declare function runIfResourceEq<T>(key: ResourceKey<T>, expected: T): RunCondition;
|
|
45
|
+
/**
|
|
46
|
+
* Run the gated system(s) once every `n` ticks — on ticks congruent to `offset`
|
|
47
|
+
* mod `n`. Keyed off the deterministic ECS tick, so it carries no private
|
|
48
|
+
* state and replays bit-identically. `offset` is a **phase shift taken mod `n`**
|
|
49
|
+
* (default `0` ⇒ fires on tick 0, n, 2n, …; `offset` and `offset + n` are the
|
|
50
|
+
* same phase, and a negative offset wraps), normalized once here into `[0, n)`.
|
|
51
|
+
* `n` must be a positive integer and `offset` an integer.
|
|
52
|
+
*
|
|
53
|
+
* The normalization isn't cosmetic: `(ecsTick - offset) % n` with a raw
|
|
54
|
+
* `offset ≥ n` (or negative) leans on JS's signed `%` yielding `-0` for a
|
|
55
|
+
* negative multiple (and `-0 === 0`) to stay congruent — correct, but load-
|
|
56
|
+
* bearing on a quirk. Folding `offset` into `[0, n)` up front makes the phase
|
|
57
|
+
* explicit: the per-tick dividend `ecsTick - phase` may still be negative
|
|
58
|
+
* (when `ecsTick < phase`), but with `phase ∈ [0, n)` it is never a *negative
|
|
59
|
+
* multiple* of `n` — it lands in `[-(n-1), -1]`, which holds no multiple of `n`
|
|
60
|
+
* — so `%` never produces `-0` and the check needs no signed-zero reliance.
|
|
61
|
+
*/
|
|
62
|
+
export declare function runEveryNTicks(n: number, offset?: number): RunCondition;
|
|
63
|
+
/**
|
|
64
|
+
* Run the gated system(s) only when a query matches at least one (enabled)
|
|
65
|
+
* entity — flecs `runIf` over a query. The query is captured at config time;
|
|
66
|
+
* its component defs are declared as `reads`. `count()` is a membership sum over
|
|
67
|
+
* matching archetypes (no column reads), so it trips no `accessCheck` read.
|
|
68
|
+
*
|
|
69
|
+
* The query must be **dense-only**: `count()` asserts this in `__DEV__`
|
|
70
|
+
* (`_assertDenseOnly`), so pass a plain `world.query(...)` — a query carrying
|
|
71
|
+
* `.optional(...)` or sparse terms throws. Gate on sparse membership with a
|
|
72
|
+
* custom predicate over `forEachEntity` instead.
|
|
73
|
+
*/
|
|
74
|
+
export declare function runIfAnyMatch(query: Query<readonly ComponentDef[]>): RunCondition;
|
|
75
|
+
//# sourceMappingURL=run_condition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run_condition.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/run_condition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8BK;AAEL,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACpC,2EAA2E;IAC3E,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CAC7C;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC;IACtD;;;wBAGoB;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC;mEAC+D;IAC/D,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;CACzD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,YAAY,CAMjF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,YAAY,CAclE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,YAAY,EAAE,CAAC,GAAG,YAAY,CAMjF"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { SystemContext } from './query';
|
|
2
|
+
import { SystemDescriptor } from './system';
|
|
3
|
+
import { ComputeBackend } from './compute_backend';
|
|
4
|
+
import { RunCondition } from './run_condition';
|
|
5
|
+
export declare enum SCHEDULE {
|
|
6
|
+
PRE_STARTUP = "PRE_STARTUP",
|
|
7
|
+
STARTUP = "STARTUP",
|
|
8
|
+
POST_STARTUP = "POST_STARTUP",
|
|
9
|
+
FIXED_UPDATE = "FIXED_UPDATE",
|
|
10
|
+
PRE_UPDATE = "PRE_UPDATE",
|
|
11
|
+
UPDATE = "UPDATE",
|
|
12
|
+
POST_UPDATE = "POST_UPDATE"
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* An opaque handle for a named group of systems (#576). A set carries a shared
|
|
16
|
+
* run condition and shared ordering that every member inherits. Sets are
|
|
17
|
+
* identified by **object identity**, not by name — create one with
|
|
18
|
+
* `systemSet(name)`, hold the handle, and reuse it across `addSystems`
|
|
19
|
+
* (`SystemEntry.set`) and `Schedule.configureSet`. The `name` is for
|
|
20
|
+
* diagnostics only.
|
|
21
|
+
*/
|
|
22
|
+
export interface SystemSet {
|
|
23
|
+
readonly name: string;
|
|
24
|
+
}
|
|
25
|
+
/** Create a `SystemSet` handle (#576). Two calls with the same name are two
|
|
26
|
+
* distinct sets — keep the returned handle and pass it around. */
|
|
27
|
+
export declare function systemSet(name: string): SystemSet;
|
|
28
|
+
/** A `before`/`after` ordering target: either a concrete system or a whole set
|
|
29
|
+
* (expanded to its members within the same phase at sort time). */
|
|
30
|
+
export type SystemOrderingTarget = SystemDescriptor | SystemSet;
|
|
31
|
+
/** Shared configuration applied to a `SystemSet` via `configureSet` (#576).
|
|
32
|
+
* Accumulates across calls — conditions AND together, ordering targets union. */
|
|
33
|
+
export interface SystemSetConfig {
|
|
34
|
+
/** Condition(s) every member is gated by (ANDed with each member's own). */
|
|
35
|
+
runIf?: RunCondition | readonly RunCondition[];
|
|
36
|
+
/** Every member runs before each of these targets. */
|
|
37
|
+
before?: readonly SystemOrderingTarget[];
|
|
38
|
+
/** Every member runs after each of these targets. */
|
|
39
|
+
after?: readonly SystemOrderingTarget[];
|
|
40
|
+
}
|
|
41
|
+
export interface SystemOrdering {
|
|
42
|
+
before?: readonly SystemOrderingTarget[];
|
|
43
|
+
after?: readonly SystemOrderingTarget[];
|
|
44
|
+
}
|
|
45
|
+
export interface SystemEntry {
|
|
46
|
+
system: SystemDescriptor;
|
|
47
|
+
ordering?: SystemOrdering;
|
|
48
|
+
/** Run condition(s) gating just this system — ANDed with any set conditions
|
|
49
|
+
* it inherits (#576). A `false` verdict skips the body that tick. */
|
|
50
|
+
runIf?: RunCondition | readonly RunCondition[];
|
|
51
|
+
/** Set membership — the system inherits each set's shared condition and
|
|
52
|
+
* ordering (#576). */
|
|
53
|
+
set?: SystemSet | readonly SystemSet[];
|
|
54
|
+
}
|
|
55
|
+
export declare class Schedule {
|
|
56
|
+
private readonly labelSystems;
|
|
57
|
+
private readonly sortedCache;
|
|
58
|
+
private readonly systemIndex;
|
|
59
|
+
private readonly systemLastRun;
|
|
60
|
+
private readonly gatedSystems;
|
|
61
|
+
private readonly setConditions;
|
|
62
|
+
private readonly setOrdering;
|
|
63
|
+
private nextInsertionOrder;
|
|
64
|
+
private _backend;
|
|
65
|
+
constructor();
|
|
66
|
+
addSystems(label: SCHEDULE, ...entries: (SystemDescriptor | SystemEntry)[]): void;
|
|
67
|
+
/**
|
|
68
|
+
* Configure a `SystemSet` (#576) — its shared run condition(s) and/or
|
|
69
|
+
* ordering, inherited by every member. Additive and order-independent w.r.t.
|
|
70
|
+
* `addSystems`: conditions accumulate (ANDed), ordering targets union, and
|
|
71
|
+
* a member added before or after this call picks the configuration up.
|
|
72
|
+
*/
|
|
73
|
+
configureSet(set: SystemSet, config: SystemSetConfig): void;
|
|
74
|
+
removeSystem(system: SystemDescriptor): void;
|
|
75
|
+
/** Attach (or, with `null`, detach) the opt-in compute backend (#622). Driven
|
|
76
|
+
* by `ECS.attachBackend`; routes any scheduled system carrying a
|
|
77
|
+
* `backendHandle` to `backend.run(handle)` in place of its `fn`. */
|
|
78
|
+
setBackend(backend: ComputeBackend | null): void;
|
|
79
|
+
runStartup(ctx: SystemContext, tick: number): void;
|
|
80
|
+
runUpdate(ctx: SystemContext, deltaTime: number, tick: number): void;
|
|
81
|
+
runFixedUpdate(ctx: SystemContext, fixedDt: number, tick: number): void;
|
|
82
|
+
hasFixedSystems(): boolean;
|
|
83
|
+
getAllSystems(): SystemDescriptor[];
|
|
84
|
+
hasSystem(system: SystemDescriptor): boolean;
|
|
85
|
+
clear(): void;
|
|
86
|
+
private runLabel;
|
|
87
|
+
/**
|
|
88
|
+
* Whether a gated system runs this tick — the AND of its own conditions and
|
|
89
|
+
* every set it belongs to. A set's conditions are evaluated at most once per
|
|
90
|
+
* phase (memoized in `setVerdicts`) and the verdict gates every member of the
|
|
91
|
+
* set uniformly; a `configureSet` between phases is still honored because the
|
|
92
|
+
* memo lives only for a single `runLabel` pass. Short-circuits on the first
|
|
93
|
+
* `false`. The system's own conditions evaluate per system, in canonical order.
|
|
94
|
+
*/
|
|
95
|
+
private shouldRun;
|
|
96
|
+
/** Evaluate a condition list with AND semantics. Each predicate runs inside a
|
|
97
|
+
* reads-only `accessCheck` span (dev), so a condition that reads an
|
|
98
|
+
* undeclared resource — or attempts any mutation — throws. */
|
|
99
|
+
private evalConditions;
|
|
100
|
+
private getSorted;
|
|
101
|
+
/**
|
|
102
|
+
* Delegates to the shared topologicalSort utility.
|
|
103
|
+
* Builds the dependency edge map from before/after constraints, then
|
|
104
|
+
* catches any cycle TypeError and re-throws as ECSError.
|
|
105
|
+
*/
|
|
106
|
+
private sortSystems;
|
|
107
|
+
/**
|
|
108
|
+
* Add the topo edges for one ordering list (#576). For `"before"` the source
|
|
109
|
+
* runs before each target (edge source→target); for `"after"` it runs after
|
|
110
|
+
* each target (edge target→source). A `SystemSet` target expands to every
|
|
111
|
+
* member within this phase (self-edges skipped, so a member ordered against
|
|
112
|
+
* its own set is a no-op); a descriptor target absent from this phase is
|
|
113
|
+
* dropped — with a dev warning only for a concrete system, since a set
|
|
114
|
+
* legitimately expands to nothing when its members live in another phase.
|
|
115
|
+
*/
|
|
116
|
+
private resolveEdges;
|
|
117
|
+
/** Push one directed edge into the adjacency map. Both endpoints are known to
|
|
118
|
+
* be in this phase (callers guard), so `edges.get(...)` is non-null. */
|
|
119
|
+
private addDirectedEdge;
|
|
120
|
+
/**
|
|
121
|
+
* Dev-only diagnostic for an ordering edge that was dropped during sort.
|
|
122
|
+
*
|
|
123
|
+
* Cross-label ordering is impossible by design (`nodeSet` is per-label), so
|
|
124
|
+
* a target registered in *another* phase is skipped silently — that's the
|
|
125
|
+
* intended isolation. But a target unknown to *every* phase is almost
|
|
126
|
+
* certainly a typo or a system that was never scheduled; without this warning
|
|
127
|
+
* the constraint vanishes and the system runs in insertion-order tiebreak as
|
|
128
|
+
* if unconstrained, with nothing to distinguish mistake from intent. Compiled
|
|
129
|
+
* out of production builds by the `__DEV__` guards at the call sites.
|
|
130
|
+
*/
|
|
131
|
+
private warnDroppedEdge;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=schedule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/schedule.ts"],"names":[],"mappings":"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"}
|