@oasys/oecs 0.3.1 → 0.5.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/CHANGELOG.md +553 -0
- package/README.md +207 -267
- package/dist/core/ecs/access_check.d.cts +77 -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.cts +486 -0
- package/dist/core/ecs/archetype.d.ts +486 -0
- package/dist/core/ecs/archetype.d.ts.map +1 -0
- 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 +43 -0
- package/dist/core/ecs/builtin_relations.d.ts.map +1 -0
- package/dist/core/ecs/command_log.d.cts +116 -0
- package/dist/core/ecs/command_log.d.ts +116 -0
- package/dist/core/ecs/command_log.d.ts.map +1 -0
- package/dist/core/ecs/component.d.cts +176 -0
- package/dist/core/ecs/component.d.ts +176 -0
- package/dist/core/ecs/component.d.ts.map +1 -0
- package/dist/core/ecs/compute_backend.d.cts +37 -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/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 +93 -0
- package/dist/core/ecs/dispatch_trace.d.ts.map +1 -0
- package/dist/core/ecs/ecs.d.cts +562 -0
- package/dist/core/ecs/ecs.d.ts +562 -0
- package/dist/core/ecs/ecs.d.ts.map +1 -0
- package/dist/core/ecs/ecs_memory.d.cts +179 -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.cts +34 -0
- package/dist/core/ecs/entity.d.ts +34 -0
- package/dist/core/ecs/entity.d.ts.map +1 -0
- 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 +79 -0
- package/dist/core/ecs/event.d.ts.map +1 -0
- 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 +133 -0
- package/dist/core/ecs/frame_trace.d.ts.map +1 -0
- package/dist/core/ecs/host_commands.d.cts +274 -0
- package/dist/core/ecs/host_commands.d.ts +274 -0
- package/dist/core/ecs/host_commands.d.ts.map +1 -0
- package/dist/core/ecs/index.d.cts +46 -0
- package/dist/core/ecs/index.d.ts +46 -0
- package/dist/core/ecs/index.d.ts.map +1 -0
- package/dist/core/ecs/observer.d.cts +173 -0
- package/dist/core/ecs/observer.d.ts +173 -0
- package/dist/core/ecs/observer.d.ts.map +1 -0
- package/dist/core/ecs/query.d.cts +718 -0
- package/dist/core/ecs/query.d.ts +718 -0
- package/dist/core/ecs/query.d.ts.map +1 -0
- package/dist/core/ecs/ref.d.cts +31 -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.cts +243 -0
- package/dist/core/ecs/relation.d.ts +243 -0
- package/dist/core/ecs/relation.d.ts.map +1 -0
- 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 +53 -0
- package/dist/core/ecs/resource.d.ts.map +1 -0
- 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 +85 -0
- package/dist/core/ecs/resume.d.ts.map +1 -0
- package/dist/core/ecs/run_condition.d.cts +81 -0
- package/dist/core/ecs/run_condition.d.ts +81 -0
- package/dist/core/ecs/run_condition.d.ts.map +1 -0
- package/dist/core/ecs/schedule.d.cts +142 -0
- package/dist/core/ecs/schedule.d.ts +142 -0
- package/dist/core/ecs/schedule.d.ts.map +1 -0
- 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 +110 -0
- package/dist/core/ecs/sparse_store.d.ts.map +1 -0
- package/dist/core/ecs/store.d.cts +950 -0
- package/dist/core/ecs/store.d.ts +950 -0
- package/dist/core/ecs/store.d.ts.map +1 -0
- package/dist/core/ecs/store_layout_listener.d.cts +23 -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.cts +250 -0
- package/dist/core/ecs/system.d.ts +250 -0
- package/dist/core/ecs/system.d.ts.map +1 -0
- package/dist/core/ecs/utils/arrays.d.cts +7 -0
- package/dist/{utils → core/ecs/utils}/arrays.d.ts +2 -1
- 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.cts +61 -0
- package/dist/core/ecs/utils/error.d.ts +61 -0
- package/dist/core/ecs/utils/error.d.ts.map +1 -0
- package/dist/core/store/action_ring.d.cts +136 -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.cts +238 -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.cts +69 -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.cts +273 -0
- package/dist/core/store/column_store.d.ts +273 -0
- package/dist/core/store/column_store.d.ts.map +1 -0
- package/dist/core/store/command_dispatch.d.cts +52 -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.cts +107 -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.cts +80 -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.cts +108 -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.cts +95 -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.cts +39 -0
- package/dist/core/store/extend.d.ts +39 -0
- package/dist/core/store/extend.d.ts.map +1 -0
- package/dist/core/store/grow.d.cts +34 -0
- package/dist/core/store/grow.d.ts +34 -0
- package/dist/core/store/grow.d.ts.map +1 -0
- package/dist/core/store/header.d.cts +64 -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.cts +17 -0
- package/dist/core/store/index.d.ts +17 -0
- package/dist/core/store/index.d.ts.map +1 -0
- 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 +74 -0
- package/dist/core/store/region_table.d.ts.map +1 -0
- package/dist/core/store/snapshot.d.cts +43 -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.cts +38 -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.cts +38 -0
- package/dist/core/store/store_regions.d.ts +38 -0
- package/dist/core/store/store_regions.d.ts.map +1 -0
- package/dist/core/store/vendored_abi/abi.d.cts +43 -0
- package/dist/core/store/vendored_abi/abi.d.ts +43 -0
- package/dist/core/store/vendored_abi/abi.d.ts.map +1 -0
- package/dist/dev_flag.d.cts +17 -0
- package/dist/dev_flag.d.ts +17 -0
- package/dist/dev_flag.d.ts.map +1 -0
- package/dist/extensions/editor/editor.d.cts +170 -0
- package/dist/extensions/editor/editor.d.ts +170 -0
- package/dist/extensions/editor/editor.d.ts.map +1 -0
- package/dist/extensions/editor/field_handle.d.cts +40 -0
- package/dist/extensions/editor/field_handle.d.ts +40 -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.cts +21 -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 +237 -0
- package/dist/extensions/reactive/ecs_sync.d.cts +214 -0
- package/dist/extensions/reactive/ecs_sync.d.ts +214 -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.cts +23 -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 +215 -0
- package/dist/extensions/solid/index.cjs +1 -0
- package/dist/extensions/solid/index.d.cts +6 -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 +36 -0
- package/dist/extensions/solid/kernel_solid.d.cts +45 -0
- package/dist/extensions/solid/kernel_solid.d.ts +45 -0
- package/dist/extensions/solid/kernel_solid.d.ts.map +1 -0
- package/dist/host_commands-BF8QMi3c.cjs +1 -0
- package/dist/host_commands-i4cAeyL5.js +2318 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +66 -0
- package/dist/index.d.ts +65 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7080 -1289
- 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/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/primitives.cjs +1 -0
- package/dist/primitives.d.cts +18 -0
- package/dist/primitives.d.ts +18 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +45 -0
- package/dist/reactive/array.d.cts +24 -0
- 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/reactive/interop.d.ts +19 -0
- package/dist/reactive/interop.d.ts.map +1 -0
- package/dist/reactive/kernel.d.cts +73 -0
- package/dist/reactive/kernel.d.ts +73 -0
- package/dist/reactive/kernel.d.ts.map +1 -0
- package/dist/reactive/map.d.cts +16 -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/reactive/struct.d.ts +10 -0
- 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 -0
- package/dist/shared.d.cts +22 -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-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 +25 -9
- 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/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.cts +54 -0
- 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.cts +23 -0
- 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.cts +16 -0
- package/dist/type_primitives/error.d.ts +8 -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 +12 -9
- package/dist/type_primitives/index.d.ts.map +1 -1
- package/dist/type_primitives/sparse_map/sparse_map.d.cts +30 -0
- 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.cts +28 -0
- 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.cts +29 -0
- 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.cts +127 -0
- 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/typed_arrays-BcXcnzB4.js +258 -0
- package/dist/typed_arrays-D3NmwtCG.cjs +1 -0
- package/dist/utils/error.d.cts +6 -0
- package/dist/utils/error.d.ts +2 -20
- package/dist/utils/error.d.ts.map +1 -1
- 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 +115 -5
- 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
- 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
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Brand } from '../../type_primitives/index.js';
|
|
2
|
+
export type EventID = Brand<number, "event_id">;
|
|
3
|
+
export declare const asEventId: (value: number) => EventID;
|
|
4
|
+
/** Event schema: field name → value type. Every value is a number at
|
|
5
|
+
* runtime; the declared type may be a branded number (e.g. `EntityID`)
|
|
6
|
+
* so the brand survives the emit → read round trip at the type layer.
|
|
7
|
+
* This is the erased/default schema type; the public surfaces constrain
|
|
8
|
+
* on `EventShape<S>` (below) instead, so schemas may be declared as type
|
|
9
|
+
* literals OR interfaces — an interface lacks the implicit index
|
|
10
|
+
* signature literals get (and so isn't assignable to this `Record`
|
|
11
|
+
* alias), but satisfies the homomorphic `EventShape` check. */
|
|
12
|
+
export type EventSchema = Readonly<Record<string, number>>;
|
|
13
|
+
/**
|
|
14
|
+
* Homomorphic constraint for event-schema type params (POLISH_AUDIT M9):
|
|
15
|
+
* `S extends EventShape<S>` checks every property of `S` is a number WITHOUT
|
|
16
|
+
* requiring an index signature, so `interface`-declared schemas (which lack
|
|
17
|
+
* the implicit index signature type literals get) are accepted too.
|
|
18
|
+
*/
|
|
19
|
+
export type EventShape<S> = {
|
|
20
|
+
readonly [K in keyof S]: number;
|
|
21
|
+
};
|
|
22
|
+
/** Schema of a signal — a zero-field event. */
|
|
23
|
+
export type EmptyEventSchema = Readonly<Record<never, number>>;
|
|
24
|
+
declare const __eventSchema: unique symbol;
|
|
25
|
+
export type EventDef<S extends EventShape<S> = EventSchema> = EventID & {
|
|
26
|
+
readonly [__eventSchema]: (value: S) => S;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Reader view over an event channel's SoA columns. Columns are read-only
|
|
30
|
+
* arrays typed per the event schema: consumers index them and read
|
|
31
|
+
* `.length`. A field declared as a branded number (e.g. `EntityID`) reads
|
|
32
|
+
* back branded — no cast at the consumer.
|
|
33
|
+
*
|
|
34
|
+
* The "cannot mutate the live channel through the reader" property is
|
|
35
|
+
* **advisory** — the columns are the same live `number[]` objects the channel
|
|
36
|
+
* mutates (see `EventChannel` below), so the `readonly` typing blocks writes
|
|
37
|
+
* at the type layer only; a §10c-policed cast can still write through.
|
|
38
|
+
*/
|
|
39
|
+
export type EventReader<S extends EventShape<S>> = {
|
|
40
|
+
readonly length: number;
|
|
41
|
+
} & {
|
|
42
|
+
readonly [K in keyof S]: ReadonlyArray<S[K]>;
|
|
43
|
+
};
|
|
44
|
+
export declare class EventChannel {
|
|
45
|
+
readonly fieldNames: string[];
|
|
46
|
+
readonly columns: number[][];
|
|
47
|
+
readonly reader: EventReader<any>;
|
|
48
|
+
private readonly _readerLen;
|
|
49
|
+
constructor(fieldNames: string[]);
|
|
50
|
+
emit(values: Record<string, number>): void;
|
|
51
|
+
/** Emit a signal (zero-field event). */
|
|
52
|
+
emitSignal(): void;
|
|
53
|
+
clear(): void;
|
|
54
|
+
}
|
|
55
|
+
declare const __eventKeySchema: unique symbol;
|
|
56
|
+
export type EventKey<S extends EventShape<S> = EventSchema> = symbol & {
|
|
57
|
+
readonly [__eventKeySchema]: (value: S) => S;
|
|
58
|
+
};
|
|
59
|
+
declare const __signalKey: unique symbol;
|
|
60
|
+
export type SignalKey = EventKey<EmptyEventSchema> & {
|
|
61
|
+
readonly [__signalKey]: true;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Compile-time exact-cover check for `registerEvent`'s `fields` list. The
|
|
65
|
+
* element type (`keyof S & string`) already rejects foreign fields; this
|
|
66
|
+
* catches the inverse mistake — an UNDER-registered channel. Registering
|
|
67
|
+
* `eventKey<{a; b}>` with `["a"]` used to compile, but `emit` requires the
|
|
68
|
+
* full payload while the channel only has an `a` column, so `b` was silently
|
|
69
|
+
* dropped and `reader.b` (typed as an array) was `undefined` at runtime.
|
|
70
|
+
* Resolves to `unknown` (intersection no-op) when `F` covers every key, and
|
|
71
|
+
* to an impossible tuple naming the missing fields otherwise. A schema with a
|
|
72
|
+
* string index signature (erased/untyped keys) skips the check — there is no
|
|
73
|
+
* finite key set to cover.
|
|
74
|
+
*/
|
|
75
|
+
export type EventFieldsCover<S extends EventShape<S>, F extends readonly (keyof S & string)[]> = string extends keyof S ? unknown : Exclude<keyof S & string, F[number]> extends never ? unknown : readonly [`ERROR — missing event field: ${Exclude<keyof S & string, F[number]>}`];
|
|
76
|
+
export declare function eventKey<S extends EventShape<S>>(name: string): EventKey<S>;
|
|
77
|
+
export declare function signalKey(name: string): SignalKey;
|
|
78
|
+
export {};
|
|
79
|
+
//# sourceMappingURL=event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/event.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { EmptyEventSchema, EventDef, EventReader, EventShape } from './event.cjs';
|
|
2
|
+
export declare class EventRegistry {
|
|
3
|
+
private readonly channels;
|
|
4
|
+
private readonly dirtyChannels;
|
|
5
|
+
private count;
|
|
6
|
+
private readonly keyMap;
|
|
7
|
+
registerEvent<S extends EventShape<S>>(fields: readonly (keyof S & string)[]): EventDef<S>;
|
|
8
|
+
emitEvent(def: EventDef<any>, values: Record<string, number>): void;
|
|
9
|
+
emitSignal(def: EventDef<EmptyEventSchema>): void;
|
|
10
|
+
getEventReader<S extends EventShape<S>>(def: EventDef<S>): EventReader<S>;
|
|
11
|
+
clearEvents(): void;
|
|
12
|
+
/** `DEV`-only: total events currently buffered across the dirty channels.
|
|
13
|
+
* `ECS.update` samples this either side of `dispatchSet` to assert an onSet
|
|
14
|
+
* observer emitted nothing — its emissions would be wiped by the tick-tail
|
|
15
|
+
* `clearEvents` and break the empty-channel-at-boundary invariant snapshot /
|
|
16
|
+
* restore relies on (#586). Walks only the dirty list, never the hot emit path. */
|
|
17
|
+
devBufferedEventCount(): number;
|
|
18
|
+
registerEventByKey<S extends EventShape<S>>(key: symbol, fields: readonly (keyof S & string)[]): EventDef<S>;
|
|
19
|
+
getEventDefByKey(key: symbol): EventDef<any>;
|
|
20
|
+
hasEventKey(key: symbol): boolean;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=event_registry.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { EmptyEventSchema, EventDef, EventReader, EventShape } from './event.js';
|
|
2
|
+
export declare class EventRegistry {
|
|
3
|
+
private readonly channels;
|
|
4
|
+
private readonly dirtyChannels;
|
|
5
|
+
private count;
|
|
6
|
+
private readonly keyMap;
|
|
7
|
+
registerEvent<S extends EventShape<S>>(fields: readonly (keyof S & string)[]): EventDef<S>;
|
|
8
|
+
emitEvent(def: EventDef<any>, values: Record<string, number>): void;
|
|
9
|
+
emitSignal(def: EventDef<EmptyEventSchema>): void;
|
|
10
|
+
getEventReader<S extends EventShape<S>>(def: EventDef<S>): EventReader<S>;
|
|
11
|
+
clearEvents(): void;
|
|
12
|
+
/** `DEV`-only: total events currently buffered across the dirty channels.
|
|
13
|
+
* `ECS.update` samples this either side of `dispatchSet` to assert an onSet
|
|
14
|
+
* observer emitted nothing — its emissions would be wiped by the tick-tail
|
|
15
|
+
* `clearEvents` and break the empty-channel-at-boundary invariant snapshot /
|
|
16
|
+
* restore relies on (#586). Walks only the dirty list, never the hot emit path. */
|
|
17
|
+
devBufferedEventCount(): number;
|
|
18
|
+
registerEventByKey<S extends EventShape<S>>(key: symbol, fields: readonly (keyof S & string)[]): EventDef<S>;
|
|
19
|
+
getEventDefByKey(key: symbol): EventDef<any>;
|
|
20
|
+
hasEventKey(key: symbol): boolean;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=event_registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event_registry.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/event_registry.ts"],"names":[],"mappings":"AAAA;;;;;;;KAOK;AAGL,OAAO,EAGN,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,MAAM,SAAS,CAAC;AAGjB,qBAAa,aAAa;IAEzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAK/C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,KAAK,CAAK;IAIlB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAEzD,aAAa,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAC3C,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,GACnC,QAAQ,CAAC,CAAC,CAAC;IAOP,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAYnE,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAQjD,cAAc,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;IAIzE,WAAW,IAAI,IAAI;IAS1B;;;;uFAImF;IAC5E,qBAAqB,IAAI,MAAM;IAQ/B,kBAAkB,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAChD,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,GACnC,QAAQ,CAAC,CAAC,CAAC;IAcP,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC;IAY5C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAGxC"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { Store } from './store.cjs';
|
|
2
|
+
import { EntityID } from './entity.cjs';
|
|
3
|
+
import { OnDeleteTarget, RelationDef, RelationOptions } from './relation.cjs';
|
|
4
|
+
import { ResourceKey } from './resource.cjs';
|
|
5
|
+
import { EventFieldsCover, EventKey, EventReader, EventShape, SignalKey } from './event.cjs';
|
|
6
|
+
/** Relations — sparse `(relation, target)` pairs and hierarchy traversal
|
|
7
|
+
* (#471 / #474, ADR-0011). Add/remove/re-target cause no archetype
|
|
8
|
+
* transition; ops are immediate and safe mid-tick. Traversal and wildcard
|
|
9
|
+
* reads are cold-path. */
|
|
10
|
+
export declare class ECSRelations {
|
|
11
|
+
private readonly store;
|
|
12
|
+
/** @internal constructed by `ECS`. */
|
|
13
|
+
constructor(store: Store);
|
|
14
|
+
/** Register a relation kind. Exclusive (default) stores one target per
|
|
15
|
+
* source; `{ multi: true }` stores a target set per source.
|
|
16
|
+
* `{ onDeleteTarget: "delete" | "clear" | "orphan" }` selects target-death
|
|
17
|
+
* cleanup (default `orphan`, #473).
|
|
18
|
+
*
|
|
19
|
+
* The overloads stamp the CARDINALITY into the handle type (typestate
|
|
20
|
+
* a173382 / POLISH_AUDIT #7), exactly like the flat `registerRelation`:
|
|
21
|
+
* the exclusive-only surfaces (`targetOf`, `ancestorsOf`/`rootOf`/
|
|
22
|
+
* `cascadeOf`, `Query.hierarchy`) accept only `RelationDef<"exclusive">`,
|
|
23
|
+
* so passing a `{ multi: true }` relation is a compile error. A
|
|
24
|
+
* dynamically-built options value falls to the erased overload and keeps
|
|
25
|
+
* the runtime check as its only guard. */
|
|
26
|
+
register(opts?: {
|
|
27
|
+
readonly exclusive?: true;
|
|
28
|
+
readonly multi?: false;
|
|
29
|
+
readonly onDeleteTarget?: OnDeleteTarget;
|
|
30
|
+
}): RelationDef<"exclusive">;
|
|
31
|
+
register(opts: {
|
|
32
|
+
readonly multi: true;
|
|
33
|
+
readonly exclusive?: false;
|
|
34
|
+
readonly onDeleteTarget?: OnDeleteTarget;
|
|
35
|
+
}): RelationDef<"multi">;
|
|
36
|
+
register(opts?: RelationOptions): RelationDef;
|
|
37
|
+
/** Count of registered relations. */
|
|
38
|
+
get count(): number;
|
|
39
|
+
/** Add a `(R, tgt)` pair to `src`. Exclusive replaces the existing target;
|
|
40
|
+
* multi adds to the set. No archetype transition. */
|
|
41
|
+
add(src: EntityID, def: RelationDef, tgt: EntityID): this;
|
|
42
|
+
/** Remove a `(R, tgt)` pair from `src`. For multi, omitting `tgt` removes
|
|
43
|
+
* all of `src`'s targets. No archetype transition. */
|
|
44
|
+
remove(src: EntityID, def: RelationDef, tgt?: EntityID): this;
|
|
45
|
+
/** Whether `src` holds any pair under `R`. */
|
|
46
|
+
has(src: EntityID, def: RelationDef): boolean;
|
|
47
|
+
/** The single target of `src` under an exclusive relation, or `undefined`. */
|
|
48
|
+
targetOf(src: EntityID, def: RelationDef<"exclusive">): EntityID | undefined;
|
|
49
|
+
/** All targets of `src` under `R`, ascending by id. */
|
|
50
|
+
targetsOf(src: EntityID, def: RelationDef): EntityID[];
|
|
51
|
+
/** Sources pointing at `tgt` under `R` (the reverse index), ascending by id.
|
|
52
|
+
* `(entity, def)` order, matching `targetOf` / `targetsOf`. */
|
|
53
|
+
sourcesOf(tgt: EntityID, def: RelationDef): EntityID[];
|
|
54
|
+
/** All `(source, target)` pairs of relation `R` — the `(R, *)` wildcard
|
|
55
|
+
* (#472). Sources in canonical entity-index order. Cold path. */
|
|
56
|
+
pairsOf(def: RelationDef): readonly (readonly [EntityID, EntityID])[];
|
|
57
|
+
/** Every `(relation, source)` pointing at `tgt`, across all relation kinds —
|
|
58
|
+
* the `(*, T)` wildcard (#472). Ordered by relation id then source id. */
|
|
59
|
+
sourcesOfAny(tgt: EntityID): readonly (readonly [RelationDef, EntityID])[];
|
|
60
|
+
/** Walk relation `R` up from `src` to its chain root, returning
|
|
61
|
+
* `[src, parent, …, root]` (nearest-ancestor-first). Exclusive only. */
|
|
62
|
+
ancestorsOf(src: EntityID, def: RelationDef<"exclusive">): EntityID[];
|
|
63
|
+
/** The root of `src`'s `R`-chain (`src` itself when it has no target).
|
|
64
|
+
* Exclusive only. */
|
|
65
|
+
rootOf(src: EntityID, def: RelationDef<"exclusive">): EntityID;
|
|
66
|
+
/** Walk relation `R` down from `root` over the reverse index, returning the
|
|
67
|
+
* subtree (including `root`) breadth-first — parents before children (the
|
|
68
|
+
* `cascade` order). Exclusive only. */
|
|
69
|
+
cascadeOf(root: EntityID, def: RelationDef<"exclusive">): EntityID[];
|
|
70
|
+
/** Reclaim relation reverse-index memory: drop every reverse entry whose
|
|
71
|
+
* target has been destroyed, returning the total dropped (#491). Purely
|
|
72
|
+
* cold-path, no observable state change — call at scene/snapshot
|
|
73
|
+
* boundaries. */
|
|
74
|
+
compact(): number;
|
|
75
|
+
}
|
|
76
|
+
/** Event channels and signals. Emit during one `update()`, visible to every
|
|
77
|
+
* later system in that call, cleared before the next. System-side reads and
|
|
78
|
+
* emits go through `ctx` — this facade is the HOST-side surface. */
|
|
79
|
+
export declare class ECSEvents {
|
|
80
|
+
private readonly store;
|
|
81
|
+
/** @internal constructed by `ECS`. */
|
|
82
|
+
constructor(store: Store);
|
|
83
|
+
/** Register an event channel at world setup, before anything emits on it.
|
|
84
|
+
* `fields` must name EVERY schema key — an under-registered channel would
|
|
85
|
+
* silently drop the missing fields at emit (see `EventFieldsCover`).
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const Damaged = eventKey<{ target: EntityID; amount: number }>("Damaged");
|
|
89
|
+
* ecs.events.register(Damaged, ["target", "amount"]);
|
|
90
|
+
* ecs.events.emit(Damaged, { target: e, amount: 10 }); // or ctx.emit inside a system
|
|
91
|
+
*/
|
|
92
|
+
register<S extends EventShape<S>, const F extends readonly (keyof S & string)[]>(key: EventKey<S>, fields: F & EventFieldsCover<S, F>): void;
|
|
93
|
+
/** Register a signal (empty-payload event channel). */
|
|
94
|
+
registerSignal(key: SignalKey): void;
|
|
95
|
+
emit(key: SignalKey): void;
|
|
96
|
+
emit<S extends EventShape<S>>(key: EventKey<S>, values: NoInfer<S>): void;
|
|
97
|
+
read<S extends EventShape<S>>(key: EventKey<S>): EventReader<S>;
|
|
98
|
+
}
|
|
99
|
+
/** World resources — singleton values keyed by `ResourceKey<T>`. Runtime
|
|
100
|
+
* mutations (`set` / `remove`) are access-checked as resource writes inside
|
|
101
|
+
* a system span; `register` is a one-time world-setup op. */
|
|
102
|
+
export declare class ECSResources {
|
|
103
|
+
private readonly store;
|
|
104
|
+
/** @internal constructed by `ECS`. */
|
|
105
|
+
constructor(store: Store);
|
|
106
|
+
/** Register a resource at world setup. Reading/writing an unregistered
|
|
107
|
+
* key throws (fail-closed) — registration is the explicit "this world has
|
|
108
|
+
* this singleton" declaration, not a lazy default.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* const GameTime = resourceKey<{ elapsed: number }>("GameTime");
|
|
112
|
+
* ecs.resources.register(GameTime, { elapsed: 0 });
|
|
113
|
+
* ecs.resources.get(GameTime).elapsed; // or ctx.resource(GameTime) inside a system
|
|
114
|
+
*/
|
|
115
|
+
register<T>(key: ResourceKey<T>, value: NoInfer<T>): void;
|
|
116
|
+
get<T>(key: ResourceKey<T>): T;
|
|
117
|
+
set<T>(key: ResourceKey<T>, value: NoInfer<T>): void;
|
|
118
|
+
/** Drop a resource from the world (#798). Access-checked as a *write*;
|
|
119
|
+
* fails closed on a missing key. Afterwards the key is free to `register`
|
|
120
|
+
* again — the present → absent → present lifecycle. */
|
|
121
|
+
remove<T>(key: ResourceKey<T>): void;
|
|
122
|
+
has<T>(key: ResourceKey<T>): boolean;
|
|
123
|
+
}
|
|
124
|
+
/** The determinism surface (#626 / ADR-0020): world snapshot/resume and the
|
|
125
|
+
* canonical state digest. Every member except `deterministic` throws
|
|
126
|
+
* `DETERMINISM_DISABLED` unless the world was constructed with
|
|
127
|
+
* `{ deterministic: true }`. All cold-path — take captures at tick
|
|
128
|
+
* boundaries (between `update()`s). */
|
|
129
|
+
export declare class ECSSnapshots {
|
|
130
|
+
private readonly store;
|
|
131
|
+
/** @internal constructed by `ECS`. */
|
|
132
|
+
constructor(store: Store);
|
|
133
|
+
/** Whether the determinism surface is enabled. */
|
|
134
|
+
get deterministic(): boolean;
|
|
135
|
+
/** FNV-1a 32 digest over every archetype's live rows in id order — the
|
|
136
|
+
* canonical "live ECS state digest". Per-call cost scales with live
|
|
137
|
+
* entity count, not SAB capacity. */
|
|
138
|
+
stateHash(): number;
|
|
139
|
+
/** Capture the full live world (dense + sparse/relations + host-side
|
|
140
|
+
* bookkeeping) to one self-contained byte buffer that `restore` can mount
|
|
141
|
+
* back onto a live, ticking world (#789). v1 does NOT capture resources,
|
|
142
|
+
* events, or change-detection baselines (ADR-0031). */
|
|
143
|
+
capture(): Uint8Array;
|
|
144
|
+
/** Mount a `capture()` buffer onto this live world and keep ticking.
|
|
145
|
+
* Fails closed on a malformed frame or registration mismatch BEFORE
|
|
146
|
+
* mutating any live state. Requires a matching archetype set + column
|
|
147
|
+
* layout (prewarm so the set is stable). */
|
|
148
|
+
restore(bytes: Uint8Array): void;
|
|
149
|
+
/** Serialize the sparse stores + relations to a self-contained buffer —
|
|
150
|
+
* the sparse half of a world snapshot, canonical entity-index order
|
|
151
|
+
* (#470). Pairs with `restoreSparse`. */
|
|
152
|
+
captureSparse(): Uint8Array;
|
|
153
|
+
/** Repopulate the sparse stores + relation indices from `captureSparse`
|
|
154
|
+
* bytes. Sparse components must already be registered in the same order;
|
|
155
|
+
* throws `SparseRestoreError` on a shape or identity mismatch. */
|
|
156
|
+
restoreSparse(bytes: Uint8Array): void;
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=facades.d.ts.map
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { Store } from './store.js';
|
|
2
|
+
import { EntityID } from './entity.js';
|
|
3
|
+
import { OnDeleteTarget, RelationDef, RelationOptions } from './relation.js';
|
|
4
|
+
import { ResourceKey } from './resource.js';
|
|
5
|
+
import { EventFieldsCover, EventKey, EventReader, EventShape, SignalKey } from './event.js';
|
|
6
|
+
/** Relations — sparse `(relation, target)` pairs and hierarchy traversal
|
|
7
|
+
* (#471 / #474, ADR-0011). Add/remove/re-target cause no archetype
|
|
8
|
+
* transition; ops are immediate and safe mid-tick. Traversal and wildcard
|
|
9
|
+
* reads are cold-path. */
|
|
10
|
+
export declare class ECSRelations {
|
|
11
|
+
private readonly store;
|
|
12
|
+
/** @internal constructed by `ECS`. */
|
|
13
|
+
constructor(store: Store);
|
|
14
|
+
/** Register a relation kind. Exclusive (default) stores one target per
|
|
15
|
+
* source; `{ multi: true }` stores a target set per source.
|
|
16
|
+
* `{ onDeleteTarget: "delete" | "clear" | "orphan" }` selects target-death
|
|
17
|
+
* cleanup (default `orphan`, #473).
|
|
18
|
+
*
|
|
19
|
+
* The overloads stamp the CARDINALITY into the handle type (typestate
|
|
20
|
+
* a173382 / POLISH_AUDIT #7), exactly like the flat `registerRelation`:
|
|
21
|
+
* the exclusive-only surfaces (`targetOf`, `ancestorsOf`/`rootOf`/
|
|
22
|
+
* `cascadeOf`, `Query.hierarchy`) accept only `RelationDef<"exclusive">`,
|
|
23
|
+
* so passing a `{ multi: true }` relation is a compile error. A
|
|
24
|
+
* dynamically-built options value falls to the erased overload and keeps
|
|
25
|
+
* the runtime check as its only guard. */
|
|
26
|
+
register(opts?: {
|
|
27
|
+
readonly exclusive?: true;
|
|
28
|
+
readonly multi?: false;
|
|
29
|
+
readonly onDeleteTarget?: OnDeleteTarget;
|
|
30
|
+
}): RelationDef<"exclusive">;
|
|
31
|
+
register(opts: {
|
|
32
|
+
readonly multi: true;
|
|
33
|
+
readonly exclusive?: false;
|
|
34
|
+
readonly onDeleteTarget?: OnDeleteTarget;
|
|
35
|
+
}): RelationDef<"multi">;
|
|
36
|
+
register(opts?: RelationOptions): RelationDef;
|
|
37
|
+
/** Count of registered relations. */
|
|
38
|
+
get count(): number;
|
|
39
|
+
/** Add a `(R, tgt)` pair to `src`. Exclusive replaces the existing target;
|
|
40
|
+
* multi adds to the set. No archetype transition. */
|
|
41
|
+
add(src: EntityID, def: RelationDef, tgt: EntityID): this;
|
|
42
|
+
/** Remove a `(R, tgt)` pair from `src`. For multi, omitting `tgt` removes
|
|
43
|
+
* all of `src`'s targets. No archetype transition. */
|
|
44
|
+
remove(src: EntityID, def: RelationDef, tgt?: EntityID): this;
|
|
45
|
+
/** Whether `src` holds any pair under `R`. */
|
|
46
|
+
has(src: EntityID, def: RelationDef): boolean;
|
|
47
|
+
/** The single target of `src` under an exclusive relation, or `undefined`. */
|
|
48
|
+
targetOf(src: EntityID, def: RelationDef<"exclusive">): EntityID | undefined;
|
|
49
|
+
/** All targets of `src` under `R`, ascending by id. */
|
|
50
|
+
targetsOf(src: EntityID, def: RelationDef): EntityID[];
|
|
51
|
+
/** Sources pointing at `tgt` under `R` (the reverse index), ascending by id.
|
|
52
|
+
* `(entity, def)` order, matching `targetOf` / `targetsOf`. */
|
|
53
|
+
sourcesOf(tgt: EntityID, def: RelationDef): EntityID[];
|
|
54
|
+
/** All `(source, target)` pairs of relation `R` — the `(R, *)` wildcard
|
|
55
|
+
* (#472). Sources in canonical entity-index order. Cold path. */
|
|
56
|
+
pairsOf(def: RelationDef): readonly (readonly [EntityID, EntityID])[];
|
|
57
|
+
/** Every `(relation, source)` pointing at `tgt`, across all relation kinds —
|
|
58
|
+
* the `(*, T)` wildcard (#472). Ordered by relation id then source id. */
|
|
59
|
+
sourcesOfAny(tgt: EntityID): readonly (readonly [RelationDef, EntityID])[];
|
|
60
|
+
/** Walk relation `R` up from `src` to its chain root, returning
|
|
61
|
+
* `[src, parent, …, root]` (nearest-ancestor-first). Exclusive only. */
|
|
62
|
+
ancestorsOf(src: EntityID, def: RelationDef<"exclusive">): EntityID[];
|
|
63
|
+
/** The root of `src`'s `R`-chain (`src` itself when it has no target).
|
|
64
|
+
* Exclusive only. */
|
|
65
|
+
rootOf(src: EntityID, def: RelationDef<"exclusive">): EntityID;
|
|
66
|
+
/** Walk relation `R` down from `root` over the reverse index, returning the
|
|
67
|
+
* subtree (including `root`) breadth-first — parents before children (the
|
|
68
|
+
* `cascade` order). Exclusive only. */
|
|
69
|
+
cascadeOf(root: EntityID, def: RelationDef<"exclusive">): EntityID[];
|
|
70
|
+
/** Reclaim relation reverse-index memory: drop every reverse entry whose
|
|
71
|
+
* target has been destroyed, returning the total dropped (#491). Purely
|
|
72
|
+
* cold-path, no observable state change — call at scene/snapshot
|
|
73
|
+
* boundaries. */
|
|
74
|
+
compact(): number;
|
|
75
|
+
}
|
|
76
|
+
/** Event channels and signals. Emit during one `update()`, visible to every
|
|
77
|
+
* later system in that call, cleared before the next. System-side reads and
|
|
78
|
+
* emits go through `ctx` — this facade is the HOST-side surface. */
|
|
79
|
+
export declare class ECSEvents {
|
|
80
|
+
private readonly store;
|
|
81
|
+
/** @internal constructed by `ECS`. */
|
|
82
|
+
constructor(store: Store);
|
|
83
|
+
/** Register an event channel at world setup, before anything emits on it.
|
|
84
|
+
* `fields` must name EVERY schema key — an under-registered channel would
|
|
85
|
+
* silently drop the missing fields at emit (see `EventFieldsCover`).
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const Damaged = eventKey<{ target: EntityID; amount: number }>("Damaged");
|
|
89
|
+
* ecs.events.register(Damaged, ["target", "amount"]);
|
|
90
|
+
* ecs.events.emit(Damaged, { target: e, amount: 10 }); // or ctx.emit inside a system
|
|
91
|
+
*/
|
|
92
|
+
register<S extends EventShape<S>, const F extends readonly (keyof S & string)[]>(key: EventKey<S>, fields: F & EventFieldsCover<S, F>): void;
|
|
93
|
+
/** Register a signal (empty-payload event channel). */
|
|
94
|
+
registerSignal(key: SignalKey): void;
|
|
95
|
+
emit(key: SignalKey): void;
|
|
96
|
+
emit<S extends EventShape<S>>(key: EventKey<S>, values: NoInfer<S>): void;
|
|
97
|
+
read<S extends EventShape<S>>(key: EventKey<S>): EventReader<S>;
|
|
98
|
+
}
|
|
99
|
+
/** World resources — singleton values keyed by `ResourceKey<T>`. Runtime
|
|
100
|
+
* mutations (`set` / `remove`) are access-checked as resource writes inside
|
|
101
|
+
* a system span; `register` is a one-time world-setup op. */
|
|
102
|
+
export declare class ECSResources {
|
|
103
|
+
private readonly store;
|
|
104
|
+
/** @internal constructed by `ECS`. */
|
|
105
|
+
constructor(store: Store);
|
|
106
|
+
/** Register a resource at world setup. Reading/writing an unregistered
|
|
107
|
+
* key throws (fail-closed) — registration is the explicit "this world has
|
|
108
|
+
* this singleton" declaration, not a lazy default.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* const GameTime = resourceKey<{ elapsed: number }>("GameTime");
|
|
112
|
+
* ecs.resources.register(GameTime, { elapsed: 0 });
|
|
113
|
+
* ecs.resources.get(GameTime).elapsed; // or ctx.resource(GameTime) inside a system
|
|
114
|
+
*/
|
|
115
|
+
register<T>(key: ResourceKey<T>, value: NoInfer<T>): void;
|
|
116
|
+
get<T>(key: ResourceKey<T>): T;
|
|
117
|
+
set<T>(key: ResourceKey<T>, value: NoInfer<T>): void;
|
|
118
|
+
/** Drop a resource from the world (#798). Access-checked as a *write*;
|
|
119
|
+
* fails closed on a missing key. Afterwards the key is free to `register`
|
|
120
|
+
* again — the present → absent → present lifecycle. */
|
|
121
|
+
remove<T>(key: ResourceKey<T>): void;
|
|
122
|
+
has<T>(key: ResourceKey<T>): boolean;
|
|
123
|
+
}
|
|
124
|
+
/** The determinism surface (#626 / ADR-0020): world snapshot/resume and the
|
|
125
|
+
* canonical state digest. Every member except `deterministic` throws
|
|
126
|
+
* `DETERMINISM_DISABLED` unless the world was constructed with
|
|
127
|
+
* `{ deterministic: true }`. All cold-path — take captures at tick
|
|
128
|
+
* boundaries (between `update()`s). */
|
|
129
|
+
export declare class ECSSnapshots {
|
|
130
|
+
private readonly store;
|
|
131
|
+
/** @internal constructed by `ECS`. */
|
|
132
|
+
constructor(store: Store);
|
|
133
|
+
/** Whether the determinism surface is enabled. */
|
|
134
|
+
get deterministic(): boolean;
|
|
135
|
+
/** FNV-1a 32 digest over every archetype's live rows in id order — the
|
|
136
|
+
* canonical "live ECS state digest". Per-call cost scales with live
|
|
137
|
+
* entity count, not SAB capacity. */
|
|
138
|
+
stateHash(): number;
|
|
139
|
+
/** Capture the full live world (dense + sparse/relations + host-side
|
|
140
|
+
* bookkeeping) to one self-contained byte buffer that `restore` can mount
|
|
141
|
+
* back onto a live, ticking world (#789). v1 does NOT capture resources,
|
|
142
|
+
* events, or change-detection baselines (ADR-0031). */
|
|
143
|
+
capture(): Uint8Array;
|
|
144
|
+
/** Mount a `capture()` buffer onto this live world and keep ticking.
|
|
145
|
+
* Fails closed on a malformed frame or registration mismatch BEFORE
|
|
146
|
+
* mutating any live state. Requires a matching archetype set + column
|
|
147
|
+
* layout (prewarm so the set is stable). */
|
|
148
|
+
restore(bytes: Uint8Array): void;
|
|
149
|
+
/** Serialize the sparse stores + relations to a self-contained buffer —
|
|
150
|
+
* the sparse half of a world snapshot, canonical entity-index order
|
|
151
|
+
* (#470). Pairs with `restoreSparse`. */
|
|
152
|
+
captureSparse(): Uint8Array;
|
|
153
|
+
/** Repopulate the sparse stores + relation indices from `captureSparse`
|
|
154
|
+
* bytes. Sparse components must already be registered in the same order;
|
|
155
|
+
* throws `SparseRestoreError` on a shape or identity mismatch. */
|
|
156
|
+
restoreSparse(bytes: Uint8Array): void;
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=facades.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facades.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/facades.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ECS } from './ecs.cjs';
|
|
2
|
+
type FrameCallback = (timestampMs: number) => void;
|
|
3
|
+
type RequestFrame = (callback: FrameCallback) => number;
|
|
4
|
+
type CancelFrame = (handle: number) => void;
|
|
5
|
+
export interface FrameStepperOptions {
|
|
6
|
+
/** Delta used by `step()` when no dt is supplied, in seconds. Default 1/60. */
|
|
7
|
+
readonly fixedDt?: number;
|
|
8
|
+
/** Clamp browser-frame deltas before forwarding them to `ECS.update()`, in
|
|
9
|
+
* seconds. Default 0.25. A backgrounded tab suspends rAF; the first frame
|
|
10
|
+
* after it resumes carries the whole suspended interval as one delta, and
|
|
11
|
+
* without the clamp that lands in `update()`'s accumulator as a giant
|
|
12
|
+
* catch-up burst (bounded by `maxFixedSteps`, but still a burst). Manual
|
|
13
|
+
* `step()` deltas are deliberately not clamped — an explicit dt is trusted. */
|
|
14
|
+
readonly maxDt?: number;
|
|
15
|
+
/** Dependency injection for tests or non-browser hosts. Defaults to `requestAnimationFrame`. */
|
|
16
|
+
readonly requestFrame?: RequestFrame;
|
|
17
|
+
/** Dependency injection for tests or non-browser hosts. Defaults to `cancelAnimationFrame`. */
|
|
18
|
+
readonly cancelFrame?: CancelFrame;
|
|
19
|
+
/** Start the automatic frame loop immediately. */
|
|
20
|
+
readonly autoStart?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Small host-side controller for manual ECS frame stepping.
|
|
24
|
+
*
|
|
25
|
+
* `ECS.update(dt)` is already the authoritative "run one frame" primitive.
|
|
26
|
+
* This class wraps it with pause/play controls for browser loops and an explicit
|
|
27
|
+
* `step()` method for debuggers, tests, editor tools, and rollback playback.
|
|
28
|
+
*/
|
|
29
|
+
export declare class FrameStepper {
|
|
30
|
+
private readonly ecs;
|
|
31
|
+
private readonly requestFrame?;
|
|
32
|
+
private readonly cancelFrame?;
|
|
33
|
+
private frameHandle;
|
|
34
|
+
private lastTimestampMs;
|
|
35
|
+
private running;
|
|
36
|
+
private _fixedDt;
|
|
37
|
+
private _maxDt;
|
|
38
|
+
constructor(ecs: ECS, options?: FrameStepperOptions);
|
|
39
|
+
get fixedDt(): number;
|
|
40
|
+
set fixedDt(value: number);
|
|
41
|
+
get maxDt(): number;
|
|
42
|
+
set maxDt(value: number);
|
|
43
|
+
get isRunning(): boolean;
|
|
44
|
+
/** Advance exactly one ECS frame. */
|
|
45
|
+
step(dt?: number): void;
|
|
46
|
+
/** Advance several fixed-size frames, useful for replaying a paused sim. */
|
|
47
|
+
stepFrames(count: number, dt?: number): void;
|
|
48
|
+
/** Start ticking with `requestAnimationFrame`; no-op when already running. */
|
|
49
|
+
play(): void;
|
|
50
|
+
/** Stop the automatic frame loop. Manual `step()` still works while paused. */
|
|
51
|
+
pause(): void;
|
|
52
|
+
toggle(): void;
|
|
53
|
+
dispose(): void;
|
|
54
|
+
private scheduleNextFrame;
|
|
55
|
+
private readonly onFrame;
|
|
56
|
+
}
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=frame_stepper.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ECS } from './ecs.js';
|
|
2
|
+
type FrameCallback = (timestampMs: number) => void;
|
|
3
|
+
type RequestFrame = (callback: FrameCallback) => number;
|
|
4
|
+
type CancelFrame = (handle: number) => void;
|
|
5
|
+
export interface FrameStepperOptions {
|
|
6
|
+
/** Delta used by `step()` when no dt is supplied, in seconds. Default 1/60. */
|
|
7
|
+
readonly fixedDt?: number;
|
|
8
|
+
/** Clamp browser-frame deltas before forwarding them to `ECS.update()`, in
|
|
9
|
+
* seconds. Default 0.25. A backgrounded tab suspends rAF; the first frame
|
|
10
|
+
* after it resumes carries the whole suspended interval as one delta, and
|
|
11
|
+
* without the clamp that lands in `update()`'s accumulator as a giant
|
|
12
|
+
* catch-up burst (bounded by `maxFixedSteps`, but still a burst). Manual
|
|
13
|
+
* `step()` deltas are deliberately not clamped — an explicit dt is trusted. */
|
|
14
|
+
readonly maxDt?: number;
|
|
15
|
+
/** Dependency injection for tests or non-browser hosts. Defaults to `requestAnimationFrame`. */
|
|
16
|
+
readonly requestFrame?: RequestFrame;
|
|
17
|
+
/** Dependency injection for tests or non-browser hosts. Defaults to `cancelAnimationFrame`. */
|
|
18
|
+
readonly cancelFrame?: CancelFrame;
|
|
19
|
+
/** Start the automatic frame loop immediately. */
|
|
20
|
+
readonly autoStart?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Small host-side controller for manual ECS frame stepping.
|
|
24
|
+
*
|
|
25
|
+
* `ECS.update(dt)` is already the authoritative "run one frame" primitive.
|
|
26
|
+
* This class wraps it with pause/play controls for browser loops and an explicit
|
|
27
|
+
* `step()` method for debuggers, tests, editor tools, and rollback playback.
|
|
28
|
+
*/
|
|
29
|
+
export declare class FrameStepper {
|
|
30
|
+
private readonly ecs;
|
|
31
|
+
private readonly requestFrame?;
|
|
32
|
+
private readonly cancelFrame?;
|
|
33
|
+
private frameHandle;
|
|
34
|
+
private lastTimestampMs;
|
|
35
|
+
private running;
|
|
36
|
+
private _fixedDt;
|
|
37
|
+
private _maxDt;
|
|
38
|
+
constructor(ecs: ECS, options?: FrameStepperOptions);
|
|
39
|
+
get fixedDt(): number;
|
|
40
|
+
set fixedDt(value: number);
|
|
41
|
+
get maxDt(): number;
|
|
42
|
+
set maxDt(value: number);
|
|
43
|
+
get isRunning(): boolean;
|
|
44
|
+
/** Advance exactly one ECS frame. */
|
|
45
|
+
step(dt?: number): void;
|
|
46
|
+
/** Advance several fixed-size frames, useful for replaying a paused sim. */
|
|
47
|
+
stepFrames(count: number, dt?: number): void;
|
|
48
|
+
/** Start ticking with `requestAnimationFrame`; no-op when already running. */
|
|
49
|
+
play(): void;
|
|
50
|
+
/** Stop the automatic frame loop. Manual `step()` still works while paused. */
|
|
51
|
+
pause(): void;
|
|
52
|
+
toggle(): void;
|
|
53
|
+
dispose(): void;
|
|
54
|
+
private scheduleNextFrame;
|
|
55
|
+
private readonly onFrame;
|
|
56
|
+
}
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=frame_stepper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame_stepper.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/frame_stepper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAGjC,KAAK,aAAa,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;AACnD,KAAK,YAAY,GAAG,CAAC,QAAQ,EAAE,aAAa,KAAK,MAAM,CAAC;AACxD,KAAK,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAM5C,MAAM,WAAW,mBAAmB;IACnC,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;mFAK+E;IAC/E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gGAAgG;IAChG,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC,+FAA+F;IAC/F,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC,kDAAkD;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC7B;AAsBD;;;;;;GAMG;AACH,qBAAa,YAAY;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAc;IAC3C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEJ,GAAG,EAAE,GAAG,EAAE,OAAO,GAAE,mBAAwB;IAW9D,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED,IAAW,OAAO,CAAC,KAAK,EAAE,MAAM,EAE/B;IAED,IAAW,KAAK,IAAI,MAAM,CAEzB;IAED,IAAW,KAAK,CAAC,KAAK,EAAE,MAAM,EAE7B;IAED,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED,qCAAqC;IAC9B,IAAI,CAAC,EAAE,GAAE,MAAsB,GAAG,IAAI;IAI7C,4EAA4E;IACrE,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAE,MAAsB,GAAG,IAAI;IAMlE,8EAA8E;IACvE,IAAI,IAAI,IAAI;IAanB,+EAA+E;IACxE,KAAK,IAAI,IAAI;IASb,MAAM,IAAI,IAAI;IAKd,OAAO,IAAI,IAAI;IAItB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAQtB;CACF"}
|