@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,12 @@
|
|
|
1
|
+
export declare const UNASSIGNED = -1;
|
|
2
|
+
export declare const NO_SWAP = -1;
|
|
3
|
+
export declare const EMPTY_VALUES: Record<string, number>;
|
|
4
|
+
export declare const HASH_GOLDEN_RATIO = 2654435769;
|
|
5
|
+
export declare const HASH_SECONDARY_PRIME = 1367130551;
|
|
6
|
+
export declare const DEFAULT_COLUMN_CAPACITY = 1024;
|
|
7
|
+
export declare const INITIAL_GENERATION = 0;
|
|
8
|
+
export declare const TOTAL_PACKED_BITS = 31;
|
|
9
|
+
export declare const DEFAULT_FIXED_TIMESTEP: number;
|
|
10
|
+
export declare const DEFAULT_MAX_FIXED_STEPS = 4;
|
|
11
|
+
export declare const STARTUP_DELTA_TIME = 0;
|
|
12
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/core/ecs/utils/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,OAAO,KAAK,CAAC;AAC1B,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAsC,CAAC;AAGvF,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAC5C,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAG/C,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAG5C,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAGpC,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAC7C,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAGzC,eAAO,MAAM,kBAAkB,IAAI,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { AppError } from '../../../utils/error.cjs';
|
|
2
|
+
export declare enum ECS_ERROR {
|
|
3
|
+
EID_MAX_INDEX_OVERFLOW = "EID_MAX_INDEX_OVERFLOW",
|
|
4
|
+
EID_MAX_GEN_OVERFLOW = "EID_MAX_GEN_OVERFLOW",
|
|
5
|
+
COMPONENT_NOT_REGISTERED = "COMPONENT_NOT_REGISTERED",
|
|
6
|
+
COMPONENT_LIMIT_EXCEEDED = "COMPONENT_LIMIT_EXCEEDED",
|
|
7
|
+
ENTITY_NOT_ALIVE = "ENTITY_NOT_ALIVE",
|
|
8
|
+
CIRCULAR_SYSTEM_DEPENDENCY = "CIRCULAR_SYSTEM_DEPENDENCY",
|
|
9
|
+
DUPLICATE_SYSTEM = "DUPLICATE_SYSTEM",
|
|
10
|
+
ARCHETYPE_NOT_FOUND = "ARCHETYPE_NOT_FOUND",
|
|
11
|
+
RESOURCE_NOT_REGISTERED = "RESOURCE_NOT_REGISTERED",
|
|
12
|
+
RESOURCE_ALREADY_REGISTERED = "RESOURCE_ALREADY_REGISTERED",
|
|
13
|
+
EVENT_ALREADY_REGISTERED = "EVENT_ALREADY_REGISTERED",
|
|
14
|
+
EVENT_NOT_REGISTERED = "EVENT_NOT_REGISTERED",
|
|
15
|
+
FIELD_NOT_REGISTERED = "FIELD_NOT_REGISTERED",
|
|
16
|
+
RELATION_NOT_REGISTERED = "RELATION_NOT_REGISTERED",
|
|
17
|
+
RELATION_MODE_INVALID = "RELATION_MODE_INVALID",
|
|
18
|
+
RELATION_MODE_MISMATCH = "RELATION_MODE_MISMATCH",
|
|
19
|
+
RELATION_CYCLE = "RELATION_CYCLE",
|
|
20
|
+
SPARSE_CACHE_KEY_OVERFLOW = "SPARSE_CACHE_KEY_OVERFLOW",
|
|
21
|
+
SPARSE_QUERY_DENSE_PATH = "SPARSE_QUERY_DENSE_PATH",
|
|
22
|
+
HIERARCHY_ALREADY_SET = "HIERARCHY_ALREADY_SET",
|
|
23
|
+
HIERARCHY_INVALID_MAX_DEPTH = "HIERARCHY_INVALID_MAX_DEPTH",
|
|
24
|
+
OBSERVER_NON_CONVERGENT = "OBSERVER_NON_CONVERGENT",
|
|
25
|
+
OBSERVER_INVALID_CONFIG = "OBSERVER_INVALID_CONFIG",
|
|
26
|
+
OBSERVER_ONSET_EMIT = "OBSERVER_ONSET_EMIT",
|
|
27
|
+
INVALID_FIXED_TIMESTEP = "INVALID_FIXED_TIMESTEP",
|
|
28
|
+
INVALID_MAX_FIXED_STEPS = "INVALID_MAX_FIXED_STEPS",
|
|
29
|
+
INVALID_RECORDER_SCHEDULE = "INVALID_RECORDER_SCHEDULE",
|
|
30
|
+
EMPTY_ARCHETYPE_MATERIALIZE = "EMPTY_ARCHETYPE_MATERIALIZE",
|
|
31
|
+
COMPONENT_INDEX_INVARIANT = "COMPONENT_INDEX_INVARIANT",
|
|
32
|
+
OPTIONAL_TERM_NOT_DECLARED = "OPTIONAL_TERM_NOT_DECLARED",
|
|
33
|
+
QUERY_ACCESS_UNDECLARED = "QUERY_ACCESS_UNDECLARED",
|
|
34
|
+
/** A system touched a component/sparse/relation/resource it didn't declare
|
|
35
|
+
* in its access surface — distinct from *_NOT_REGISTERED (which means the
|
|
36
|
+
* thing was never registered with the world at all). */
|
|
37
|
+
ACCESS_UNDECLARED = "ACCESS_UNDECLARED",
|
|
38
|
+
/** `Query.singleEntity` found 0 or >1 matches (dev-only assertion). */
|
|
39
|
+
QUERY_NOT_SINGLETON = "QUERY_NOT_SINGLETON",
|
|
40
|
+
/** A run-condition factory was given invalid arguments (dev-only). */
|
|
41
|
+
INVALID_RUN_CONDITION = "INVALID_RUN_CONDITION",
|
|
42
|
+
SYSTEM_FN_ARITY = "SYSTEM_FN_ARITY",
|
|
43
|
+
PARTITION_APPEND_NEEDS_ENTITY_ROW = "PARTITION_APPEND_NEEDS_ENTITY_ROW",
|
|
44
|
+
PARTITION_BULK_INTO_DISABLED = "PARTITION_BULK_INTO_DISABLED",
|
|
45
|
+
ENTITY_NOT_DISABLED = "ENTITY_NOT_DISABLED",
|
|
46
|
+
STRUCTURAL_DURING_ITERATION = "STRUCTURAL_DURING_ITERATION",
|
|
47
|
+
BACKEND_ALREADY_ATTACHED = "BACKEND_ALREADY_ATTACHED",
|
|
48
|
+
DETERMINISM_DISABLED = "DETERMINISM_DISABLED",
|
|
49
|
+
NON_DETERMINISTIC_COLUMN_TYPE = "NON_DETERMINISTIC_COLUMN_TYPE",
|
|
50
|
+
INVALID_MEMORY_OPTIONS = "INVALID_MEMORY_OPTIONS",
|
|
51
|
+
STORE_CAP_EXCEEDED = "STORE_CAP_EXCEEDED",
|
|
52
|
+
REGION_NOT_DECLARED = "REGION_NOT_DECLARED",
|
|
53
|
+
COMMAND_LOG_TAG_COLLISION = "COMMAND_LOG_TAG_COLLISION",
|
|
54
|
+
INVALID_FRAME_STEP = "INVALID_FRAME_STEP"
|
|
55
|
+
}
|
|
56
|
+
export declare class ECSError extends AppError {
|
|
57
|
+
readonly category: ECS_ERROR;
|
|
58
|
+
constructor(category: ECS_ERROR, message?: string, context?: Record<string, unknown>);
|
|
59
|
+
}
|
|
60
|
+
export declare function isEcsError(error: unknown): error is ECSError;
|
|
61
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { AppError } from '../../../utils/error.js';
|
|
2
|
+
export declare enum ECS_ERROR {
|
|
3
|
+
EID_MAX_INDEX_OVERFLOW = "EID_MAX_INDEX_OVERFLOW",
|
|
4
|
+
EID_MAX_GEN_OVERFLOW = "EID_MAX_GEN_OVERFLOW",
|
|
5
|
+
COMPONENT_NOT_REGISTERED = "COMPONENT_NOT_REGISTERED",
|
|
6
|
+
COMPONENT_LIMIT_EXCEEDED = "COMPONENT_LIMIT_EXCEEDED",
|
|
7
|
+
ENTITY_NOT_ALIVE = "ENTITY_NOT_ALIVE",
|
|
8
|
+
CIRCULAR_SYSTEM_DEPENDENCY = "CIRCULAR_SYSTEM_DEPENDENCY",
|
|
9
|
+
DUPLICATE_SYSTEM = "DUPLICATE_SYSTEM",
|
|
10
|
+
ARCHETYPE_NOT_FOUND = "ARCHETYPE_NOT_FOUND",
|
|
11
|
+
RESOURCE_NOT_REGISTERED = "RESOURCE_NOT_REGISTERED",
|
|
12
|
+
RESOURCE_ALREADY_REGISTERED = "RESOURCE_ALREADY_REGISTERED",
|
|
13
|
+
EVENT_ALREADY_REGISTERED = "EVENT_ALREADY_REGISTERED",
|
|
14
|
+
EVENT_NOT_REGISTERED = "EVENT_NOT_REGISTERED",
|
|
15
|
+
FIELD_NOT_REGISTERED = "FIELD_NOT_REGISTERED",
|
|
16
|
+
RELATION_NOT_REGISTERED = "RELATION_NOT_REGISTERED",
|
|
17
|
+
RELATION_MODE_INVALID = "RELATION_MODE_INVALID",
|
|
18
|
+
RELATION_MODE_MISMATCH = "RELATION_MODE_MISMATCH",
|
|
19
|
+
RELATION_CYCLE = "RELATION_CYCLE",
|
|
20
|
+
SPARSE_CACHE_KEY_OVERFLOW = "SPARSE_CACHE_KEY_OVERFLOW",
|
|
21
|
+
SPARSE_QUERY_DENSE_PATH = "SPARSE_QUERY_DENSE_PATH",
|
|
22
|
+
HIERARCHY_ALREADY_SET = "HIERARCHY_ALREADY_SET",
|
|
23
|
+
HIERARCHY_INVALID_MAX_DEPTH = "HIERARCHY_INVALID_MAX_DEPTH",
|
|
24
|
+
OBSERVER_NON_CONVERGENT = "OBSERVER_NON_CONVERGENT",
|
|
25
|
+
OBSERVER_INVALID_CONFIG = "OBSERVER_INVALID_CONFIG",
|
|
26
|
+
OBSERVER_ONSET_EMIT = "OBSERVER_ONSET_EMIT",
|
|
27
|
+
INVALID_FIXED_TIMESTEP = "INVALID_FIXED_TIMESTEP",
|
|
28
|
+
INVALID_MAX_FIXED_STEPS = "INVALID_MAX_FIXED_STEPS",
|
|
29
|
+
INVALID_RECORDER_SCHEDULE = "INVALID_RECORDER_SCHEDULE",
|
|
30
|
+
EMPTY_ARCHETYPE_MATERIALIZE = "EMPTY_ARCHETYPE_MATERIALIZE",
|
|
31
|
+
COMPONENT_INDEX_INVARIANT = "COMPONENT_INDEX_INVARIANT",
|
|
32
|
+
OPTIONAL_TERM_NOT_DECLARED = "OPTIONAL_TERM_NOT_DECLARED",
|
|
33
|
+
QUERY_ACCESS_UNDECLARED = "QUERY_ACCESS_UNDECLARED",
|
|
34
|
+
/** A system touched a component/sparse/relation/resource it didn't declare
|
|
35
|
+
* in its access surface — distinct from *_NOT_REGISTERED (which means the
|
|
36
|
+
* thing was never registered with the world at all). */
|
|
37
|
+
ACCESS_UNDECLARED = "ACCESS_UNDECLARED",
|
|
38
|
+
/** `Query.singleEntity` found 0 or >1 matches (dev-only assertion). */
|
|
39
|
+
QUERY_NOT_SINGLETON = "QUERY_NOT_SINGLETON",
|
|
40
|
+
/** A run-condition factory was given invalid arguments (dev-only). */
|
|
41
|
+
INVALID_RUN_CONDITION = "INVALID_RUN_CONDITION",
|
|
42
|
+
SYSTEM_FN_ARITY = "SYSTEM_FN_ARITY",
|
|
43
|
+
PARTITION_APPEND_NEEDS_ENTITY_ROW = "PARTITION_APPEND_NEEDS_ENTITY_ROW",
|
|
44
|
+
PARTITION_BULK_INTO_DISABLED = "PARTITION_BULK_INTO_DISABLED",
|
|
45
|
+
ENTITY_NOT_DISABLED = "ENTITY_NOT_DISABLED",
|
|
46
|
+
STRUCTURAL_DURING_ITERATION = "STRUCTURAL_DURING_ITERATION",
|
|
47
|
+
BACKEND_ALREADY_ATTACHED = "BACKEND_ALREADY_ATTACHED",
|
|
48
|
+
DETERMINISM_DISABLED = "DETERMINISM_DISABLED",
|
|
49
|
+
NON_DETERMINISTIC_COLUMN_TYPE = "NON_DETERMINISTIC_COLUMN_TYPE",
|
|
50
|
+
INVALID_MEMORY_OPTIONS = "INVALID_MEMORY_OPTIONS",
|
|
51
|
+
STORE_CAP_EXCEEDED = "STORE_CAP_EXCEEDED",
|
|
52
|
+
REGION_NOT_DECLARED = "REGION_NOT_DECLARED",
|
|
53
|
+
COMMAND_LOG_TAG_COLLISION = "COMMAND_LOG_TAG_COLLISION",
|
|
54
|
+
INVALID_FRAME_STEP = "INVALID_FRAME_STEP"
|
|
55
|
+
}
|
|
56
|
+
export declare class ECSError extends AppError {
|
|
57
|
+
readonly category: ECS_ERROR;
|
|
58
|
+
constructor(category: ECS_ERROR, message?: string, context?: Record<string, unknown>);
|
|
59
|
+
}
|
|
60
|
+
export declare function isEcsError(error: unknown): error is ECSError;
|
|
61
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../../src/core/ecs/utils/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,oBAAY,SAAS;IACpB,sBAAsB,2BAA2B;IACjD,oBAAoB,yBAAyB;IAC7C,wBAAwB,6BAA6B;IACrD,wBAAwB,6BAA6B;IACrD,gBAAgB,qBAAqB;IACrC,0BAA0B,+BAA+B;IACzD,gBAAgB,qBAAqB;IACrC,mBAAmB,wBAAwB;IAC3C,uBAAuB,4BAA4B;IACnD,2BAA2B,gCAAgC;IAC3D,wBAAwB,6BAA6B;IACrD,oBAAoB,yBAAyB;IAC7C,oBAAoB,yBAAyB;IAC7C,uBAAuB,4BAA4B;IACnD,qBAAqB,0BAA0B;IAC/C,sBAAsB,2BAA2B;IACjD,cAAc,mBAAmB;IACjC,yBAAyB,8BAA8B;IACvD,uBAAuB,4BAA4B;IACnD,qBAAqB,0BAA0B;IAC/C,2BAA2B,gCAAgC;IAC3D,uBAAuB,4BAA4B;IACnD,uBAAuB,4BAA4B;IACnD,mBAAmB,wBAAwB;IAC3C,sBAAsB,2BAA2B;IACjD,uBAAuB,4BAA4B;IACnD,yBAAyB,8BAA8B;IACvD,2BAA2B,gCAAgC;IAC3D,yBAAyB,8BAA8B;IACvD,0BAA0B,+BAA+B;IACzD,uBAAuB,4BAA4B;IACnD;;4DAEwD;IACxD,iBAAiB,sBAAsB;IACvC,uEAAuE;IACvE,mBAAmB,wBAAwB;IAC3C,sEAAsE;IACtE,qBAAqB,0BAA0B;IAC/C,eAAe,oBAAoB;IACnC,iCAAiC,sCAAsC;IACvE,4BAA4B,iCAAiC;IAC7D,mBAAmB,wBAAwB;IAC3C,2BAA2B,gCAAgC;IAC3D,wBAAwB,6BAA6B;IACrD,oBAAoB,yBAAyB;IAC7C,6BAA6B,kCAAkC;IAC/D,sBAAsB,2BAA2B;IACjD,kBAAkB,uBAAuB;IACzC,mBAAmB,wBAAwB;IAC3C,yBAAyB,8BAA8B;IACvD,kBAAkB,uBAAuB;CACzC;AAED,qBAAa,QAAS,SAAQ,QAAQ;aAEpB,QAAQ,EAAE,SAAS;gBAAnB,QAAQ,EAAE,SAAS,EACnC,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAIlC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action ring — main-thread producer / worker-thread consumer SPSC ring
|
|
3
|
+
* for client input intents (`send_action`-shaped bytes). Plan §6.5 task
|
|
4
|
+
* 3 / `docs/ideas/buffer-wasm-sim-plan-2026-05-14T1600.md`.
|
|
5
|
+
*
|
|
6
|
+
* Same on-the-wire shape as `command_ring.ts`, but with two practical
|
|
7
|
+
* differences:
|
|
8
|
+
*
|
|
9
|
+
* 1. Producer/consumer roles flip — the action ring is main → worker,
|
|
10
|
+
* whereas the command ring is sim → host.
|
|
11
|
+
* 2. Slot payload carries a `length` prefix because client actions are
|
|
12
|
+
* variable-width (the encoded bytes that would normally go straight
|
|
13
|
+
* to the WebSocket). `payload[0]` is the length in bytes; bytes
|
|
14
|
+
* `[1..1+length)` are the action payload itself.
|
|
15
|
+
*
|
|
16
|
+
* Layout (identical to command ring header):
|
|
17
|
+
*
|
|
18
|
+
* [ write_head: u32 ] monotonic; modulo `capacity_slots` for slot
|
|
19
|
+
* [ read_head: u32 ] monotonic
|
|
20
|
+
* [ capacity: u32 ] slot count, power-of-two
|
|
21
|
+
* [ overflow: u32 ] 0 = OK; 1 = ring exhausted (producer side)
|
|
22
|
+
* [ slot 0: 16 B ] length: u8, payload: [15]u8
|
|
23
|
+
* [ slot 1: 16 B ] ...
|
|
24
|
+
*
|
|
25
|
+
* SPSC contract:
|
|
26
|
+
* - Producer: main thread, from `GameNetworkClient.send_action`. Pushes
|
|
27
|
+
* one entry per user action; `Atomics.store`s `write_head` after each.
|
|
28
|
+
* - Consumer: sim worker, drained on each `apply_diff` / `apply_snapshot`
|
|
29
|
+
* boundary. `Atomics.store`s `read_head` after each pop.
|
|
30
|
+
* - Today's consumer is a no-op observer (logs / counts in DEV) — the
|
|
31
|
+
* wire path still goes main → WebSocket → server. PR 5N migrates the
|
|
32
|
+
* `PredictionReconciler` into the worker so the action ring becomes
|
|
33
|
+
* load-bearing for client-side prediction.
|
|
34
|
+
*
|
|
35
|
+
* Overflow:
|
|
36
|
+
* - If main writes a slot when `(write_head - read_head) === capacity`,
|
|
37
|
+
* it sets `overflow = 1` and the push returns `false`. The server
|
|
38
|
+
* send path is independent (`_transport.send(...)` ran first), so an
|
|
39
|
+
* overflow doesn't drop the action — it only drops worker
|
|
40
|
+
* observability for that one entry.
|
|
41
|
+
*
|
|
42
|
+
* Atomics: the head fields (`write_head` / `read_head`) are the
|
|
43
|
+
* cross-thread synchronization edge — the producer runs on the main
|
|
44
|
+
* thread, the consumer in the sim worker, and both alias the same
|
|
45
|
+
* `SharedArrayBuffer`. The producer writes the slot bytes, then
|
|
46
|
+
* `Atomics.store`s `write_head`; the consumer `Atomics.load`s
|
|
47
|
+
* `write_head` before touching the slot, reads it, then `Atomics.store`s
|
|
48
|
+
* `read_head`. These SeqCst ops establish the happens-before that a
|
|
49
|
+
* plain `DataView` write does not under the JS memory model (#374):
|
|
50
|
+
* without them the worker could observe a bumped `write_head` before the
|
|
51
|
+
* producer's `setUint8(len)` + payload `set()` are visible and read a
|
|
52
|
+
* torn/stale slot, and the producer could read a stale `read_head`
|
|
53
|
+
* (false overflow, or overwrite a slot mid-read). Slot payload bytes
|
|
54
|
+
* stay on plain `DataView` / `Uint8Array` ops — the head Atomics fence
|
|
55
|
+
* them, so no per-byte atomic is needed. A future PR may still add an
|
|
56
|
+
* `Atomics.wait/notify` pair so the worker can block between actions
|
|
57
|
+
* instead of polling — additive change, no layout shift.
|
|
58
|
+
*/
|
|
59
|
+
/** Total bytes for the ring header. Identical to `command_ring`. */
|
|
60
|
+
export declare const ACTION_RING_HEADER_BYTES = 16;
|
|
61
|
+
/** Fixed slot size — 1-byte length + 15-byte payload. */
|
|
62
|
+
export declare const ACTION_RING_SLOT_BYTES = 16;
|
|
63
|
+
/** Default ring capacity in slots. Sized for ~250 ms of click-spam at 60
|
|
64
|
+
* Hz on the high end of human input rates; 256 × 16 B = 4 KiB + 16 B
|
|
65
|
+
* header. */
|
|
66
|
+
export declare const ACTION_RING_DEFAULT_CAPACITY_SLOTS = 256;
|
|
67
|
+
/** Max payload bytes per slot (slot size minus the length prefix). All
|
|
68
|
+
* actions defined in `packages/protocol/src/actions.ts` encode to under
|
|
69
|
+
* 8 bytes, so this is comfortably above today's max. */
|
|
70
|
+
export declare const ACTION_RING_MAX_PAYLOAD_BYTES: number;
|
|
71
|
+
/** Byte offsets within the ring header. Matches `command_ring` so a
|
|
72
|
+
* future shared helper can normalise across both rings without per-ring
|
|
73
|
+
* arithmetic. */
|
|
74
|
+
export declare const ACTION_RING_HEADER_OFFSETS: {
|
|
75
|
+
readonly write_head: 0;
|
|
76
|
+
readonly read_head: 4;
|
|
77
|
+
readonly capacity_slots: 8;
|
|
78
|
+
readonly overflow_flag: 12;
|
|
79
|
+
};
|
|
80
|
+
/** Total bytes the ring occupies for `capacity_slots` slots. */
|
|
81
|
+
export declare function actionRingBytes(capacitySlots: number): number;
|
|
82
|
+
export declare class ActionRingError extends Error {
|
|
83
|
+
constructor(message: string);
|
|
84
|
+
}
|
|
85
|
+
/** Initialise the ring header at `ringOff` in the SAB. Zeroes heads
|
|
86
|
+
* and the overflow flag; sets `capacity_slots`. Slot bytes are left
|
|
87
|
+
* as-is (callers normally allocate the ring on a zero-initialised SAB). */
|
|
88
|
+
export declare function initActionRing(view: DataView, ringOff: number, capacitySlots: number): void;
|
|
89
|
+
/** Read live ring-header fields. Heads are stored signed but returned
|
|
90
|
+
* unsigned (`>>> 0`) so the monotonic-counter arithmetic below is
|
|
91
|
+
* identical to the prior `getUint32` behaviour. */
|
|
92
|
+
export declare function actionRingWriteHead(view: DataView, ringOff: number): number;
|
|
93
|
+
export declare function actionRingReadHead(view: DataView, ringOff: number): number;
|
|
94
|
+
export declare function actionRingCapacitySlots(view: DataView, ringOff: number): number;
|
|
95
|
+
export declare function actionRingOverflow(view: DataView, ringOff: number): boolean;
|
|
96
|
+
/** Pending entry count = `(write_head - read_head) mod 2^32`. */
|
|
97
|
+
export declare function pendingActionCount(view: DataView, ringOff: number): number;
|
|
98
|
+
/** Push an action into the ring. `payload` must be in
|
|
99
|
+
* `[1, ACTION_RING_MAX_PAYLOAD_BYTES]`; longer payloads — and **empty**
|
|
100
|
+
* ones — are an `ActionRingError` (the producer is the only caller and it
|
|
101
|
+
* can size its inputs ahead of time). The zero-length rejection closes the
|
|
102
|
+
* lower-bound footgun: a 0-byte slot is indistinguishable from
|
|
103
|
+
* `popAction`'s empty-ring sentinel (`0`), so admitting one would let it
|
|
104
|
+
* masquerade as "ring empty". No encoder produces a 0-byte payload, so this
|
|
105
|
+
* only ever rejects the ABI-skew bug case (#430). Returns `false` on
|
|
106
|
+
* overflow and sets the overflow flag. */
|
|
107
|
+
export declare function pushAction(view: DataView, ringOff: number, payload: Uint8Array): boolean;
|
|
108
|
+
/** Pop one action from the ring. Returns the byte length written into
|
|
109
|
+
* `outPayload`, or `0` if the ring was empty. `outPayload` must be at
|
|
110
|
+
* least `ACTION_RING_MAX_PAYLOAD_BYTES`; only the first `length` bytes
|
|
111
|
+
* are meaningful after a non-zero return.
|
|
112
|
+
*
|
|
113
|
+
* NOTE: a `0` return is ambiguous — it means "ring empty" OR "a 0-byte
|
|
114
|
+
* slot" (the latter only reachable via ABI-skew, since `pushAction`
|
|
115
|
+
* rejects empty payloads). Callers that loop must decide emptiness from
|
|
116
|
+
* the heads (`pendingActionCount` / `write_head === read_head`), not
|
|
117
|
+
* from this return value; see `drainActionRing` and #430. */
|
|
118
|
+
export declare function popAction(view: DataView, ringOff: number, outPayload: Uint8Array): number;
|
|
119
|
+
/** Drain every pending action, invoking `handler(payload)` per entry.
|
|
120
|
+
* The `payload` passed to the handler is a freshly-copied
|
|
121
|
+
* `Uint8Array(length)` so handlers can hold it past the next pop without
|
|
122
|
+
* aliasing the scratch buffer. Returns the number of actions drained.
|
|
123
|
+
*
|
|
124
|
+
* Termination is decided from the heads (`pendingActionCount`), NOT from
|
|
125
|
+
* `popAction`'s return value. A genuine 0-byte slot returns `0` — the same
|
|
126
|
+
* value `popAction` yields on an empty ring — so terminating on `len === 0`
|
|
127
|
+
* would silently consume the zero-length entry and strand everything queued
|
|
128
|
+
* behind it for a tick (#430). The heads check is SPSC-safe: this consumer
|
|
129
|
+
* is the sole reader, so a non-zero pending count cannot race to empty before
|
|
130
|
+
* the `popAction` below. */
|
|
131
|
+
export declare function drainActionRing(view: DataView, ringOff: number, handler: (payload: Uint8Array) => void): number;
|
|
132
|
+
/** Clear the overflow flag. The producer sets it on a failed push; the
|
|
133
|
+
* consumer can reset it once it has observed and logged the condition,
|
|
134
|
+
* so a single overflow doesn't keep firing dev assertions. */
|
|
135
|
+
export declare function clearActionRingOverflow(view: DataView, ringOff: number): void;
|
|
136
|
+
//# sourceMappingURL=action_ring.d.ts.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action ring — main-thread producer / worker-thread consumer SPSC ring
|
|
3
|
+
* for client input intents (`send_action`-shaped bytes). Plan §6.5 task
|
|
4
|
+
* 3 / `docs/ideas/buffer-wasm-sim-plan-2026-05-14T1600.md`.
|
|
5
|
+
*
|
|
6
|
+
* Same on-the-wire shape as `command_ring.ts`, but with two practical
|
|
7
|
+
* differences:
|
|
8
|
+
*
|
|
9
|
+
* 1. Producer/consumer roles flip — the action ring is main → worker,
|
|
10
|
+
* whereas the command ring is sim → host.
|
|
11
|
+
* 2. Slot payload carries a `length` prefix because client actions are
|
|
12
|
+
* variable-width (the encoded bytes that would normally go straight
|
|
13
|
+
* to the WebSocket). `payload[0]` is the length in bytes; bytes
|
|
14
|
+
* `[1..1+length)` are the action payload itself.
|
|
15
|
+
*
|
|
16
|
+
* Layout (identical to command ring header):
|
|
17
|
+
*
|
|
18
|
+
* [ write_head: u32 ] monotonic; modulo `capacity_slots` for slot
|
|
19
|
+
* [ read_head: u32 ] monotonic
|
|
20
|
+
* [ capacity: u32 ] slot count, power-of-two
|
|
21
|
+
* [ overflow: u32 ] 0 = OK; 1 = ring exhausted (producer side)
|
|
22
|
+
* [ slot 0: 16 B ] length: u8, payload: [15]u8
|
|
23
|
+
* [ slot 1: 16 B ] ...
|
|
24
|
+
*
|
|
25
|
+
* SPSC contract:
|
|
26
|
+
* - Producer: main thread, from `GameNetworkClient.send_action`. Pushes
|
|
27
|
+
* one entry per user action; `Atomics.store`s `write_head` after each.
|
|
28
|
+
* - Consumer: sim worker, drained on each `apply_diff` / `apply_snapshot`
|
|
29
|
+
* boundary. `Atomics.store`s `read_head` after each pop.
|
|
30
|
+
* - Today's consumer is a no-op observer (logs / counts in DEV) — the
|
|
31
|
+
* wire path still goes main → WebSocket → server. PR 5N migrates the
|
|
32
|
+
* `PredictionReconciler` into the worker so the action ring becomes
|
|
33
|
+
* load-bearing for client-side prediction.
|
|
34
|
+
*
|
|
35
|
+
* Overflow:
|
|
36
|
+
* - If main writes a slot when `(write_head - read_head) === capacity`,
|
|
37
|
+
* it sets `overflow = 1` and the push returns `false`. The server
|
|
38
|
+
* send path is independent (`_transport.send(...)` ran first), so an
|
|
39
|
+
* overflow doesn't drop the action — it only drops worker
|
|
40
|
+
* observability for that one entry.
|
|
41
|
+
*
|
|
42
|
+
* Atomics: the head fields (`write_head` / `read_head`) are the
|
|
43
|
+
* cross-thread synchronization edge — the producer runs on the main
|
|
44
|
+
* thread, the consumer in the sim worker, and both alias the same
|
|
45
|
+
* `SharedArrayBuffer`. The producer writes the slot bytes, then
|
|
46
|
+
* `Atomics.store`s `write_head`; the consumer `Atomics.load`s
|
|
47
|
+
* `write_head` before touching the slot, reads it, then `Atomics.store`s
|
|
48
|
+
* `read_head`. These SeqCst ops establish the happens-before that a
|
|
49
|
+
* plain `DataView` write does not under the JS memory model (#374):
|
|
50
|
+
* without them the worker could observe a bumped `write_head` before the
|
|
51
|
+
* producer's `setUint8(len)` + payload `set()` are visible and read a
|
|
52
|
+
* torn/stale slot, and the producer could read a stale `read_head`
|
|
53
|
+
* (false overflow, or overwrite a slot mid-read). Slot payload bytes
|
|
54
|
+
* stay on plain `DataView` / `Uint8Array` ops — the head Atomics fence
|
|
55
|
+
* them, so no per-byte atomic is needed. A future PR may still add an
|
|
56
|
+
* `Atomics.wait/notify` pair so the worker can block between actions
|
|
57
|
+
* instead of polling — additive change, no layout shift.
|
|
58
|
+
*/
|
|
59
|
+
/** Total bytes for the ring header. Identical to `command_ring`. */
|
|
60
|
+
export declare const ACTION_RING_HEADER_BYTES = 16;
|
|
61
|
+
/** Fixed slot size — 1-byte length + 15-byte payload. */
|
|
62
|
+
export declare const ACTION_RING_SLOT_BYTES = 16;
|
|
63
|
+
/** Default ring capacity in slots. Sized for ~250 ms of click-spam at 60
|
|
64
|
+
* Hz on the high end of human input rates; 256 × 16 B = 4 KiB + 16 B
|
|
65
|
+
* header. */
|
|
66
|
+
export declare const ACTION_RING_DEFAULT_CAPACITY_SLOTS = 256;
|
|
67
|
+
/** Max payload bytes per slot (slot size minus the length prefix). All
|
|
68
|
+
* actions defined in `packages/protocol/src/actions.ts` encode to under
|
|
69
|
+
* 8 bytes, so this is comfortably above today's max. */
|
|
70
|
+
export declare const ACTION_RING_MAX_PAYLOAD_BYTES: number;
|
|
71
|
+
/** Byte offsets within the ring header. Matches `command_ring` so a
|
|
72
|
+
* future shared helper can normalise across both rings without per-ring
|
|
73
|
+
* arithmetic. */
|
|
74
|
+
export declare const ACTION_RING_HEADER_OFFSETS: {
|
|
75
|
+
readonly write_head: 0;
|
|
76
|
+
readonly read_head: 4;
|
|
77
|
+
readonly capacity_slots: 8;
|
|
78
|
+
readonly overflow_flag: 12;
|
|
79
|
+
};
|
|
80
|
+
/** Total bytes the ring occupies for `capacity_slots` slots. */
|
|
81
|
+
export declare function actionRingBytes(capacitySlots: number): number;
|
|
82
|
+
export declare class ActionRingError extends Error {
|
|
83
|
+
constructor(message: string);
|
|
84
|
+
}
|
|
85
|
+
/** Initialise the ring header at `ringOff` in the SAB. Zeroes heads
|
|
86
|
+
* and the overflow flag; sets `capacity_slots`. Slot bytes are left
|
|
87
|
+
* as-is (callers normally allocate the ring on a zero-initialised SAB). */
|
|
88
|
+
export declare function initActionRing(view: DataView, ringOff: number, capacitySlots: number): void;
|
|
89
|
+
/** Read live ring-header fields. Heads are stored signed but returned
|
|
90
|
+
* unsigned (`>>> 0`) so the monotonic-counter arithmetic below is
|
|
91
|
+
* identical to the prior `getUint32` behaviour. */
|
|
92
|
+
export declare function actionRingWriteHead(view: DataView, ringOff: number): number;
|
|
93
|
+
export declare function actionRingReadHead(view: DataView, ringOff: number): number;
|
|
94
|
+
export declare function actionRingCapacitySlots(view: DataView, ringOff: number): number;
|
|
95
|
+
export declare function actionRingOverflow(view: DataView, ringOff: number): boolean;
|
|
96
|
+
/** Pending entry count = `(write_head - read_head) mod 2^32`. */
|
|
97
|
+
export declare function pendingActionCount(view: DataView, ringOff: number): number;
|
|
98
|
+
/** Push an action into the ring. `payload` must be in
|
|
99
|
+
* `[1, ACTION_RING_MAX_PAYLOAD_BYTES]`; longer payloads — and **empty**
|
|
100
|
+
* ones — are an `ActionRingError` (the producer is the only caller and it
|
|
101
|
+
* can size its inputs ahead of time). The zero-length rejection closes the
|
|
102
|
+
* lower-bound footgun: a 0-byte slot is indistinguishable from
|
|
103
|
+
* `popAction`'s empty-ring sentinel (`0`), so admitting one would let it
|
|
104
|
+
* masquerade as "ring empty". No encoder produces a 0-byte payload, so this
|
|
105
|
+
* only ever rejects the ABI-skew bug case (#430). Returns `false` on
|
|
106
|
+
* overflow and sets the overflow flag. */
|
|
107
|
+
export declare function pushAction(view: DataView, ringOff: number, payload: Uint8Array): boolean;
|
|
108
|
+
/** Pop one action from the ring. Returns the byte length written into
|
|
109
|
+
* `outPayload`, or `0` if the ring was empty. `outPayload` must be at
|
|
110
|
+
* least `ACTION_RING_MAX_PAYLOAD_BYTES`; only the first `length` bytes
|
|
111
|
+
* are meaningful after a non-zero return.
|
|
112
|
+
*
|
|
113
|
+
* NOTE: a `0` return is ambiguous — it means "ring empty" OR "a 0-byte
|
|
114
|
+
* slot" (the latter only reachable via ABI-skew, since `pushAction`
|
|
115
|
+
* rejects empty payloads). Callers that loop must decide emptiness from
|
|
116
|
+
* the heads (`pendingActionCount` / `write_head === read_head`), not
|
|
117
|
+
* from this return value; see `drainActionRing` and #430. */
|
|
118
|
+
export declare function popAction(view: DataView, ringOff: number, outPayload: Uint8Array): number;
|
|
119
|
+
/** Drain every pending action, invoking `handler(payload)` per entry.
|
|
120
|
+
* The `payload` passed to the handler is a freshly-copied
|
|
121
|
+
* `Uint8Array(length)` so handlers can hold it past the next pop without
|
|
122
|
+
* aliasing the scratch buffer. Returns the number of actions drained.
|
|
123
|
+
*
|
|
124
|
+
* Termination is decided from the heads (`pendingActionCount`), NOT from
|
|
125
|
+
* `popAction`'s return value. A genuine 0-byte slot returns `0` — the same
|
|
126
|
+
* value `popAction` yields on an empty ring — so terminating on `len === 0`
|
|
127
|
+
* would silently consume the zero-length entry and strand everything queued
|
|
128
|
+
* behind it for a tick (#430). The heads check is SPSC-safe: this consumer
|
|
129
|
+
* is the sole reader, so a non-zero pending count cannot race to empty before
|
|
130
|
+
* the `popAction` below. */
|
|
131
|
+
export declare function drainActionRing(view: DataView, ringOff: number, handler: (payload: Uint8Array) => void): number;
|
|
132
|
+
/** Clear the overflow flag. The producer sets it on a failed push; the
|
|
133
|
+
* consumer can reset it once it has observed and logged the condition,
|
|
134
|
+
* so a single overflow doesn't keep firing dev assertions. */
|
|
135
|
+
export declare function clearActionRingOverflow(view: DataView, ringOff: number): void;
|
|
136
|
+
//# sourceMappingURL=action_ring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action_ring.d.ts","sourceRoot":"","sources":["../../../src/core/store/action_ring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAEH,oEAAoE;AACpE,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAE3C,yDAAyD;AACzD,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;aAEa;AACb,eAAO,MAAM,kCAAkC,MAAM,CAAC;AAEtD;;wDAEwD;AACxD,eAAO,MAAM,6BAA6B,QAA6B,CAAC;AAExE;;iBAEiB;AACjB,eAAO,MAAM,0BAA0B;;;;;CAK7B,CAAC;AAwBX,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE7D;AAMD,qBAAa,eAAgB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI3B;AAED;;2EAE2E;AAC3E,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAiB3F;AAED;;mDAEmD;AACnD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3E;AACD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1E;AACD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/E;AACD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3E;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED;;;;;;;;0CAQ0C;AAC1C,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAoCxF;AAED;;;;;;;;;6DAS6D;AAC7D,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,CAwBzF;AAED;;;;;;;;;;;4BAW4B;AAC5B,wBAAgB,eAAe,CAC9B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,GACpC,MAAM,CAUR;AAED;;8DAE8D;AAC9D,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7E"}
|