@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,2318 @@
|
|
|
1
|
+
import { S as et, t as tt } from "./topological_sort-DK6EjpWa.js";
|
|
2
|
+
import { D as nt, h as K, w as we, g as st } from "./shared-BU1Cd40h.js";
|
|
3
|
+
class Be extends Error {
|
|
4
|
+
constructor(t, n, r) {
|
|
5
|
+
super(t), this.isOperational = n, this.context = r, this.name = this.constructor.name, Error.captureStackTrace(this, this.constructor);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
var Fe = /* @__PURE__ */ ((e) => (e.ASSERTION_FAIL_CONDITION = "ASSERTION_FAIL_CONDITION", e.VALIDATION_FAIL_CONDITION = "VALIDATION_FAIL_CONDITION", e.ASSERTION_FAIL_NON_NULLABLE = "ASSERTION_FAIL_NON_NULLABLE", e.ASSERTION_FAIL_UNREACHABLE = "ASSERTION_FAIL_UNREACHABLE", e))(Fe || {});
|
|
9
|
+
class rt extends Be {
|
|
10
|
+
constructor(t, n, r) {
|
|
11
|
+
super(n, !1, r), this.category = t;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function yn(e, t, n) {
|
|
15
|
+
return e;
|
|
16
|
+
}
|
|
17
|
+
function Tn(e) {
|
|
18
|
+
return e;
|
|
19
|
+
}
|
|
20
|
+
function ot(e, t) {
|
|
21
|
+
throw new rt(
|
|
22
|
+
Fe.ASSERTION_FAIL_UNREACHABLE,
|
|
23
|
+
`Unhandled ${t}: ${String(e)}`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
var w = /* @__PURE__ */ ((e) => (e.EID_MAX_INDEX_OVERFLOW = "EID_MAX_INDEX_OVERFLOW", e.EID_MAX_GEN_OVERFLOW = "EID_MAX_GEN_OVERFLOW", e.COMPONENT_NOT_REGISTERED = "COMPONENT_NOT_REGISTERED", e.COMPONENT_LIMIT_EXCEEDED = "COMPONENT_LIMIT_EXCEEDED", e.ENTITY_NOT_ALIVE = "ENTITY_NOT_ALIVE", e.CIRCULAR_SYSTEM_DEPENDENCY = "CIRCULAR_SYSTEM_DEPENDENCY", e.DUPLICATE_SYSTEM = "DUPLICATE_SYSTEM", e.ARCHETYPE_NOT_FOUND = "ARCHETYPE_NOT_FOUND", e.RESOURCE_NOT_REGISTERED = "RESOURCE_NOT_REGISTERED", e.RESOURCE_ALREADY_REGISTERED = "RESOURCE_ALREADY_REGISTERED", e.EVENT_ALREADY_REGISTERED = "EVENT_ALREADY_REGISTERED", e.EVENT_NOT_REGISTERED = "EVENT_NOT_REGISTERED", e.FIELD_NOT_REGISTERED = "FIELD_NOT_REGISTERED", e.RELATION_NOT_REGISTERED = "RELATION_NOT_REGISTERED", e.RELATION_MODE_INVALID = "RELATION_MODE_INVALID", e.RELATION_MODE_MISMATCH = "RELATION_MODE_MISMATCH", e.RELATION_CYCLE = "RELATION_CYCLE", e.SPARSE_CACHE_KEY_OVERFLOW = "SPARSE_CACHE_KEY_OVERFLOW", e.SPARSE_QUERY_DENSE_PATH = "SPARSE_QUERY_DENSE_PATH", e.HIERARCHY_ALREADY_SET = "HIERARCHY_ALREADY_SET", e.HIERARCHY_INVALID_MAX_DEPTH = "HIERARCHY_INVALID_MAX_DEPTH", e.OBSERVER_NON_CONVERGENT = "OBSERVER_NON_CONVERGENT", e.OBSERVER_INVALID_CONFIG = "OBSERVER_INVALID_CONFIG", e.OBSERVER_ONSET_EMIT = "OBSERVER_ONSET_EMIT", e.INVALID_FIXED_TIMESTEP = "INVALID_FIXED_TIMESTEP", e.INVALID_MAX_FIXED_STEPS = "INVALID_MAX_FIXED_STEPS", e.INVALID_RECORDER_SCHEDULE = "INVALID_RECORDER_SCHEDULE", e.EMPTY_ARCHETYPE_MATERIALIZE = "EMPTY_ARCHETYPE_MATERIALIZE", e.COMPONENT_INDEX_INVARIANT = "COMPONENT_INDEX_INVARIANT", e.OPTIONAL_TERM_NOT_DECLARED = "OPTIONAL_TERM_NOT_DECLARED", e.QUERY_ACCESS_UNDECLARED = "QUERY_ACCESS_UNDECLARED", e.ACCESS_UNDECLARED = "ACCESS_UNDECLARED", e.QUERY_NOT_SINGLETON = "QUERY_NOT_SINGLETON", e.INVALID_RUN_CONDITION = "INVALID_RUN_CONDITION", e.SYSTEM_FN_ARITY = "SYSTEM_FN_ARITY", e.PARTITION_APPEND_NEEDS_ENTITY_ROW = "PARTITION_APPEND_NEEDS_ENTITY_ROW", e.PARTITION_BULK_INTO_DISABLED = "PARTITION_BULK_INTO_DISABLED", e.ENTITY_NOT_DISABLED = "ENTITY_NOT_DISABLED", e.STRUCTURAL_DURING_ITERATION = "STRUCTURAL_DURING_ITERATION", e.BACKEND_ALREADY_ATTACHED = "BACKEND_ALREADY_ATTACHED", e.DETERMINISM_DISABLED = "DETERMINISM_DISABLED", e.NON_DETERMINISTIC_COLUMN_TYPE = "NON_DETERMINISTIC_COLUMN_TYPE", e.INVALID_MEMORY_OPTIONS = "INVALID_MEMORY_OPTIONS", e.STORE_CAP_EXCEEDED = "STORE_CAP_EXCEEDED", e.REGION_NOT_DECLARED = "REGION_NOT_DECLARED", e.COMMAND_LOG_TAG_COLLISION = "COMMAND_LOG_TAG_COLLISION", e.INVALID_FRAME_STEP = "INVALID_FRAME_STEP", e))(w || {});
|
|
27
|
+
class S extends Be {
|
|
28
|
+
constructor(t, n, r) {
|
|
29
|
+
super(n ?? t, !0, r), this.category = t;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function An(e) {
|
|
33
|
+
return e instanceof S;
|
|
34
|
+
}
|
|
35
|
+
const In = -1, wn = -1, Sn = Object.freeze(/* @__PURE__ */ Object.create(null)), Nn = 2654435769, Dn = 1367130551, B = 1024, Rn = 0, it = 31, On = 1 / 60, bn = 4, at = 0, z = 20, Ye = (1 << z) - 1, P = Ye, ct = it - z, _e = (1 << ct) - 1, Cn = _e, Un = _e - 1, Se = _e << z | P, vn = (e, t) => t << z | e, k = (e) => e & Ye, Ln = (e) => e >> z, he = /* @__PURE__ */ new WeakMap();
|
|
36
|
+
function Mn(e, t) {
|
|
37
|
+
he.set(e, t);
|
|
38
|
+
}
|
|
39
|
+
function $n(e) {
|
|
40
|
+
return he.get(e);
|
|
41
|
+
}
|
|
42
|
+
function dt(e) {
|
|
43
|
+
const t = he.get(e);
|
|
44
|
+
return t !== void 0 ? `'${t}' (component ${e.id})` : `component ${e.id}`;
|
|
45
|
+
}
|
|
46
|
+
const lt = 827148627, ut = 0, J = 4, ft = 52, m = {
|
|
47
|
+
magic: 0,
|
|
48
|
+
sim_abi_version: 4,
|
|
49
|
+
view_stamp: 8,
|
|
50
|
+
capacity: 12,
|
|
51
|
+
archetype_count: 16,
|
|
52
|
+
layout_descriptor_off: 20,
|
|
53
|
+
command_ring_off: 24,
|
|
54
|
+
action_ring_off: 28,
|
|
55
|
+
entity_index_off: 32,
|
|
56
|
+
event_ring_off: 36,
|
|
57
|
+
region_table_off: 40,
|
|
58
|
+
region_table_count: 44,
|
|
59
|
+
bindings_off: 48
|
|
60
|
+
}, q = 12, L = {
|
|
61
|
+
region_id: 0,
|
|
62
|
+
byte_offset: 4,
|
|
63
|
+
byte_length: 8
|
|
64
|
+
}, me = 16, O = {
|
|
65
|
+
component_id: 0,
|
|
66
|
+
field_id: 2,
|
|
67
|
+
type_tag: 4,
|
|
68
|
+
byte_off: 8,
|
|
69
|
+
stride: 12
|
|
70
|
+
}, ge = 36, N = {
|
|
71
|
+
archetype_id: 0,
|
|
72
|
+
component_mask: 4,
|
|
73
|
+
row_count: 20,
|
|
74
|
+
row_capacity: 24,
|
|
75
|
+
column_count: 28,
|
|
76
|
+
enabled_count: 32
|
|
77
|
+
};
|
|
78
|
+
function _t(e, t) {
|
|
79
|
+
e.setUint32(m.magic, t.magic, !0), e.setUint32(m.sim_abi_version, t.simAbiVersion, !0), e.setUint32(m.view_stamp, t.viewStamp, !0), e.setUint32(m.capacity, t.capacity, !0), e.setUint32(m.archetype_count, t.archetypeCount, !0), e.setUint32(m.layout_descriptor_off, t.layoutDescriptorOff, !0), e.setUint32(m.command_ring_off, t.commandRingOff, !0), e.setUint32(m.action_ring_off, t.actionRingOff, !0), e.setUint32(m.entity_index_off, t.entityIndexOff, !0), e.setUint32(m.event_ring_off, t.eventRingOff, !0), e.setUint32(m.region_table_off, t.regionTableOff, !0), e.setUint32(m.region_table_count, t.regionTableCount, !0), e.setUint32(m.bindings_off, t.bindingsOff, !0);
|
|
80
|
+
}
|
|
81
|
+
function Pn(e) {
|
|
82
|
+
return {
|
|
83
|
+
magic: e.getUint32(m.magic, !0),
|
|
84
|
+
simAbiVersion: e.getUint32(m.sim_abi_version, !0),
|
|
85
|
+
viewStamp: e.getUint32(m.view_stamp, !0),
|
|
86
|
+
capacity: e.getUint32(m.capacity, !0),
|
|
87
|
+
archetypeCount: e.getUint32(m.archetype_count, !0),
|
|
88
|
+
layoutDescriptorOff: e.getUint32(m.layout_descriptor_off, !0),
|
|
89
|
+
commandRingOff: e.getUint32(m.command_ring_off, !0),
|
|
90
|
+
actionRingOff: e.getUint32(m.action_ring_off, !0),
|
|
91
|
+
entityIndexOff: e.getUint32(m.entity_index_off, !0),
|
|
92
|
+
eventRingOff: e.getUint32(m.event_ring_off, !0),
|
|
93
|
+
regionTableOff: e.getUint32(m.region_table_off, !0),
|
|
94
|
+
regionTableCount: e.getUint32(m.region_table_count, !0),
|
|
95
|
+
bindingsOff: e.getUint32(m.bindings_off, !0)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const E = {
|
|
99
|
+
u8: 0,
|
|
100
|
+
i8: 1,
|
|
101
|
+
u16: 2,
|
|
102
|
+
i16: 3,
|
|
103
|
+
u32: 4,
|
|
104
|
+
i32: 5,
|
|
105
|
+
f32: 6,
|
|
106
|
+
f64: 7
|
|
107
|
+
}, Ne = Object.freeze({
|
|
108
|
+
[E.u8]: 1,
|
|
109
|
+
[E.i8]: 1,
|
|
110
|
+
[E.u16]: 2,
|
|
111
|
+
[E.i16]: 2,
|
|
112
|
+
[E.u32]: 4,
|
|
113
|
+
[E.i32]: 4,
|
|
114
|
+
[E.f32]: 4,
|
|
115
|
+
[E.f64]: 8
|
|
116
|
+
}), xn = {
|
|
117
|
+
u8: E.u8,
|
|
118
|
+
i8: E.i8,
|
|
119
|
+
u16: E.u16,
|
|
120
|
+
i16: E.i16,
|
|
121
|
+
u32: E.u32,
|
|
122
|
+
i32: E.i32,
|
|
123
|
+
f32: E.f32,
|
|
124
|
+
f64: E.f64
|
|
125
|
+
};
|
|
126
|
+
function ht(e, t, n) {
|
|
127
|
+
e.setUint16(t + O.component_id, n.componentId, !0), e.setUint16(t + O.field_id, n.fieldId, !0), e.setUint8(t + O.type_tag, n.typeTag), e.setUint32(t + O.byte_off, n.byteOff, !0), e.setUint16(t + O.stride, n.stride, !0);
|
|
128
|
+
}
|
|
129
|
+
function mt(e, t) {
|
|
130
|
+
return {
|
|
131
|
+
componentId: e.getUint16(t + O.component_id, !0),
|
|
132
|
+
fieldId: e.getUint16(t + O.field_id, !0),
|
|
133
|
+
typeTag: e.getUint8(t + O.type_tag),
|
|
134
|
+
byteOff: e.getUint32(t + O.byte_off, !0),
|
|
135
|
+
stride: e.getUint16(t + O.stride, !0)
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const Bn = J * 32;
|
|
139
|
+
function ke(e) {
|
|
140
|
+
return ge + e * me;
|
|
141
|
+
}
|
|
142
|
+
function gt(e, t, n) {
|
|
143
|
+
e.setUint32(t + N.archetype_id, n.archetypeId, !0);
|
|
144
|
+
for (let s = 0; s < J; s++)
|
|
145
|
+
e.setUint32(
|
|
146
|
+
t + N.component_mask + s * 4,
|
|
147
|
+
n.componentMask[s] ?? 0,
|
|
148
|
+
!0
|
|
149
|
+
);
|
|
150
|
+
e.setUint32(t + N.row_count, n.rowCount, !0), e.setUint32(t + N.row_capacity, n.rowCapacity, !0), e.setUint32(t + N.column_count, n.columns.length, !0), e.setUint32(t + N.enabled_count, n.enabledCount, !0);
|
|
151
|
+
let r = t + ge;
|
|
152
|
+
for (let s = 0; s < n.columns.length; s++)
|
|
153
|
+
ht(e, r, n.columns[s]), r += me;
|
|
154
|
+
return r;
|
|
155
|
+
}
|
|
156
|
+
function Et(e, t) {
|
|
157
|
+
const n = e.getUint32(t + N.column_count, !0), r = new Array(n);
|
|
158
|
+
let s = t + ge;
|
|
159
|
+
for (let i = 0; i < n; i++)
|
|
160
|
+
r[i] = mt(e, s), s += me;
|
|
161
|
+
const o = new Array(J);
|
|
162
|
+
for (let i = 0; i < J; i++)
|
|
163
|
+
o[i] = e.getUint32(
|
|
164
|
+
t + N.component_mask + i * 4,
|
|
165
|
+
!0
|
|
166
|
+
);
|
|
167
|
+
return {
|
|
168
|
+
archetypeId: e.getUint32(t + N.archetype_id, !0),
|
|
169
|
+
componentMask: o,
|
|
170
|
+
rowCount: e.getUint32(t + N.row_count, !0),
|
|
171
|
+
rowCapacity: e.getUint32(t + N.row_capacity, !0),
|
|
172
|
+
enabledCount: e.getUint32(t + N.enabled_count, !0),
|
|
173
|
+
columns: r
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function pt(e, t, n) {
|
|
177
|
+
let r = t;
|
|
178
|
+
for (let s = 0; s < n.length; s++)
|
|
179
|
+
r = gt(e, r, n[s]);
|
|
180
|
+
return r;
|
|
181
|
+
}
|
|
182
|
+
function Fn(e, t, n) {
|
|
183
|
+
const r = new Array(n);
|
|
184
|
+
let s = t;
|
|
185
|
+
for (let o = 0; o < n; o++) {
|
|
186
|
+
const i = Et(e, s);
|
|
187
|
+
r[o] = i, s += ke(i.columns.length);
|
|
188
|
+
}
|
|
189
|
+
return r;
|
|
190
|
+
}
|
|
191
|
+
function yt(e) {
|
|
192
|
+
let t = 0;
|
|
193
|
+
for (let n = 0; n < e.length; n++)
|
|
194
|
+
t += ke(e[n].columns.length);
|
|
195
|
+
return t;
|
|
196
|
+
}
|
|
197
|
+
const Ve = 16, M = 16, Yn = 256, b = {
|
|
198
|
+
write_head: 0,
|
|
199
|
+
read_head: 4,
|
|
200
|
+
capacity_slots: 8,
|
|
201
|
+
overflow_flag: 12
|
|
202
|
+
}, Ee = 0;
|
|
203
|
+
function De(e) {
|
|
204
|
+
return Ve + e * M;
|
|
205
|
+
}
|
|
206
|
+
function Tt(e) {
|
|
207
|
+
return e > 0 && (e & e - 1) === 0;
|
|
208
|
+
}
|
|
209
|
+
class U extends Error {
|
|
210
|
+
constructor(t) {
|
|
211
|
+
super(t), this.name = "CommandRingError";
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function At(e, t, n) {
|
|
215
|
+
if (!Tt(n))
|
|
216
|
+
throw new U(
|
|
217
|
+
`command ring capacity_slots must be a positive power of two (got ${n})`
|
|
218
|
+
);
|
|
219
|
+
e.setUint32(t + b.write_head, 0, !0), e.setUint32(t + b.read_head, 0, !0), e.setUint32(t + b.capacity_slots, n, !0), e.setUint32(t + b.overflow_flag, 0, !0);
|
|
220
|
+
}
|
|
221
|
+
function It(e, t) {
|
|
222
|
+
return e.getUint32(t + b.write_head, !0);
|
|
223
|
+
}
|
|
224
|
+
function wt(e, t) {
|
|
225
|
+
return e.getUint32(t + b.read_head, !0);
|
|
226
|
+
}
|
|
227
|
+
function St(e, t) {
|
|
228
|
+
return e.getUint32(t + b.capacity_slots, !0);
|
|
229
|
+
}
|
|
230
|
+
function Nt(e, t, n) {
|
|
231
|
+
if (n.byteLength !== M - 1)
|
|
232
|
+
throw new U(
|
|
233
|
+
`out_payload must be ${M - 1} bytes (got ${n.byteLength})`
|
|
234
|
+
);
|
|
235
|
+
const r = It(e, t), s = wt(e, t);
|
|
236
|
+
if (r === s) return Ee;
|
|
237
|
+
const o = St(e, t), i = s & o - 1, c = t + Ve + i * M, a = e.getUint8(c), l = new Uint8Array(e.buffer, c + 1, M - 1);
|
|
238
|
+
return n.set(l), e.setUint32(t + b.read_head, s + 1 >>> 0, !0), a;
|
|
239
|
+
}
|
|
240
|
+
function Dt(e, t, n) {
|
|
241
|
+
let r = 0;
|
|
242
|
+
const s = new Uint8Array(M - 1);
|
|
243
|
+
for (; ; ) {
|
|
244
|
+
const o = Nt(e, t, s);
|
|
245
|
+
if (o === Ee) return r;
|
|
246
|
+
n(o, s.slice()), r++;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const re = 16, D = 12, ee = {
|
|
250
|
+
length: 0,
|
|
251
|
+
capacity: 4
|
|
252
|
+
// 8..16: pad to 16-byte alignment so the i32 arrays start aligned.
|
|
253
|
+
}, v = 1 << 20;
|
|
254
|
+
function Re(e) {
|
|
255
|
+
if (e < 0 || !Number.isInteger(e))
|
|
256
|
+
throw new Ge(
|
|
257
|
+
`entity_index capacity must be a non-negative integer (got ${e})`
|
|
258
|
+
);
|
|
259
|
+
return re + e * D;
|
|
260
|
+
}
|
|
261
|
+
function Rt(e) {
|
|
262
|
+
return e + re;
|
|
263
|
+
}
|
|
264
|
+
function Ot(e, t) {
|
|
265
|
+
return e + re + t * 4;
|
|
266
|
+
}
|
|
267
|
+
function bt(e, t) {
|
|
268
|
+
return e + re + t * 8;
|
|
269
|
+
}
|
|
270
|
+
class Ge extends Error {
|
|
271
|
+
constructor(t) {
|
|
272
|
+
super(t), this.name = "EntityIndexError";
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function Ct(e, t, n) {
|
|
276
|
+
if (n < 0 || !Number.isInteger(n))
|
|
277
|
+
throw new Ge(
|
|
278
|
+
`entity_index capacity must be a non-negative integer (got ${n})`
|
|
279
|
+
);
|
|
280
|
+
e.setUint32(t + ee.length, 0, !0), e.setUint32(t + ee.capacity, n, !0);
|
|
281
|
+
}
|
|
282
|
+
function kn(e, t, n) {
|
|
283
|
+
return {
|
|
284
|
+
generations: new Int32Array(e, Rt(t), n),
|
|
285
|
+
archetypes: new Int32Array(e, Ot(t, n), n),
|
|
286
|
+
rows: new Int32Array(e, bt(t, n), n)
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
const Ut = 16, vt = 16, Vn = 256, Y = {
|
|
290
|
+
write_head: 0,
|
|
291
|
+
read_head: 4,
|
|
292
|
+
capacity_slots: 8,
|
|
293
|
+
overflow_flag: 12
|
|
294
|
+
};
|
|
295
|
+
function Oe(e) {
|
|
296
|
+
return Ut + e * vt;
|
|
297
|
+
}
|
|
298
|
+
function Lt(e) {
|
|
299
|
+
return e > 0 && (e & e - 1) === 0;
|
|
300
|
+
}
|
|
301
|
+
class Mt extends Error {
|
|
302
|
+
constructor(t) {
|
|
303
|
+
super(t), this.name = "EventRingError";
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function $t(e, t, n) {
|
|
307
|
+
if (!Lt(n))
|
|
308
|
+
throw new Mt(
|
|
309
|
+
`event ring capacity_slots must be a positive power of two (got ${n})`
|
|
310
|
+
);
|
|
311
|
+
e.setUint32(t + Y.write_head, 0, !0), e.setUint32(t + Y.read_head, 0, !0), e.setUint32(t + Y.capacity_slots, n, !0), e.setUint32(t + Y.overflow_flag, 0, !0);
|
|
312
|
+
}
|
|
313
|
+
const Pt = 16, xt = 16, Gn = 256, V = {
|
|
314
|
+
write_head: 0,
|
|
315
|
+
read_head: 4,
|
|
316
|
+
capacity_slots: 8,
|
|
317
|
+
overflow_flag: 12
|
|
318
|
+
}, Bt = V.write_head / 4, Ft = V.read_head / 4, Yt = V.capacity_slots / 4, kt = V.overflow_flag / 4;
|
|
319
|
+
function Vt(e, t) {
|
|
320
|
+
return new Int32Array(e.buffer, e.byteOffset + t, 4);
|
|
321
|
+
}
|
|
322
|
+
function be(e) {
|
|
323
|
+
return Pt + e * xt;
|
|
324
|
+
}
|
|
325
|
+
function Gt(e) {
|
|
326
|
+
return e > 0 && (e & e - 1) === 0;
|
|
327
|
+
}
|
|
328
|
+
class Ce extends Error {
|
|
329
|
+
constructor(t) {
|
|
330
|
+
super(t), this.name = "ActionRingError";
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function Ht(e, t, n) {
|
|
334
|
+
if (!Gt(n))
|
|
335
|
+
throw new Ce(
|
|
336
|
+
`action ring capacity_slots must be a positive power of two (got ${n})`
|
|
337
|
+
);
|
|
338
|
+
if ((e.byteOffset + t) % 4 !== 0)
|
|
339
|
+
throw new Ce(
|
|
340
|
+
`action ring header must be 4-byte aligned for Atomics (view.byteOffset ${e.byteOffset} + ring_off ${t} is not a multiple of 4)`
|
|
341
|
+
);
|
|
342
|
+
const r = Vt(e, t);
|
|
343
|
+
Atomics.store(r, Bt, 0), Atomics.store(r, Ft, 0), Atomics.store(r, Yt, n), Atomics.store(r, kt, 0);
|
|
344
|
+
}
|
|
345
|
+
const j = [
|
|
346
|
+
{
|
|
347
|
+
name: "command_ring",
|
|
348
|
+
headerOff: "command_ring_off",
|
|
349
|
+
sizeFromOptions: (e) => e.commandRingCapacitySlots !== void 0 ? De(e.commandRingCapacitySlots) : 0,
|
|
350
|
+
init: (e, t, n) => At(e, t, n.commandRingCapacitySlots),
|
|
351
|
+
regionBytes: (e, t) => De(e.getUint32(t + b.capacity_slots, !0)),
|
|
352
|
+
readOptions: (e, t, n) => {
|
|
353
|
+
n.commandRingCapacitySlots = e.getUint32(
|
|
354
|
+
t + b.capacity_slots,
|
|
355
|
+
!0
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
name: "entity_index",
|
|
361
|
+
headerOff: "entity_index_off",
|
|
362
|
+
sizeFromOptions: (e) => e.entityIndexCapacity !== void 0 ? Re(e.entityIndexCapacity) : 0,
|
|
363
|
+
init: (e, t, n) => Ct(e, t, n.entityIndexCapacity),
|
|
364
|
+
regionBytes: (e, t) => Re(e.getUint32(t + ee.capacity, !0)),
|
|
365
|
+
readOptions: (e, t, n) => {
|
|
366
|
+
n.entityIndexCapacity = e.getUint32(t + ee.capacity, !0);
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
name: "event_ring",
|
|
371
|
+
headerOff: "event_ring_off",
|
|
372
|
+
sizeFromOptions: (e) => e.eventRingCapacitySlots !== void 0 ? Oe(e.eventRingCapacitySlots) : 0,
|
|
373
|
+
init: (e, t, n) => $t(e, t, n.eventRingCapacitySlots),
|
|
374
|
+
regionBytes: (e, t) => Oe(e.getUint32(t + Y.capacity_slots, !0)),
|
|
375
|
+
readOptions: (e, t, n) => {
|
|
376
|
+
n.eventRingCapacitySlots = e.getUint32(
|
|
377
|
+
t + Y.capacity_slots,
|
|
378
|
+
!0
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
name: "action_ring",
|
|
384
|
+
headerOff: "action_ring_off",
|
|
385
|
+
sizeFromOptions: (e) => e.actionRingCapacitySlots !== void 0 ? be(e.actionRingCapacitySlots) : 0,
|
|
386
|
+
init: (e, t, n) => Ht(e, t, n.actionRingCapacitySlots),
|
|
387
|
+
regionBytes: (e, t) => be(e.getUint32(t + V.capacity_slots, !0)),
|
|
388
|
+
readOptions: (e, t, n) => {
|
|
389
|
+
n.actionRingCapacitySlots = e.getUint32(
|
|
390
|
+
t + V.capacity_slots,
|
|
391
|
+
!0
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
];
|
|
396
|
+
class Z extends Error {
|
|
397
|
+
constructor(t) {
|
|
398
|
+
super(t), this.name = "RegionRegistryError";
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function He(e) {
|
|
402
|
+
return e * q;
|
|
403
|
+
}
|
|
404
|
+
function pe(e, t) {
|
|
405
|
+
const n = e.getUint32(m.region_table_count, !0);
|
|
406
|
+
if (t + He(n) > e.byteLength)
|
|
407
|
+
throw new Z(
|
|
408
|
+
`region table of ${n} entries at byte ${t} overruns the buffer (${e.byteLength} bytes)`
|
|
409
|
+
);
|
|
410
|
+
return n;
|
|
411
|
+
}
|
|
412
|
+
function Xt(e) {
|
|
413
|
+
const t = /* @__PURE__ */ new Set();
|
|
414
|
+
for (let n = 0; n < e.length; n++) {
|
|
415
|
+
const r = e[n];
|
|
416
|
+
if (!Number.isInteger(r.id) || r.id <= 0)
|
|
417
|
+
throw new Z(
|
|
418
|
+
`region "${r.name}" has invalid id ${r.id} — region ids must be positive integers (0 is the absent sentinel)`
|
|
419
|
+
);
|
|
420
|
+
if (t.has(r.id))
|
|
421
|
+
throw new Z(
|
|
422
|
+
`duplicate region id ${r.id} (region "${r.name}") — ids must be distinct within a consumer's region set`
|
|
423
|
+
);
|
|
424
|
+
if (t.add(r.id), !Number.isInteger(r.bytes) || r.bytes <= 0)
|
|
425
|
+
throw new Z(
|
|
426
|
+
`region "${r.name}" (id ${r.id}) has invalid byte size ${r.bytes} — must be a positive integer`
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function Wt(e, t, n) {
|
|
431
|
+
e.setUint32(t + L.region_id, n.regionId, !0), e.setUint32(t + L.byte_offset, n.byteOffset, !0), e.setUint32(t + L.byte_length, n.byteLength, !0);
|
|
432
|
+
}
|
|
433
|
+
function Xe(e, t) {
|
|
434
|
+
return {
|
|
435
|
+
regionId: e.getUint32(t + L.region_id, !0),
|
|
436
|
+
byteOffset: e.getUint32(t + L.byte_offset, !0),
|
|
437
|
+
byteLength: e.getUint32(t + L.byte_length, !0)
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
function zt(e, t, n) {
|
|
441
|
+
for (let r = 0; r < n.length; r++)
|
|
442
|
+
Wt(e, t + r * q, n[r]);
|
|
443
|
+
}
|
|
444
|
+
function qt(e, t, n) {
|
|
445
|
+
const r = new Array(n);
|
|
446
|
+
for (let s = 0; s < n; s++)
|
|
447
|
+
r[s] = Xe(e, t + s * q);
|
|
448
|
+
return r;
|
|
449
|
+
}
|
|
450
|
+
function Hn(e) {
|
|
451
|
+
const t = e.getUint32(m.region_table_off, !0);
|
|
452
|
+
if (t === 0) return [];
|
|
453
|
+
const n = pe(e, t);
|
|
454
|
+
return qt(e, t, n);
|
|
455
|
+
}
|
|
456
|
+
function Xn(e, t) {
|
|
457
|
+
const n = e.getUint32(m.region_table_off, !0);
|
|
458
|
+
if (n === 0) return 0;
|
|
459
|
+
const r = pe(e, n);
|
|
460
|
+
for (let s = 0; s < r; s++) {
|
|
461
|
+
const o = n + s * q;
|
|
462
|
+
if (e.getUint32(o + L.region_id, !0) === t)
|
|
463
|
+
return e.getUint32(o + L.byte_offset, !0);
|
|
464
|
+
}
|
|
465
|
+
return 0;
|
|
466
|
+
}
|
|
467
|
+
function Wn(e, t) {
|
|
468
|
+
const n = e.getUint32(m.region_table_off, !0);
|
|
469
|
+
if (n === 0) return null;
|
|
470
|
+
const r = pe(e, n);
|
|
471
|
+
for (let s = 0; s < r; s++) {
|
|
472
|
+
const o = Xe(e, n + s * q);
|
|
473
|
+
if (o.regionId === t) return o;
|
|
474
|
+
}
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
function Kt(e, t) {
|
|
478
|
+
return e << 16 | t;
|
|
479
|
+
}
|
|
480
|
+
const ye = 2 ** 31;
|
|
481
|
+
class We extends Error {
|
|
482
|
+
constructor(t) {
|
|
483
|
+
super(
|
|
484
|
+
`SAB column layout offset ${t} reaches or exceeds the 2³¹ (${ye}-byte) ceiling. Past 2 GiB the signed-32-bit bitwise alignment math wraps to negative/misaligned offsets. This is a structural limit independent of the (default 256 MiB) allocator cap — a single SAB cannot back more than ~2 GiB of column data (#382).`
|
|
485
|
+
), this.name = "StoreLayoutOverflowError";
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
function ze(e, t) {
|
|
489
|
+
if (e + t > ye)
|
|
490
|
+
throw new We(e);
|
|
491
|
+
return e + (t - 1) & ~(t - 1);
|
|
492
|
+
}
|
|
493
|
+
function jt(e, t, n, r) {
|
|
494
|
+
switch (t) {
|
|
495
|
+
case E.u8:
|
|
496
|
+
return new Uint8Array(e, n, r);
|
|
497
|
+
case E.i8:
|
|
498
|
+
return new Int8Array(e, n, r);
|
|
499
|
+
case E.u16:
|
|
500
|
+
return new Uint16Array(e, n, r);
|
|
501
|
+
case E.i16:
|
|
502
|
+
return new Int16Array(e, n, r);
|
|
503
|
+
case E.u32:
|
|
504
|
+
return new Uint32Array(e, n, r);
|
|
505
|
+
case E.i32:
|
|
506
|
+
return new Int32Array(e, n, r);
|
|
507
|
+
case E.f32:
|
|
508
|
+
return new Float32Array(e, n, r);
|
|
509
|
+
case E.f64:
|
|
510
|
+
return new Float64Array(e, n, r);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function Qt(e, t, n = 0) {
|
|
514
|
+
const s = yt(
|
|
515
|
+
e.map((c) => ({
|
|
516
|
+
archetypeId: c.archetypeId,
|
|
517
|
+
componentMask: c.componentMask,
|
|
518
|
+
rowCount: 0,
|
|
519
|
+
enabledCount: 0,
|
|
520
|
+
rowCapacity: c.rowCapacity,
|
|
521
|
+
columns: c.columns.map((a) => ({
|
|
522
|
+
componentId: a.componentId,
|
|
523
|
+
fieldId: a.fieldId,
|
|
524
|
+
typeTag: a.typeTag,
|
|
525
|
+
byteOff: 0,
|
|
526
|
+
stride: Ne[a.typeTag]
|
|
527
|
+
}))
|
|
528
|
+
}))
|
|
529
|
+
) + n;
|
|
530
|
+
let o = t + s;
|
|
531
|
+
const i = new Array(e.length);
|
|
532
|
+
for (let c = 0; c < e.length; c++) {
|
|
533
|
+
const a = e[c], l = new Array(a.columns.length);
|
|
534
|
+
for (let d = 0; d < a.columns.length; d++) {
|
|
535
|
+
const f = a.columns[d], _ = Ne[f.typeTag];
|
|
536
|
+
o = ze(o, _), l[d] = {
|
|
537
|
+
componentId: f.componentId,
|
|
538
|
+
fieldId: f.fieldId,
|
|
539
|
+
typeTag: f.typeTag,
|
|
540
|
+
byteOff: o,
|
|
541
|
+
stride: _
|
|
542
|
+
}, o += _ * a.rowCapacity;
|
|
543
|
+
}
|
|
544
|
+
i[c] = {
|
|
545
|
+
archetypeId: a.archetypeId,
|
|
546
|
+
componentMask: a.componentMask,
|
|
547
|
+
rowCount: 0,
|
|
548
|
+
enabledCount: 0,
|
|
549
|
+
rowCapacity: a.rowCapacity,
|
|
550
|
+
columns: l
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
if (o > ye)
|
|
554
|
+
throw new We(o);
|
|
555
|
+
return { descriptors: i, totalBytes: o, regionBytes: s };
|
|
556
|
+
}
|
|
557
|
+
function zn(e) {
|
|
558
|
+
const t = e;
|
|
559
|
+
return typeof t._regionBytes == "number" && typeof t._allocator == "function" && typeof t._reservedDescriptorBytes == "number";
|
|
560
|
+
}
|
|
561
|
+
function qn(e, t = nt, n = {}) {
|
|
562
|
+
const r = {};
|
|
563
|
+
let s = ft;
|
|
564
|
+
for (let A = 0; A < j.length; A++) {
|
|
565
|
+
const C = j[A], H = C.sizeFromOptions(n);
|
|
566
|
+
r[C.headerOff] = H === 0 ? 0 : s, s += H;
|
|
567
|
+
}
|
|
568
|
+
const o = n.regions ?? [];
|
|
569
|
+
Xt(o);
|
|
570
|
+
const i = o.length, c = i > 0 ? s : 0;
|
|
571
|
+
s += He(i);
|
|
572
|
+
const a = new Array(i);
|
|
573
|
+
for (let A = 0; A < o.length; A++) {
|
|
574
|
+
const C = o[A];
|
|
575
|
+
a[A] = { regionId: C.id, byteOffset: s, byteLength: C.bytes }, s += C.bytes;
|
|
576
|
+
}
|
|
577
|
+
const l = n.bindingsRegionBytes ?? 0, d = l === 0 ? 0 : s;
|
|
578
|
+
s += l;
|
|
579
|
+
const f = s, { descriptors: _, totalBytes: g, regionBytes: y } = Qt(
|
|
580
|
+
e,
|
|
581
|
+
f,
|
|
582
|
+
n.reservedDescriptorBytes ?? 0
|
|
583
|
+
), u = t(g), h = new DataView(u), T = {
|
|
584
|
+
magic: lt,
|
|
585
|
+
simAbiVersion: ut,
|
|
586
|
+
viewStamp: 0,
|
|
587
|
+
capacity: g,
|
|
588
|
+
archetypeCount: e.length,
|
|
589
|
+
layoutDescriptorOff: f,
|
|
590
|
+
bindingsOff: d,
|
|
591
|
+
regionTableOff: c,
|
|
592
|
+
regionTableCount: i,
|
|
593
|
+
// `regionOffsets` stays keyed by the snake ABI field names (it also indexes
|
|
594
|
+
// `STORE_HEADER_OFFSETS`); map its 4 entries onto the camelCase header fields.
|
|
595
|
+
commandRingOff: r.command_ring_off,
|
|
596
|
+
entityIndexOff: r.entity_index_off,
|
|
597
|
+
eventRingOff: r.event_ring_off,
|
|
598
|
+
actionRingOff: r.action_ring_off
|
|
599
|
+
};
|
|
600
|
+
_t(h, T), l > 0 && new Uint8Array(u, d, l).fill(0);
|
|
601
|
+
for (let A = 0; A < j.length; A++) {
|
|
602
|
+
const C = j[A], H = r[C.headerOff];
|
|
603
|
+
H !== 0 && C.init(h, H, n);
|
|
604
|
+
}
|
|
605
|
+
c !== 0 && zt(h, c, a);
|
|
606
|
+
for (let A = 0; A < o.length; A++)
|
|
607
|
+
o[A].init(h, a[A].byteOffset);
|
|
608
|
+
pt(h, f, _);
|
|
609
|
+
const x = Zt(u, _);
|
|
610
|
+
return {
|
|
611
|
+
buffer: u,
|
|
612
|
+
view: h,
|
|
613
|
+
header: T,
|
|
614
|
+
archetypes: x,
|
|
615
|
+
_regionBytes: y,
|
|
616
|
+
_allocator: t,
|
|
617
|
+
// Carry the headroom policy with the store so the realloc slow path
|
|
618
|
+
// (`optionsFromOld`) can re-reserve the same margin (#541).
|
|
619
|
+
_reservedDescriptorBytes: n.reservedDescriptorBytes ?? 0
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
function Zt(e, t) {
|
|
623
|
+
const n = /* @__PURE__ */ new Map();
|
|
624
|
+
for (let r = 0; r < t.length; r++) {
|
|
625
|
+
const s = t[r], o = new Array(s.columns.length), i = /* @__PURE__ */ new Map();
|
|
626
|
+
for (let c = 0; c < s.columns.length; c++) {
|
|
627
|
+
const a = s.columns[c], l = {
|
|
628
|
+
componentId: a.componentId,
|
|
629
|
+
fieldId: a.fieldId,
|
|
630
|
+
typeTag: a.typeTag,
|
|
631
|
+
byteOff: a.byteOff,
|
|
632
|
+
stride: a.stride,
|
|
633
|
+
view: jt(e, a.typeTag, a.byteOff, s.rowCapacity)
|
|
634
|
+
};
|
|
635
|
+
o[c] = l, i.set(Kt(a.componentId, a.fieldId), l);
|
|
636
|
+
}
|
|
637
|
+
n.set(s.archetypeId, {
|
|
638
|
+
archetypeId: s.archetypeId,
|
|
639
|
+
componentMask: s.componentMask,
|
|
640
|
+
rowCapacity: s.rowCapacity,
|
|
641
|
+
columns: i,
|
|
642
|
+
columnsInOrder: o
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
return n;
|
|
646
|
+
}
|
|
647
|
+
const Jt = 2166136261, qe = 16777619;
|
|
648
|
+
function ae(e, t) {
|
|
649
|
+
return e = (e ^ t & 255) >>> 0, Math.imul(e, qe) >>> 0;
|
|
650
|
+
}
|
|
651
|
+
function Kn(e, t) {
|
|
652
|
+
return e = (e ^ t >>> 0) >>> 0, Math.imul(e, qe) >>> 0;
|
|
653
|
+
}
|
|
654
|
+
class jn {
|
|
655
|
+
/** entity index → field-value row (length = field count; `[]` for a tag). */
|
|
656
|
+
_data = new et();
|
|
657
|
+
fieldNames;
|
|
658
|
+
fieldTypes;
|
|
659
|
+
fieldIndex;
|
|
660
|
+
constructor(t, n) {
|
|
661
|
+
this.fieldNames = t, this.fieldTypes = n;
|
|
662
|
+
const r = /* @__PURE__ */ Object.create(null);
|
|
663
|
+
for (let s = 0; s < t.length; s++) r[t[s]] = s;
|
|
664
|
+
this.fieldIndex = r;
|
|
665
|
+
}
|
|
666
|
+
/** Number of entities holding this sparse component. */
|
|
667
|
+
get size() {
|
|
668
|
+
return this._data.size;
|
|
669
|
+
}
|
|
670
|
+
/** Live entity indices that hold this component (dense, iteration order is
|
|
671
|
+
* SparseMap insertion/swap order — NOT canonical). Used by the hot query
|
|
672
|
+
* integration path (#469); for the determinism surface use
|
|
673
|
+
* `canonicalIndices` instead. */
|
|
674
|
+
get indices() {
|
|
675
|
+
return this._data.keys;
|
|
676
|
+
}
|
|
677
|
+
/** Live entity indices in **canonical** (ascending) order — the determinism
|
|
678
|
+
* ordering for `stateHash` + snapshot/restore (ADR-0011, #470). The native
|
|
679
|
+
* `indices` getter is insertion/swap order and would make two worlds with
|
|
680
|
+
* identical contents reached by different add/remove histories diverge, so
|
|
681
|
+
* the cold determinism paths sort here. Allocates a sorted copy each call;
|
|
682
|
+
* never call it on the hot query path. Indices are 20-bit entity indices,
|
|
683
|
+
* so the subtraction comparator can't overflow. */
|
|
684
|
+
canonicalIndices() {
|
|
685
|
+
return this._data.keys.slice().sort((t, n) => t - n);
|
|
686
|
+
}
|
|
687
|
+
/** The field-value row for `index` (length = field count; `[]` for a tag),
|
|
688
|
+
* or `undefined` if `index` isn't a member. Read-only view for the
|
|
689
|
+
* determinism paths (`stateHash`, snapshot); mutate via `setField`. */
|
|
690
|
+
getRow(t) {
|
|
691
|
+
return this._data.get(t);
|
|
692
|
+
}
|
|
693
|
+
/** Drop all membership + data. Restore path only — `restoreSparseStores`
|
|
694
|
+
* repopulates a cleared store from snapshot bytes. */
|
|
695
|
+
clear() {
|
|
696
|
+
this._data.clear();
|
|
697
|
+
}
|
|
698
|
+
/** Insert the positional field-value `row` for `index`, taking ownership of
|
|
699
|
+
* the array. Restore path only; bypasses the name→index mapping `setRow`
|
|
700
|
+
* does, because snapshot bytes are already positional. */
|
|
701
|
+
setRawRow(t, n) {
|
|
702
|
+
this._data.set(t, n);
|
|
703
|
+
}
|
|
704
|
+
has(t) {
|
|
705
|
+
return this._data.has(t);
|
|
706
|
+
}
|
|
707
|
+
/** Insert or overwrite the row for `index`, building it from `values`.
|
|
708
|
+
* Fields absent from `values` default to 0; a tag stores `[]`. */
|
|
709
|
+
setRow(t, n) {
|
|
710
|
+
const r = this.fieldNames, s = new Array(r.length);
|
|
711
|
+
for (let o = 0; o < r.length; o++) {
|
|
712
|
+
const i = n[r[o]];
|
|
713
|
+
s[o] = i === void 0 ? 0 : i;
|
|
714
|
+
}
|
|
715
|
+
this._data.set(t, s);
|
|
716
|
+
}
|
|
717
|
+
/** Drop `index`'s membership + data. Returns whether it was present. */
|
|
718
|
+
remove(t) {
|
|
719
|
+
return this._data.delete(t);
|
|
720
|
+
}
|
|
721
|
+
/** Read one field, or `undefined` if `index` doesn't hold this component. */
|
|
722
|
+
getField(t, n) {
|
|
723
|
+
const r = this._data.get(t);
|
|
724
|
+
return r === void 0 ? void 0 : r[n];
|
|
725
|
+
}
|
|
726
|
+
/** Write one field. Returns `false` (no-op) if `index` isn't a member. */
|
|
727
|
+
setField(t, n, r) {
|
|
728
|
+
const s = this._data.get(t);
|
|
729
|
+
return s === void 0 ? !1 : (s[n] = r, !0);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
class p extends Error {
|
|
733
|
+
constructor(t) {
|
|
734
|
+
super(t), this.name = "SparseRestoreError";
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
const Te = 12, Ae = 4, G = 8;
|
|
738
|
+
function Ie(e, t) {
|
|
739
|
+
let n = Jt;
|
|
740
|
+
const r = (s) => {
|
|
741
|
+
for (let o = 0; o < s.length; o++) n = ae(n, s.charCodeAt(o));
|
|
742
|
+
};
|
|
743
|
+
for (let s = 0; s < e.length; s++)
|
|
744
|
+
r(e[s]), n = ae(n, 31), r(t[s]), n = ae(n, 30);
|
|
745
|
+
return n >>> 0;
|
|
746
|
+
}
|
|
747
|
+
function Qn(e) {
|
|
748
|
+
let t = 4;
|
|
749
|
+
for (let o = 0; o < e.length; o++) {
|
|
750
|
+
const i = e[o], c = i.fieldNames.length;
|
|
751
|
+
t += Te + i.size * (Ae + c * G);
|
|
752
|
+
}
|
|
753
|
+
const n = new Uint8Array(t), r = new DataView(n.buffer);
|
|
754
|
+
let s = 0;
|
|
755
|
+
r.setUint32(s, e.length, !0), s += 4;
|
|
756
|
+
for (let o = 0; o < e.length; o++) {
|
|
757
|
+
const i = e[o], c = i.fieldNames.length, a = i.canonicalIndices();
|
|
758
|
+
r.setUint32(s, c, !0), s += 4, r.setUint32(s, Ie(i.fieldNames, i.fieldTypes), !0), s += 4, r.setUint32(s, a.length, !0), s += 4;
|
|
759
|
+
for (let l = 0; l < a.length; l++) {
|
|
760
|
+
const d = a[l];
|
|
761
|
+
r.setUint32(s, d, !0), s += 4;
|
|
762
|
+
const f = i.getRow(d);
|
|
763
|
+
for (let _ = 0; _ < c; _++)
|
|
764
|
+
r.setFloat64(s, f[_], !0), s += G;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
return n;
|
|
768
|
+
}
|
|
769
|
+
function Zn(e, t) {
|
|
770
|
+
const n = new DataView(t.buffer, t.byteOffset, t.byteLength), r = t.byteLength;
|
|
771
|
+
let s = 0;
|
|
772
|
+
const o = (c) => {
|
|
773
|
+
if (s + c > r)
|
|
774
|
+
throw new p(
|
|
775
|
+
`sparse snapshot truncated: need ${c} more bytes at offset ${s}, have ${r - s}`
|
|
776
|
+
);
|
|
777
|
+
};
|
|
778
|
+
o(4);
|
|
779
|
+
const i = n.getUint32(s, !0);
|
|
780
|
+
if (s += 4, i !== e.length)
|
|
781
|
+
throw new p(
|
|
782
|
+
`sparse store count mismatch: snapshot=${i}, registered=${e.length}`
|
|
783
|
+
);
|
|
784
|
+
for (let c = 0; c < e.length; c++) {
|
|
785
|
+
const a = e[c];
|
|
786
|
+
o(Te);
|
|
787
|
+
const l = n.getUint32(s, !0);
|
|
788
|
+
s += 4;
|
|
789
|
+
const d = n.getUint32(s, !0);
|
|
790
|
+
s += 4;
|
|
791
|
+
const f = n.getUint32(s, !0);
|
|
792
|
+
if (s += 4, l !== a.fieldNames.length)
|
|
793
|
+
throw new p(
|
|
794
|
+
`sparse store ${c} field-count mismatch: snapshot=${l}, registered=${a.fieldNames.length}`
|
|
795
|
+
);
|
|
796
|
+
const _ = Ie(a.fieldNames, a.fieldTypes);
|
|
797
|
+
if (d !== _)
|
|
798
|
+
throw new p(
|
|
799
|
+
`sparse store ${c} schema identity mismatch: snapshot hash=${d}, registered=${_} (same field count, different field names/types — likely a registration-order divergence between the snapshot and restore worlds)`
|
|
800
|
+
);
|
|
801
|
+
a.clear();
|
|
802
|
+
for (let g = 0; g < f; g++) {
|
|
803
|
+
o(Ae + l * G);
|
|
804
|
+
const y = n.getUint32(s, !0);
|
|
805
|
+
if (s += 4, y > P)
|
|
806
|
+
throw new p(
|
|
807
|
+
`sparse store ${c} member ${g} entity index ${y} exceeds MAX_INDEX (${P})`
|
|
808
|
+
);
|
|
809
|
+
const u = new Array(l);
|
|
810
|
+
for (let h = 0; h < l; h++)
|
|
811
|
+
u[h] = n.getFloat64(s, !0), s += G;
|
|
812
|
+
a.setRawRow(y, u);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
if (s !== r)
|
|
816
|
+
throw new p(
|
|
817
|
+
`sparse snapshot has ${r - s} trailing bytes after the last store (not a canonical encoding)`
|
|
818
|
+
);
|
|
819
|
+
}
|
|
820
|
+
function Jn(e, t) {
|
|
821
|
+
const n = new DataView(t.buffer, t.byteOffset, t.byteLength), r = t.byteLength;
|
|
822
|
+
let s = 0;
|
|
823
|
+
const o = (c) => {
|
|
824
|
+
if (s + c > r)
|
|
825
|
+
throw new p(
|
|
826
|
+
`sparse snapshot truncated: need ${c} more bytes at offset ${s}, have ${r - s}`
|
|
827
|
+
);
|
|
828
|
+
};
|
|
829
|
+
o(4);
|
|
830
|
+
const i = n.getUint32(s, !0);
|
|
831
|
+
if (s += 4, i !== e.length)
|
|
832
|
+
throw new p(
|
|
833
|
+
`sparse store count mismatch: snapshot=${i}, registered=${e.length}`
|
|
834
|
+
);
|
|
835
|
+
for (let c = 0; c < e.length; c++) {
|
|
836
|
+
const a = e[c];
|
|
837
|
+
o(Te);
|
|
838
|
+
const l = n.getUint32(s, !0);
|
|
839
|
+
s += 4;
|
|
840
|
+
const d = n.getUint32(s, !0);
|
|
841
|
+
s += 4;
|
|
842
|
+
const f = n.getUint32(s, !0);
|
|
843
|
+
if (s += 4, l !== a.fieldNames.length)
|
|
844
|
+
throw new p(
|
|
845
|
+
`sparse store ${c} field-count mismatch: snapshot=${l}, registered=${a.fieldNames.length}`
|
|
846
|
+
);
|
|
847
|
+
const _ = Ie(a.fieldNames, a.fieldTypes);
|
|
848
|
+
if (d !== _)
|
|
849
|
+
throw new p(
|
|
850
|
+
`sparse store ${c} schema identity mismatch: snapshot hash=${d}, registered=${_} (same field count, different field names/types — likely a registration-order divergence between the snapshot and restore worlds)`
|
|
851
|
+
);
|
|
852
|
+
for (let g = 0; g < f; g++) {
|
|
853
|
+
o(Ae + l * G);
|
|
854
|
+
const y = n.getUint32(s, !0);
|
|
855
|
+
if (s += 4, y > P)
|
|
856
|
+
throw new p(
|
|
857
|
+
`sparse store ${c} member ${g} entity index ${y} exceeds MAX_INDEX (${P})`
|
|
858
|
+
);
|
|
859
|
+
s += l * G;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
if (s !== r)
|
|
863
|
+
throw new p(
|
|
864
|
+
`sparse snapshot has ${r - s} trailing bytes after the last store (not a canonical encoding)`
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
const Ue = 2147483647, es = "orphan", en = "target", tn = Object.freeze({});
|
|
868
|
+
class Ke {
|
|
869
|
+
/** `true` → one target per source (target in the sparse field); `false` →
|
|
870
|
+
* a set of targets per source. The cardinality discriminant survives as a
|
|
871
|
+
* field because it is part of the snapshot header and the traversal/`targetOf`
|
|
872
|
+
* mode guards — but the forward *mechanics* are virtual, not branched on it. */
|
|
873
|
+
exclusive;
|
|
874
|
+
/** Backing sparse component def: `{ target: f64 }` when exclusive, a tag when
|
|
875
|
+
* multi. Carries membership (and the target, when exclusive). */
|
|
876
|
+
sparse;
|
|
877
|
+
/** Cleanup policy applied to this relation's sources when a target is
|
|
878
|
+
* destroyed (#473). `orphan` (the default) is a no-op — the link dangles
|
|
879
|
+
* safely. `Store` reads this at destroy-flush off `sourcesOf`. */
|
|
880
|
+
onDeleteTarget;
|
|
881
|
+
/** The backing sparse store instance. Owned for registration/liveness by
|
|
882
|
+
* `Store`, but the relation drives the forward/membership rows on it directly
|
|
883
|
+
* — that is the cardinality interaction this class now encapsulates (#498). */
|
|
884
|
+
_store;
|
|
885
|
+
/** target `EntityID` → set of source `EntityID`s. Keyed by the full id, not
|
|
886
|
+
* the index, so a recycled target slot can't alias a dead target's sources.
|
|
887
|
+
* An entry is dropped the moment its set empties (`unlinkReverse`). */
|
|
888
|
+
_reverse = /* @__PURE__ */ new Map();
|
|
889
|
+
constructor(t, n, r, s) {
|
|
890
|
+
this.exclusive = t, this.sparse = n, this._store = r, this.onDeleteTarget = s;
|
|
891
|
+
}
|
|
892
|
+
// --- shared reverse index (cardinality-agnostic) ---
|
|
893
|
+
/** Record that `src` points at `tgt` in the reverse index. */
|
|
894
|
+
linkReverse(t, n) {
|
|
895
|
+
let r = this._reverse.get(t);
|
|
896
|
+
r === void 0 && (r = /* @__PURE__ */ new Set(), this._reverse.set(t, r)), r.add(n);
|
|
897
|
+
}
|
|
898
|
+
/** Drop the `src → tgt` edge from the reverse index, removing the target's
|
|
899
|
+
* entry entirely once its last source is gone (so a dead-target key doesn't
|
|
900
|
+
* linger with an empty set). */
|
|
901
|
+
unlinkReverse(t, n) {
|
|
902
|
+
const r = this._reverse.get(t);
|
|
903
|
+
r !== void 0 && (r.delete(n), r.size === 0 && this._reverse.delete(t));
|
|
904
|
+
}
|
|
905
|
+
/** Drop every reverse-index entry whose **target** is no longer alive,
|
|
906
|
+
* returning the count dropped (#491). The `orphan` policy intentionally
|
|
907
|
+
* leaves a destroyed target's reverse entry intact (the link dangles
|
|
908
|
+
* safely), so a long-lived source that orphan-points at a stream of
|
|
909
|
+
* short-lived targets and never re-targets/dies accumulates dead-target keys
|
|
910
|
+
* without bound. This is the reclaim primitive behind `Store.compactRelations`
|
|
911
|
+
* — a cold path the host calls at scene/snapshot boundaries. It is
|
|
912
|
+
* cardinality-free (reverse-index only), so it lives on the base unchanged.
|
|
913
|
+
*
|
|
914
|
+
* Pure index reclaim: the **forward** links (the exclusive sparse target
|
|
915
|
+
* field, the multi forward set) are left untouched, so `targetOf` /
|
|
916
|
+
* `targetsOf` still return the dangling dead handle exactly as `orphan`
|
|
917
|
+
* promises. The reverse index is derived, so dropping a dead-target entry
|
|
918
|
+
* changes nothing observable except `sourcesOf` on that dead handle (which
|
|
919
|
+
* goes from the dangling sources to `[]` — meaningless either way, the target
|
|
920
|
+
* is gone) and is faithfully rebuilt by snapshot/restore from the surviving
|
|
921
|
+
* forward links. Only the **target** role can leak here: a destroyed *source*
|
|
922
|
+
* is already unlinked from every reverse set by `purgeSource`, so a live
|
|
923
|
+
* target's set never holds a dead source. `isAlive` is supplied by `Store`,
|
|
924
|
+
* which owns entity liveness. Deleting during `Map` key iteration is
|
|
925
|
+
* well-defined — already-visited and not-yet-reached keys are unaffected. */
|
|
926
|
+
pruneDeadReverse(t) {
|
|
927
|
+
let n = 0;
|
|
928
|
+
for (const r of this._reverse.keys())
|
|
929
|
+
t(r) || (this._reverse.delete(r), n++);
|
|
930
|
+
return n;
|
|
931
|
+
}
|
|
932
|
+
/** Sources that point at `tgt`, ascending by id (deterministic, cold-path
|
|
933
|
+
* sort) — empty when none. */
|
|
934
|
+
sourcesOf(t) {
|
|
935
|
+
const n = this._reverse.get(t);
|
|
936
|
+
if (n === void 0 || n.size === 0) return [];
|
|
937
|
+
const r = new Array(n.size);
|
|
938
|
+
let s = 0;
|
|
939
|
+
return n.forEach((o) => {
|
|
940
|
+
r[s++] = o;
|
|
941
|
+
}), r.sort((o, i) => o - i), r;
|
|
942
|
+
}
|
|
943
|
+
/** Drop every derived side index — the reverse index and (for multi) the
|
|
944
|
+
* forward target sets. Restore path only (`restoreRelations`): the side
|
|
945
|
+
* indices are rebuilt from scratch, so they're cleared first to stay
|
|
946
|
+
* idempotent when restoring into a dirty world. The backing sparse store is
|
|
947
|
+
* cleared separately by `restoreSparseStores`. */
|
|
948
|
+
resetIndices() {
|
|
949
|
+
this._reverse.clear(), this._resetForward();
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
class nn extends Ke {
|
|
953
|
+
constructor(t, n, r) {
|
|
954
|
+
super(!0, t, n, r);
|
|
955
|
+
}
|
|
956
|
+
_resetForward() {
|
|
957
|
+
}
|
|
958
|
+
link(t, n) {
|
|
959
|
+
const r = k(t), s = this._store.getField(r, 0);
|
|
960
|
+
if (s !== void 0) {
|
|
961
|
+
if (s === n) return;
|
|
962
|
+
this.unlinkReverse(s, t);
|
|
963
|
+
}
|
|
964
|
+
this._store.setRow(r, { [en]: n }), this.linkReverse(n, t);
|
|
965
|
+
}
|
|
966
|
+
unlink(t, n) {
|
|
967
|
+
const r = k(t), s = this._store.getField(r, 0);
|
|
968
|
+
s !== void 0 && (n !== void 0 && s !== n || (this.unlinkReverse(s, t), this._store.remove(r)));
|
|
969
|
+
}
|
|
970
|
+
purgeSource(t) {
|
|
971
|
+
const n = k(t), r = this._store.getField(n, 0);
|
|
972
|
+
r !== void 0 && this.unlinkReverse(r, t);
|
|
973
|
+
}
|
|
974
|
+
singleTarget(t) {
|
|
975
|
+
const n = this._store.getField(t, 0);
|
|
976
|
+
return n === void 0 ? void 0 : n;
|
|
977
|
+
}
|
|
978
|
+
targetsOf(t) {
|
|
979
|
+
const n = this._store.getField(t, 0);
|
|
980
|
+
return n === void 0 ? [] : [n];
|
|
981
|
+
}
|
|
982
|
+
has(t) {
|
|
983
|
+
return this._store.has(t);
|
|
984
|
+
}
|
|
985
|
+
forEachCanonicalTargetSet(t) {
|
|
986
|
+
}
|
|
987
|
+
forEachCanonicalPair(t, n) {
|
|
988
|
+
const r = this._store.canonicalIndices();
|
|
989
|
+
for (let s = 0; s < r.length; s++) {
|
|
990
|
+
const o = r[s];
|
|
991
|
+
n(t(o), this._store.getField(o, 0));
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
rebuildReverseFromForward(t) {
|
|
995
|
+
const n = this._store.indices;
|
|
996
|
+
for (let r = 0; r < n.length; r++) {
|
|
997
|
+
const s = n[r];
|
|
998
|
+
this.linkReverse(this._store.getField(s, 0), t(s));
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
restoreAddTarget() {
|
|
1002
|
+
throw new p(
|
|
1003
|
+
"exclusive relation has no multi forward sources to restore (snapshot header should have guarded this)"
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
class sn extends Ke {
|
|
1008
|
+
/** source entity **index** → set of target `EntityID`s. Keyed by source index
|
|
1009
|
+
* so destroy-purge — which has the freed index — can drop it in O(1). An
|
|
1010
|
+
* entry is removed the moment its set empties. */
|
|
1011
|
+
_forward = /* @__PURE__ */ new Map();
|
|
1012
|
+
constructor(t, n, r) {
|
|
1013
|
+
super(!1, t, n, r);
|
|
1014
|
+
}
|
|
1015
|
+
_resetForward() {
|
|
1016
|
+
this._forward.clear();
|
|
1017
|
+
}
|
|
1018
|
+
link(t, n) {
|
|
1019
|
+
const r = k(t);
|
|
1020
|
+
let s = this._forward.get(r);
|
|
1021
|
+
s === void 0 && (s = /* @__PURE__ */ new Set(), this._forward.set(r, s), this._store.setRow(r, tn)), s.add(n), this.linkReverse(n, t);
|
|
1022
|
+
}
|
|
1023
|
+
unlink(t, n) {
|
|
1024
|
+
const r = k(t), s = this._forward.get(r);
|
|
1025
|
+
if (s !== void 0) {
|
|
1026
|
+
if (n === void 0) {
|
|
1027
|
+
this._forward.delete(r), s.forEach((o) => this.unlinkReverse(o, t)), this._store.remove(r);
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
s.has(n) && (s.delete(n), this.unlinkReverse(n, t), s.size === 0 && (this._forward.delete(r), this._store.remove(r)));
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
purgeSource(t) {
|
|
1034
|
+
const n = k(t), r = this._forward.get(n);
|
|
1035
|
+
r !== void 0 && (this._forward.delete(n), r.forEach((s) => this.unlinkReverse(s, t)));
|
|
1036
|
+
}
|
|
1037
|
+
singleTarget() {
|
|
1038
|
+
}
|
|
1039
|
+
targetsOf(t) {
|
|
1040
|
+
const n = this._forward.get(t);
|
|
1041
|
+
if (n === void 0 || n.size === 0) return [];
|
|
1042
|
+
const r = new Array(n.size);
|
|
1043
|
+
let s = 0;
|
|
1044
|
+
return n.forEach((o) => {
|
|
1045
|
+
r[s++] = o;
|
|
1046
|
+
}), r.sort((o, i) => o - i), r;
|
|
1047
|
+
}
|
|
1048
|
+
has(t) {
|
|
1049
|
+
return this._store.has(t);
|
|
1050
|
+
}
|
|
1051
|
+
forEachCanonicalTargetSet(t) {
|
|
1052
|
+
const n = Array.from(this._forward.keys()).sort((r, s) => r - s);
|
|
1053
|
+
for (let r = 0; r < n.length; r++) {
|
|
1054
|
+
const s = this.targetsOf(n[r]);
|
|
1055
|
+
s.length !== 0 && t(n[r], s);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
forEachCanonicalPair(t, n) {
|
|
1059
|
+
this.forEachCanonicalTargetSet((r, s) => {
|
|
1060
|
+
const o = t(r);
|
|
1061
|
+
for (let i = 0; i < s.length; i++) n(o, s[i]);
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
rebuildReverseFromForward() {
|
|
1065
|
+
}
|
|
1066
|
+
restoreAddTarget(t, n, r) {
|
|
1067
|
+
let s = this._forward.get(t);
|
|
1068
|
+
s === void 0 && (s = /* @__PURE__ */ new Set(), this._forward.set(t, s)), s.add(n), this.linkReverse(n, r);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
function ts(e, t, n, r) {
|
|
1072
|
+
return e ? new nn(t, n, r) : new sn(t, n, r);
|
|
1073
|
+
}
|
|
1074
|
+
const je = 4, Qe = 4, Ze = 8, te = 8;
|
|
1075
|
+
function ns(e) {
|
|
1076
|
+
const t = new Array(e.length);
|
|
1077
|
+
let n = 4;
|
|
1078
|
+
for (let i = 0; i < e.length; i++) {
|
|
1079
|
+
n += je;
|
|
1080
|
+
const c = e[i];
|
|
1081
|
+
if (c.exclusive) {
|
|
1082
|
+
t[i] = null;
|
|
1083
|
+
continue;
|
|
1084
|
+
}
|
|
1085
|
+
const a = [];
|
|
1086
|
+
c.forEachCanonicalTargetSet((l, d) => a.push([l, d])), t[i] = a, n += Qe;
|
|
1087
|
+
for (let l = 0; l < a.length; l++)
|
|
1088
|
+
n += Ze + a[l][1].length * te;
|
|
1089
|
+
}
|
|
1090
|
+
const r = new Uint8Array(n), s = new DataView(r.buffer);
|
|
1091
|
+
let o = 0;
|
|
1092
|
+
s.setUint32(o, e.length, !0), o += 4;
|
|
1093
|
+
for (let i = 0; i < e.length; i++) {
|
|
1094
|
+
s.setUint32(o, e[i].exclusive ? 0 : 1, !0), o += 4;
|
|
1095
|
+
const c = t[i];
|
|
1096
|
+
if (c !== null) {
|
|
1097
|
+
s.setUint32(o, c.length, !0), o += 4;
|
|
1098
|
+
for (let a = 0; a < c.length; a++) {
|
|
1099
|
+
const l = c[a][0], d = c[a][1];
|
|
1100
|
+
s.setUint32(o, l, !0), o += 4, s.setUint32(o, d.length, !0), o += 4;
|
|
1101
|
+
for (let f = 0; f < d.length; f++)
|
|
1102
|
+
s.setFloat64(o, d[f], !0), o += te;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
return r;
|
|
1107
|
+
}
|
|
1108
|
+
function ss(e, t, n) {
|
|
1109
|
+
const r = new DataView(t.buffer, t.byteOffset, t.byteLength), s = t.byteLength;
|
|
1110
|
+
let o = 0;
|
|
1111
|
+
const i = (a) => {
|
|
1112
|
+
if (o + a > s)
|
|
1113
|
+
throw new p(
|
|
1114
|
+
`relation snapshot truncated: need ${a} more bytes at offset ${o}, have ${s - o}`
|
|
1115
|
+
);
|
|
1116
|
+
};
|
|
1117
|
+
for (let a = 0; a < e.length; a++) e[a].resetIndices();
|
|
1118
|
+
i(4);
|
|
1119
|
+
const c = r.getUint32(o, !0);
|
|
1120
|
+
if (o += 4, c !== e.length)
|
|
1121
|
+
throw new p(
|
|
1122
|
+
`relation count mismatch: snapshot=${c}, registered=${e.length}`
|
|
1123
|
+
);
|
|
1124
|
+
for (let a = 0; a < e.length; a++) {
|
|
1125
|
+
const l = e[a];
|
|
1126
|
+
i(je);
|
|
1127
|
+
const d = r.getUint32(o, !0);
|
|
1128
|
+
if (o += 4, d === 1 === l.exclusive)
|
|
1129
|
+
throw new p(
|
|
1130
|
+
`relation ${a} cardinality mismatch: snapshot ${d ? "multi" : "exclusive"}, registered ${l.exclusive ? "exclusive" : "multi"}`
|
|
1131
|
+
);
|
|
1132
|
+
if (l.exclusive) continue;
|
|
1133
|
+
i(Qe);
|
|
1134
|
+
const f = r.getUint32(o, !0);
|
|
1135
|
+
o += 4;
|
|
1136
|
+
for (let _ = 0; _ < f; _++) {
|
|
1137
|
+
i(Ze);
|
|
1138
|
+
const g = r.getUint32(o, !0);
|
|
1139
|
+
o += 4;
|
|
1140
|
+
const y = r.getUint32(o, !0);
|
|
1141
|
+
if (o += 4, g > P)
|
|
1142
|
+
throw new p(
|
|
1143
|
+
`relation ${a} source index ${g} exceeds MAX_INDEX (${P})`
|
|
1144
|
+
);
|
|
1145
|
+
i(y * te);
|
|
1146
|
+
const u = n(g);
|
|
1147
|
+
for (let h = 0; h < y; h++) {
|
|
1148
|
+
const T = r.getFloat64(o, !0);
|
|
1149
|
+
o += te;
|
|
1150
|
+
const x = T;
|
|
1151
|
+
if (!Number.isInteger(x) || x < 0 || x > Se)
|
|
1152
|
+
throw new p(
|
|
1153
|
+
`relation ${a} target ${x} is not a well-formed packed EntityID (expected an integer in [0, ${Se}])`
|
|
1154
|
+
);
|
|
1155
|
+
l.restoreAddTarget(g, T, u);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
if (o !== s)
|
|
1160
|
+
throw new p(
|
|
1161
|
+
`relation snapshot has ${s - o} trailing bytes after the last relation (not a canonical encoding)`
|
|
1162
|
+
);
|
|
1163
|
+
}
|
|
1164
|
+
const ve = /* @__PURE__ */ new WeakMap();
|
|
1165
|
+
function rn(e) {
|
|
1166
|
+
const t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), c = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set();
|
|
1167
|
+
for (let u = 0; u < e.writes.length; u++) {
|
|
1168
|
+
const h = e.writes[u].id;
|
|
1169
|
+
n.add(h), t.add(h), r.add(h);
|
|
1170
|
+
}
|
|
1171
|
+
for (let u = 0; u < e.reads.length; u++)
|
|
1172
|
+
t.add(e.reads[u].id);
|
|
1173
|
+
for (let u = 0; u < e.spawns.length; u++) {
|
|
1174
|
+
const h = e.spawns[u];
|
|
1175
|
+
for (let T = 0; T < h.length; T++)
|
|
1176
|
+
r.add(h[T].id);
|
|
1177
|
+
}
|
|
1178
|
+
for (let u = 0; u < e.transitions.length; u++) {
|
|
1179
|
+
const h = e.transitions[u];
|
|
1180
|
+
if (h.add)
|
|
1181
|
+
for (let T = 0; T < h.add.length; T++)
|
|
1182
|
+
r.add(h.add[T].id);
|
|
1183
|
+
if (h.remove)
|
|
1184
|
+
for (let T = 0; T < h.remove.length; T++)
|
|
1185
|
+
s.add(h.remove[T].id);
|
|
1186
|
+
}
|
|
1187
|
+
for (let u = 0; u < e.despawns.length; u++)
|
|
1188
|
+
s.add(e.despawns[u].id);
|
|
1189
|
+
for (let u = 0; u < e.resourceReads.length; u++)
|
|
1190
|
+
o.add(e.resourceReads[u]);
|
|
1191
|
+
for (let u = 0; u < e.resourceWrites.length; u++) {
|
|
1192
|
+
const h = e.resourceWrites[u];
|
|
1193
|
+
i.add(h), o.add(h);
|
|
1194
|
+
}
|
|
1195
|
+
const f = e.sparseWrites;
|
|
1196
|
+
if (f !== void 0)
|
|
1197
|
+
for (let u = 0; u < f.length; u++) {
|
|
1198
|
+
const h = f[u];
|
|
1199
|
+
a.add(h), c.add(h);
|
|
1200
|
+
}
|
|
1201
|
+
const _ = e.sparseReads;
|
|
1202
|
+
if (_ !== void 0)
|
|
1203
|
+
for (let u = 0; u < _.length; u++) c.add(_[u]);
|
|
1204
|
+
const g = e.relationWrites;
|
|
1205
|
+
if (g !== void 0)
|
|
1206
|
+
for (let u = 0; u < g.length; u++) {
|
|
1207
|
+
const h = g[u];
|
|
1208
|
+
d.add(h), l.add(h);
|
|
1209
|
+
}
|
|
1210
|
+
const y = e.relationReads;
|
|
1211
|
+
if (y !== void 0)
|
|
1212
|
+
for (let u = 0; u < y.length; u++)
|
|
1213
|
+
l.add(y[u]);
|
|
1214
|
+
return {
|
|
1215
|
+
reads: t,
|
|
1216
|
+
writes: n,
|
|
1217
|
+
addAllowed: r,
|
|
1218
|
+
removeAllowed: s,
|
|
1219
|
+
hasDespawns: e.despawns.length > 0,
|
|
1220
|
+
resourceReads: o,
|
|
1221
|
+
resourceWrites: i,
|
|
1222
|
+
sparseReads: c,
|
|
1223
|
+
sparseWrites: a,
|
|
1224
|
+
relationReads: l,
|
|
1225
|
+
relationWrites: d
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
function on(e) {
|
|
1229
|
+
const t = ve.get(e);
|
|
1230
|
+
if (t !== void 0) return t;
|
|
1231
|
+
const n = rn(e);
|
|
1232
|
+
return ve.set(e, n), n;
|
|
1233
|
+
}
|
|
1234
|
+
const Le = /* @__PURE__ */ new WeakMap();
|
|
1235
|
+
function an(e) {
|
|
1236
|
+
const t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set();
|
|
1237
|
+
if (e.reads !== void 0)
|
|
1238
|
+
for (let r = 0; r < e.reads.length; r++) t.add(e.reads[r].id);
|
|
1239
|
+
if (e.resourceReads !== void 0)
|
|
1240
|
+
for (let r = 0; r < e.resourceReads.length; r++)
|
|
1241
|
+
n.add(e.resourceReads[r]);
|
|
1242
|
+
return {
|
|
1243
|
+
reads: t,
|
|
1244
|
+
writes: /* @__PURE__ */ new Set(),
|
|
1245
|
+
addAllowed: /* @__PURE__ */ new Set(),
|
|
1246
|
+
removeAllowed: /* @__PURE__ */ new Set(),
|
|
1247
|
+
hasDespawns: !1,
|
|
1248
|
+
resourceReads: n,
|
|
1249
|
+
resourceWrites: /* @__PURE__ */ new Set(),
|
|
1250
|
+
sparseReads: /* @__PURE__ */ new Set(),
|
|
1251
|
+
sparseWrites: /* @__PURE__ */ new Set(),
|
|
1252
|
+
relationReads: /* @__PURE__ */ new Set(),
|
|
1253
|
+
relationWrites: /* @__PURE__ */ new Set()
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
function cn(e) {
|
|
1257
|
+
const t = Le.get(e);
|
|
1258
|
+
if (t !== void 0) return t;
|
|
1259
|
+
const n = an(e);
|
|
1260
|
+
return Le.set(e, n), n;
|
|
1261
|
+
}
|
|
1262
|
+
class dn {
|
|
1263
|
+
active = null;
|
|
1264
|
+
sets = null;
|
|
1265
|
+
// The label used in violation messages. Tracks `active` for a system span,
|
|
1266
|
+
// but a run-condition span (#576) has no descriptor — only this name — so the
|
|
1267
|
+
// failure helpers read the label here rather than off `active`.
|
|
1268
|
+
activeName = null;
|
|
1269
|
+
// An `exclusive` system (#681) has full world access: every check_* below
|
|
1270
|
+
// passes for the whole span. Kept as an explicit flag (rather than leaving
|
|
1271
|
+
// `sets` null) so `isActive()` stays truthful inside the span.
|
|
1272
|
+
exclusive = !1;
|
|
1273
|
+
enter(t) {
|
|
1274
|
+
this.active = t, this.activeName = t.name ?? `system_${t.id}`, this.exclusive = t.exclusive === !0, this.sets = this.exclusive ? null : on(t);
|
|
1275
|
+
}
|
|
1276
|
+
/** Open a reads-only span for a run condition (#576). No descriptor — a
|
|
1277
|
+
* condition can gate a whole SystemSet, so it isn't attributable to one
|
|
1278
|
+
* system — just its declared reads/resource_reads and a name for diagnostics.
|
|
1279
|
+
* Paired with `leave()`. */
|
|
1280
|
+
enterCondition(t) {
|
|
1281
|
+
this.active = null, this.activeName = t.name, this.sets = cn(t);
|
|
1282
|
+
}
|
|
1283
|
+
leave() {
|
|
1284
|
+
this.active = null, this.activeName = null, this.sets = null, this.exclusive = !1;
|
|
1285
|
+
}
|
|
1286
|
+
isActive() {
|
|
1287
|
+
return this.sets !== null || this.exclusive;
|
|
1288
|
+
}
|
|
1289
|
+
/** Current system descriptor, if any. Null during a run-condition span. */
|
|
1290
|
+
current() {
|
|
1291
|
+
return this.active;
|
|
1292
|
+
}
|
|
1293
|
+
checkRead(t) {
|
|
1294
|
+
this.sets !== null && (this.sets.reads.has(t.id) || this.failComponent("read", t, "reads"));
|
|
1295
|
+
}
|
|
1296
|
+
checkWrite(t) {
|
|
1297
|
+
this.sets !== null && (this.sets.writes.has(t.id) || this.failComponent("write", t, "writes"));
|
|
1298
|
+
}
|
|
1299
|
+
checkAdd(t) {
|
|
1300
|
+
this.sets !== null && (this.sets.addAllowed.has(t.id) || this.failComponent("addComponent", t, "spawns / transitions.add / writes"));
|
|
1301
|
+
}
|
|
1302
|
+
checkRemove(t) {
|
|
1303
|
+
this.sets !== null && (this.sets.removeAllowed.has(t.id) || this.failComponent("removeComponent", t, "despawns / transitions.remove"));
|
|
1304
|
+
}
|
|
1305
|
+
checkDestroy() {
|
|
1306
|
+
if (this.sets === null || this.sets.hasDespawns) return;
|
|
1307
|
+
const t = this.activeName;
|
|
1308
|
+
throw new S(
|
|
1309
|
+
w.ACCESS_UNDECLARED,
|
|
1310
|
+
`system '${t}' called despawn but didn't declare any despawns — declare the components this system removes via despawn in its 'despawns'`,
|
|
1311
|
+
{ system: t, op: "despawn" }
|
|
1312
|
+
);
|
|
1313
|
+
}
|
|
1314
|
+
checkResourceRead(t) {
|
|
1315
|
+
if (this.sets === null) return;
|
|
1316
|
+
const n = t;
|
|
1317
|
+
this.sets.resourceReads.has(n) || this.failResource("read", t, "resourceReads");
|
|
1318
|
+
}
|
|
1319
|
+
checkResourceWrite(t) {
|
|
1320
|
+
if (this.sets === null) return;
|
|
1321
|
+
const n = t;
|
|
1322
|
+
this.sets.resourceWrites.has(n) || this.failResource("write", t, "resourceWrites");
|
|
1323
|
+
}
|
|
1324
|
+
// --- Sparse component / relation checks (#496) ---
|
|
1325
|
+
// Keyed against the dedicated sparse/relation sets, NOT the dense
|
|
1326
|
+
// `reads`/`writes` sets — the id spaces are disjoint by construction (see
|
|
1327
|
+
// file header). `def as unknown as number` recovers the SparseComponentID /
|
|
1328
|
+
// RelationID the branded handle erases to at runtime.
|
|
1329
|
+
checkSparseRead(t) {
|
|
1330
|
+
if (this.sets === null) return;
|
|
1331
|
+
const n = t;
|
|
1332
|
+
this.sets.sparseReads.has(n) || this.failSparse("read", n, "sparseReads");
|
|
1333
|
+
}
|
|
1334
|
+
checkSparseWrite(t) {
|
|
1335
|
+
if (this.sets === null) return;
|
|
1336
|
+
const n = t;
|
|
1337
|
+
this.sets.sparseWrites.has(n) || this.failSparse("write", n, "sparseWrites");
|
|
1338
|
+
}
|
|
1339
|
+
checkRelationRead(t) {
|
|
1340
|
+
if (this.sets === null) return;
|
|
1341
|
+
const n = t;
|
|
1342
|
+
this.sets.relationReads.has(n) || this.failRelation("read", n, "relationReads");
|
|
1343
|
+
}
|
|
1344
|
+
checkRelationWrite(t) {
|
|
1345
|
+
if (this.sets === null) return;
|
|
1346
|
+
const n = t;
|
|
1347
|
+
this.sets.relationWrites.has(n) || this.failRelation("write", n, "relationWrites");
|
|
1348
|
+
}
|
|
1349
|
+
/** A `(*, T)` wildcard (`Query.forEachRelatedTo`, #579) reads every
|
|
1350
|
+
* relation's reverse index, so it can't name a specific relation — it is
|
|
1351
|
+
* authorised by the `ANY_RELATION` sentinel in `relationReads`. Honoured here
|
|
1352
|
+
* exactly like a per-relation read, just keyed on the reserved sentinel id
|
|
1353
|
+
* (which computeSets folds into `relationReads` like any other entry). */
|
|
1354
|
+
checkRelationReadAny() {
|
|
1355
|
+
this.sets !== null && (this.sets.relationReads.has(Ue) || this.failRelation(
|
|
1356
|
+
"(*, T) wildcard read",
|
|
1357
|
+
Ue,
|
|
1358
|
+
"relationReads (as ANY_RELATION)"
|
|
1359
|
+
));
|
|
1360
|
+
}
|
|
1361
|
+
// --- Optional query-term scope (#592) ---
|
|
1362
|
+
// `Query.forEach` and `ChangedQuery.forEach` push the iterating query's
|
|
1363
|
+
// `_optional` term list for the span of the callback;
|
|
1364
|
+
// `Archetype.getOptionalColumnRead` then verifies the fetched component was
|
|
1365
|
+
// declared via `.optional(T)` — the term that authorizes the optional fetch.
|
|
1366
|
+
// This is what makes the optional term *consumed* rather than decorative: like
|
|
1367
|
+
// `reads:[T]` for required access, `.optional(T)` is the fetch's declaration,
|
|
1368
|
+
// checked here in `DEV`. A stack (not a single slot) handles re-entrant /
|
|
1369
|
+
// nested `forEach`. The optional scope is independent of the per-system
|
|
1370
|
+
// `enter`/`leave` above — a host-side `ecs.query(...).forEach` outside any
|
|
1371
|
+
// system still establishes one. No active scope ⇒ lenient: a manual
|
|
1372
|
+
// `query.archetypes` walk can't be attributed to an optional declaration, so it
|
|
1373
|
+
// isn't checked — mirroring the unchecked outside-of-system calls in the header.
|
|
1374
|
+
//
|
|
1375
|
+
// CAVEAT (#594 Task 3): the gate always attributes to the INNERMOST active
|
|
1376
|
+
// `forEach`. If you nest `forEach` and call `getOptionalColumnRead` on an
|
|
1377
|
+
// OUTER query's archetype inside the inner loop, it is checked against the inner
|
|
1378
|
+
// query's terms (a false throw or false pass). Per-query attribution isn't worth
|
|
1379
|
+
// the complexity for a dev-only assertion; iterate one query at a time, or read
|
|
1380
|
+
// the outer span before entering the inner loop.
|
|
1381
|
+
optionalScopes = [];
|
|
1382
|
+
enterOptionalScope(t) {
|
|
1383
|
+
this.optionalScopes.push(t);
|
|
1384
|
+
}
|
|
1385
|
+
leaveOptionalScope() {
|
|
1386
|
+
this.optionalScopes.pop();
|
|
1387
|
+
}
|
|
1388
|
+
checkOptionalFetch(t) {
|
|
1389
|
+
const n = this.optionalScopes.length;
|
|
1390
|
+
if (n === 0) return;
|
|
1391
|
+
const r = this.optionalScopes[n - 1], s = t.id;
|
|
1392
|
+
for (let o = 0; o < r.length; o++)
|
|
1393
|
+
if (r[o] === s) return;
|
|
1394
|
+
throw new S(
|
|
1395
|
+
w.OPTIONAL_TERM_NOT_DECLARED,
|
|
1396
|
+
`getOptionalColumnRead fetched optional component ${s} but the iterating query didn't declare it — add .optional(component) to the query before fetching it`
|
|
1397
|
+
);
|
|
1398
|
+
}
|
|
1399
|
+
failComponent(t, n, r) {
|
|
1400
|
+
const s = this.activeName, o = dt(n);
|
|
1401
|
+
throw new S(
|
|
1402
|
+
w.ACCESS_UNDECLARED,
|
|
1403
|
+
`system '${s}' performed ${t} on ${o} but didn't declare it — add it to '${r}' (see docs/api/systems.md)`,
|
|
1404
|
+
{ system: s, op: t, component: n.id }
|
|
1405
|
+
);
|
|
1406
|
+
}
|
|
1407
|
+
failSparse(t, n, r) {
|
|
1408
|
+
const s = this.activeName;
|
|
1409
|
+
throw new S(
|
|
1410
|
+
w.ACCESS_UNDECLARED,
|
|
1411
|
+
`system '${s}' performed ${t} on sparse component ${n} but didn't declare it — add it to '${r}' (see docs/api/systems.md)`,
|
|
1412
|
+
{ system: s, op: t, sparse: n }
|
|
1413
|
+
);
|
|
1414
|
+
}
|
|
1415
|
+
failRelation(t, n, r) {
|
|
1416
|
+
const s = this.activeName;
|
|
1417
|
+
throw new S(
|
|
1418
|
+
w.ACCESS_UNDECLARED,
|
|
1419
|
+
`system '${s}' performed ${t} on relation ${n} but didn't declare it — add it to '${r}' (see docs/api/systems.md)`,
|
|
1420
|
+
{ system: s, op: t, relation: n }
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
failResource(t, n, r) {
|
|
1424
|
+
const s = this.activeName, o = n.description ?? "<unnamed>";
|
|
1425
|
+
throw new S(
|
|
1426
|
+
w.ACCESS_UNDECLARED,
|
|
1427
|
+
`system '${s}' performed resource ${t} on '${o}' but didn't declare it — add the resource key to '${r}' (see docs/api/systems.md)`,
|
|
1428
|
+
{ system: s, op: t, resource: o }
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
const rs = new dn();
|
|
1433
|
+
var $ = /* @__PURE__ */ ((e) => (e.PRE_STARTUP = "PRE_STARTUP", e.STARTUP = "STARTUP", e.POST_STARTUP = "POST_STARTUP", e.FIXED_UPDATE = "FIXED_UPDATE", e.PRE_UPDATE = "PRE_UPDATE", e.UPDATE = "UPDATE", e.POST_UPDATE = "POST_UPDATE", e))($ || {});
|
|
1434
|
+
const ce = [
|
|
1435
|
+
"PRE_STARTUP",
|
|
1436
|
+
"STARTUP",
|
|
1437
|
+
"POST_STARTUP"
|
|
1438
|
+
/* POST_STARTUP */
|
|
1439
|
+
], de = [
|
|
1440
|
+
"PRE_UPDATE",
|
|
1441
|
+
"UPDATE",
|
|
1442
|
+
"POST_UPDATE"
|
|
1443
|
+
/* POST_UPDATE */
|
|
1444
|
+
];
|
|
1445
|
+
function os(e) {
|
|
1446
|
+
return Object.freeze({ name: e });
|
|
1447
|
+
}
|
|
1448
|
+
function ln(e) {
|
|
1449
|
+
return !("fn" in e);
|
|
1450
|
+
}
|
|
1451
|
+
const W = Object.freeze([]);
|
|
1452
|
+
function le(e) {
|
|
1453
|
+
return e === void 0 ? W : Array.isArray(e) ? e : [e];
|
|
1454
|
+
}
|
|
1455
|
+
class is {
|
|
1456
|
+
labelSystems = /* @__PURE__ */ new Map();
|
|
1457
|
+
sortedCache = /* @__PURE__ */ new Map();
|
|
1458
|
+
systemIndex = /* @__PURE__ */ new Map();
|
|
1459
|
+
systemLastRun = /* @__PURE__ */ new Map();
|
|
1460
|
+
// Only systems carrying a run condition or set membership (#576). The hot
|
|
1461
|
+
// loop skips the per-system gate probe entirely when this is empty, so a
|
|
1462
|
+
// schedule that uses no conditions runs byte-for-byte the pre-#576 path.
|
|
1463
|
+
gatedSystems = /* @__PURE__ */ new Map();
|
|
1464
|
+
// Live set configuration, read at sort time (ordering) and run time
|
|
1465
|
+
// (conditions) so `configureSet` is order-independent w.r.t. `addSystems`.
|
|
1466
|
+
setConditions = /* @__PURE__ */ new Map();
|
|
1467
|
+
setOrdering = /* @__PURE__ */ new Map();
|
|
1468
|
+
nextInsertionOrder = 0;
|
|
1469
|
+
// The opt-in compute backend (#622), or null (the default — pure-TS). When
|
|
1470
|
+
// set, a scheduled system carrying a `backendHandle` runs `backend.run(...)`
|
|
1471
|
+
// instead of its `fn`. `null` is the byte-for-byte pre-#622 path: `runLabel`
|
|
1472
|
+
// hoists this to a local and only reads `desc.backendHandle` when non-null,
|
|
1473
|
+
// so a no-backend ECS never touches the routing field.
|
|
1474
|
+
_backend = null;
|
|
1475
|
+
/** Dev-diagnostic sink (`ECSOptions.onWarn`); defaults to `console.warn`.
|
|
1476
|
+
* The only schedule diagnostic today is `warnDroppedEdge`. */
|
|
1477
|
+
onWarn;
|
|
1478
|
+
constructor(t) {
|
|
1479
|
+
this.onWarn = t ?? ((n) => console.warn(n));
|
|
1480
|
+
for (let n = 0; n < ce.length; n++)
|
|
1481
|
+
this.labelSystems.set(ce[n], []);
|
|
1482
|
+
this.labelSystems.set("FIXED_UPDATE", []);
|
|
1483
|
+
for (let n = 0; n < de.length; n++)
|
|
1484
|
+
this.labelSystems.set(de[n], []);
|
|
1485
|
+
}
|
|
1486
|
+
addSystems(t, ...n) {
|
|
1487
|
+
for (const r of n) {
|
|
1488
|
+
const s = "system" in r, o = s ? r.system : r, i = s ? r.ordering : void 0, c = s ? le(r.runIf) : W, a = s ? le(r.set) : W, l = {
|
|
1489
|
+
descriptor: o,
|
|
1490
|
+
insertionOrder: this.nextInsertionOrder++,
|
|
1491
|
+
before: new Set(i?.before ?? []),
|
|
1492
|
+
after: new Set(i?.after ?? []),
|
|
1493
|
+
conditions: c,
|
|
1494
|
+
sets: a
|
|
1495
|
+
};
|
|
1496
|
+
this.labelSystems.get(t).push(l), this.systemIndex.set(o, t), this.systemLastRun.set(o, 0), (c.length > 0 || a.length > 0) && this.gatedSystems.set(o, l), this.sortedCache.delete(t);
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
/**
|
|
1500
|
+
* Configure a `SystemSet` (#576) — its shared run condition(s) and/or
|
|
1501
|
+
* ordering, inherited by every member. Additive and order-independent w.r.t.
|
|
1502
|
+
* `addSystems`: conditions accumulate (ANDed), ordering targets union, and
|
|
1503
|
+
* a member added before or after this call picks the configuration up.
|
|
1504
|
+
*/
|
|
1505
|
+
configureSet(t, n) {
|
|
1506
|
+
const r = le(n.runIf);
|
|
1507
|
+
if (r.length > 0) {
|
|
1508
|
+
const s = this.setConditions.get(t);
|
|
1509
|
+
s === void 0 ? this.setConditions.set(t, [...r]) : s.push(...r);
|
|
1510
|
+
}
|
|
1511
|
+
if (n.before !== void 0 || n.after !== void 0) {
|
|
1512
|
+
let s = this.setOrdering.get(t);
|
|
1513
|
+
s === void 0 && (s = { before: /* @__PURE__ */ new Set(), after: /* @__PURE__ */ new Set() }, this.setOrdering.set(t, s));
|
|
1514
|
+
for (const o of n.before ?? W) s.before.add(o);
|
|
1515
|
+
for (const o of n.after ?? W) s.after.add(o);
|
|
1516
|
+
this.sortedCache.clear();
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
removeSystem(t) {
|
|
1520
|
+
const n = this.systemIndex.get(t);
|
|
1521
|
+
if (n === void 0) return;
|
|
1522
|
+
const r = this.labelSystems.get(n), s = r.findIndex((o) => o.descriptor === t);
|
|
1523
|
+
if (s !== -1) {
|
|
1524
|
+
const o = r.length - 1;
|
|
1525
|
+
s !== o && (r[s] = r[o]), r.pop();
|
|
1526
|
+
for (const i of r)
|
|
1527
|
+
i.before.delete(t), i.after.delete(t);
|
|
1528
|
+
}
|
|
1529
|
+
this.systemIndex.delete(t), this.systemLastRun.delete(t), this.gatedSystems.delete(t), this.sortedCache.delete(n);
|
|
1530
|
+
}
|
|
1531
|
+
/** Attach (or, with `null`, detach) the opt-in compute backend (#622). Driven
|
|
1532
|
+
* by `ECS.attachBackend`; routes any scheduled system carrying a
|
|
1533
|
+
* `backendHandle` to `backend.run(handle)` in place of its `fn`. */
|
|
1534
|
+
setBackend(t) {
|
|
1535
|
+
this._backend = t;
|
|
1536
|
+
}
|
|
1537
|
+
runStartup(t, n) {
|
|
1538
|
+
for (const r of ce)
|
|
1539
|
+
this.runLabel(r, t, at, n);
|
|
1540
|
+
}
|
|
1541
|
+
runUpdate(t, n, r) {
|
|
1542
|
+
for (const s of de)
|
|
1543
|
+
this.runLabel(s, t, n, r);
|
|
1544
|
+
}
|
|
1545
|
+
runFixedUpdate(t, n, r) {
|
|
1546
|
+
this.runLabel("FIXED_UPDATE", t, n, r);
|
|
1547
|
+
}
|
|
1548
|
+
hasFixedSystems() {
|
|
1549
|
+
return this.labelSystems.get(
|
|
1550
|
+
"FIXED_UPDATE"
|
|
1551
|
+
/* FIXED_UPDATE */
|
|
1552
|
+
).length > 0;
|
|
1553
|
+
}
|
|
1554
|
+
getAllSystems() {
|
|
1555
|
+
const t = [];
|
|
1556
|
+
for (const n of this.labelSystems.values())
|
|
1557
|
+
for (const r of n)
|
|
1558
|
+
t.push(r.descriptor);
|
|
1559
|
+
return t;
|
|
1560
|
+
}
|
|
1561
|
+
hasSystem(t) {
|
|
1562
|
+
return this.systemIndex.has(t);
|
|
1563
|
+
}
|
|
1564
|
+
clear() {
|
|
1565
|
+
for (const t of this.labelSystems.values())
|
|
1566
|
+
t.length = 0;
|
|
1567
|
+
this.sortedCache.clear(), this.systemIndex.clear(), this.systemLastRun.clear(), this.gatedSystems.clear(), this.setConditions.clear(), this.setOrdering.clear();
|
|
1568
|
+
}
|
|
1569
|
+
runLabel(t, n, r, s) {
|
|
1570
|
+
const o = this.getSorted(t), i = this.gatedSystems.size > 0, c = this._backend, a = i ? /* @__PURE__ */ new Map() : void 0;
|
|
1571
|
+
for (let l = 0; l < o.length; l++) {
|
|
1572
|
+
const d = o[l];
|
|
1573
|
+
if (i) {
|
|
1574
|
+
const _ = this.gatedSystems.get(d);
|
|
1575
|
+
if (_ !== void 0 && !this.shouldRun(_, n, a)) continue;
|
|
1576
|
+
}
|
|
1577
|
+
n.lastRunTick = this.systemLastRun.get(d) ?? 0;
|
|
1578
|
+
const f = c !== null ? d.backendHandle : void 0;
|
|
1579
|
+
try {
|
|
1580
|
+
f !== void 0 ? c.run(f) : d.fn?.(n, r);
|
|
1581
|
+
} finally {
|
|
1582
|
+
}
|
|
1583
|
+
this.systemLastRun.set(d, s);
|
|
1584
|
+
}
|
|
1585
|
+
n.flush();
|
|
1586
|
+
}
|
|
1587
|
+
/**
|
|
1588
|
+
* Whether a gated system runs this tick — the AND of its own conditions and
|
|
1589
|
+
* every set it belongs to. A set's conditions are evaluated at most once per
|
|
1590
|
+
* phase (memoized in `setVerdicts`) and the verdict gates every member of the
|
|
1591
|
+
* set uniformly; a `configureSet` between phases is still honored because the
|
|
1592
|
+
* memo lives only for a single `runLabel` pass. Short-circuits on the first
|
|
1593
|
+
* `false`. The system's own conditions evaluate per system, in canonical order.
|
|
1594
|
+
*
|
|
1595
|
+
* #731 SEMANTIC NOTE: this evaluates a set's conditions once-per-set-per-phase
|
|
1596
|
+
* rather than once-per-member. Equivalent for pure RunConditions; observably
|
|
1597
|
+
* different only if a set condition reads state mutated earlier in the SAME
|
|
1598
|
+
* phase (resources write immediately). That is intentional — the set gates as a
|
|
1599
|
+
* unit, so all its members share one verdict for the phase.
|
|
1600
|
+
*/
|
|
1601
|
+
shouldRun(t, n, r) {
|
|
1602
|
+
if (t.conditions.length > 0 && !this.evalConditions(t.conditions, n))
|
|
1603
|
+
return !1;
|
|
1604
|
+
for (let s = 0; s < t.sets.length; s++) {
|
|
1605
|
+
const o = t.sets[s];
|
|
1606
|
+
let i = r.get(o);
|
|
1607
|
+
if (i === void 0) {
|
|
1608
|
+
const c = this.setConditions.get(o);
|
|
1609
|
+
i = c === void 0 || c.length === 0 ? !0 : this.evalConditions(c, n), r.set(o, i);
|
|
1610
|
+
}
|
|
1611
|
+
if (!i) return !1;
|
|
1612
|
+
}
|
|
1613
|
+
return !0;
|
|
1614
|
+
}
|
|
1615
|
+
/** Evaluate a condition list with AND semantics. Each predicate runs inside a
|
|
1616
|
+
* reads-only `accessCheck` span (dev), so a condition that reads an
|
|
1617
|
+
* undeclared resource — or attempts any mutation — throws. */
|
|
1618
|
+
evalConditions(t, n) {
|
|
1619
|
+
for (let r = 0; r < t.length; r++) {
|
|
1620
|
+
const s = t[r];
|
|
1621
|
+
let o;
|
|
1622
|
+
try {
|
|
1623
|
+
o = s.evaluate(n);
|
|
1624
|
+
} finally {
|
|
1625
|
+
}
|
|
1626
|
+
if (!o) return !1;
|
|
1627
|
+
}
|
|
1628
|
+
return !0;
|
|
1629
|
+
}
|
|
1630
|
+
getSorted(t) {
|
|
1631
|
+
const n = this.sortedCache.get(t);
|
|
1632
|
+
if (n !== void 0) return n;
|
|
1633
|
+
const r = this.labelSystems.get(t), s = this.sortSystems(r, t);
|
|
1634
|
+
return this.sortedCache.set(t, s), s;
|
|
1635
|
+
}
|
|
1636
|
+
/**
|
|
1637
|
+
* Delegates to the shared topologicalSort utility.
|
|
1638
|
+
* Builds the dependency edge map from before/after constraints, then
|
|
1639
|
+
* catches any cycle TypeError and re-throws as ECSError.
|
|
1640
|
+
*/
|
|
1641
|
+
sortSystems(t, n) {
|
|
1642
|
+
if (t.length === 0) return [];
|
|
1643
|
+
const r = [], s = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Map();
|
|
1644
|
+
for (const d of t) {
|
|
1645
|
+
r.push(d.descriptor), s.set(d.descriptor, d.insertionOrder), o.add(d.descriptor);
|
|
1646
|
+
for (let f = 0; f < d.sets.length; f++) {
|
|
1647
|
+
const _ = d.sets[f];
|
|
1648
|
+
let g = i.get(_);
|
|
1649
|
+
g === void 0 && (g = [], i.set(_, g)), g.push(d.descriptor);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
const c = /* @__PURE__ */ new Map();
|
|
1653
|
+
for (const d of t)
|
|
1654
|
+
c.set(d.descriptor, []);
|
|
1655
|
+
for (const d of t) {
|
|
1656
|
+
this.resolveEdges(
|
|
1657
|
+
d.descriptor,
|
|
1658
|
+
d.before,
|
|
1659
|
+
"before",
|
|
1660
|
+
o,
|
|
1661
|
+
i,
|
|
1662
|
+
c,
|
|
1663
|
+
n
|
|
1664
|
+
), this.resolveEdges(d.descriptor, d.after, "after", o, i, c, n);
|
|
1665
|
+
for (let f = 0; f < d.sets.length; f++) {
|
|
1666
|
+
const _ = this.setOrdering.get(d.sets[f]);
|
|
1667
|
+
_ !== void 0 && (this.resolveEdges(
|
|
1668
|
+
d.descriptor,
|
|
1669
|
+
_.before,
|
|
1670
|
+
"before",
|
|
1671
|
+
o,
|
|
1672
|
+
i,
|
|
1673
|
+
c,
|
|
1674
|
+
n
|
|
1675
|
+
), this.resolveEdges(
|
|
1676
|
+
d.descriptor,
|
|
1677
|
+
_.after,
|
|
1678
|
+
"after",
|
|
1679
|
+
o,
|
|
1680
|
+
i,
|
|
1681
|
+
c,
|
|
1682
|
+
n
|
|
1683
|
+
));
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
const a = (d, f) => s.get(d) - s.get(f), l = (d) => d.name ?? `system_${d.id}`;
|
|
1687
|
+
try {
|
|
1688
|
+
return tt(r, c, a, l);
|
|
1689
|
+
} catch (d) {
|
|
1690
|
+
throw d instanceof TypeError ? new S(
|
|
1691
|
+
w.CIRCULAR_SYSTEM_DEPENDENCY,
|
|
1692
|
+
`Circular system dependency detected in ${n}: ${d.message}`
|
|
1693
|
+
) : d;
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
/**
|
|
1697
|
+
* Add the topo edges for one ordering list (#576). For `"before"` the source
|
|
1698
|
+
* runs before each target (edge source→target); for `"after"` it runs after
|
|
1699
|
+
* each target (edge target→source). A `SystemSet` target expands to every
|
|
1700
|
+
* member within this phase (self-edges skipped, so a member ordered against
|
|
1701
|
+
* its own set is a no-op); a descriptor target absent from this phase is
|
|
1702
|
+
* dropped — with a dev warning only for a concrete system, since a set
|
|
1703
|
+
* legitimately expands to nothing when its members live in another phase.
|
|
1704
|
+
*/
|
|
1705
|
+
resolveEdges(t, n, r, s, o, i, c) {
|
|
1706
|
+
for (const a of n) {
|
|
1707
|
+
if (ln(a)) {
|
|
1708
|
+
const l = o.get(a);
|
|
1709
|
+
if (l === void 0) continue;
|
|
1710
|
+
for (let d = 0; d < l.length; d++) {
|
|
1711
|
+
const f = l[d];
|
|
1712
|
+
f !== t && this.addDirectedEdge(t, f, r, i);
|
|
1713
|
+
}
|
|
1714
|
+
continue;
|
|
1715
|
+
}
|
|
1716
|
+
s.has(a) && this.addDirectedEdge(t, a, r, i);
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
/** Push one directed edge into the adjacency map. Both endpoints are known to
|
|
1720
|
+
* be in this phase (callers guard), so `edges.get(...)` is non-null. */
|
|
1721
|
+
addDirectedEdge(t, n, r, s) {
|
|
1722
|
+
r === "before" ? s.get(t).push(n) : s.get(n).push(t);
|
|
1723
|
+
}
|
|
1724
|
+
/**
|
|
1725
|
+
* Dev-only diagnostic for an ordering edge that was dropped during sort.
|
|
1726
|
+
*
|
|
1727
|
+
* Cross-label ordering is impossible by design (`nodeSet` is per-label), so
|
|
1728
|
+
* a target registered in *another* phase is skipped silently — that's the
|
|
1729
|
+
* intended isolation. But a target unknown to *every* phase is almost
|
|
1730
|
+
* certainly a typo or a system that was never scheduled; without this warning
|
|
1731
|
+
* the constraint vanishes and the system runs in insertion-order tiebreak as
|
|
1732
|
+
* if unconstrained, with nothing to distinguish mistake from intent. Compiled
|
|
1733
|
+
* out of production builds by the `DEV` guards at the call sites.
|
|
1734
|
+
*/
|
|
1735
|
+
warnDroppedEdge(t, n, r, s) {
|
|
1736
|
+
if (this.systemIndex.has(n)) return;
|
|
1737
|
+
const o = (i) => i.name ?? `system_${i.id}`;
|
|
1738
|
+
this.onWarn(
|
|
1739
|
+
`Schedule[${s}]: \`${o(t)}\` declares \`${r}\` ordering against \`${o(n)}\`, which is not registered in any phase — the constraint is ignored. Check for a typo or a missing add_systems() call.`
|
|
1740
|
+
);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
const ne = 1024, se = 1024 * ne, Me = 64 * ne, X = 256 * se, $e = 3, un = 64, fn = 8, Pe = 4 * se, xe = (e) => 2 ** Math.ceil(Math.log2(Math.max(1, e))), Q = (e) => 2 ** Math.floor(Math.log2(Math.max(1, e))), F = (e, t, n) => Math.min(n, Math.max(t, e)), I = (e) => e >= se ? `${(e / se).toFixed(1)} MiB` : e >= ne ? `${(e / ne).toFixed(0)} KiB` : `${e} B`;
|
|
1744
|
+
function R(e, t) {
|
|
1745
|
+
if (!Number.isInteger(t) || t <= 0)
|
|
1746
|
+
throw new S(
|
|
1747
|
+
w.INVALID_MEMORY_OPTIONS,
|
|
1748
|
+
`memory.${e} must be a positive integer (got ${t})`
|
|
1749
|
+
);
|
|
1750
|
+
}
|
|
1751
|
+
function as(e) {
|
|
1752
|
+
const t = ["budget", "maxBytes", "wasm", "allocator", "heap", "shared"].filter(
|
|
1753
|
+
(s) => e !== void 0 && e[s] !== void 0
|
|
1754
|
+
);
|
|
1755
|
+
if (t.length > 1)
|
|
1756
|
+
throw new S(
|
|
1757
|
+
w.INVALID_MEMORY_OPTIONS,
|
|
1758
|
+
`memory takes at most one of budget | maxBytes | wasm | allocator | heap | shared (got: ${t.join(", ")})`
|
|
1759
|
+
);
|
|
1760
|
+
const n = e?.columnCapacity;
|
|
1761
|
+
if (n !== void 0 && R("column_capacity", n), e?.budget !== void 0) {
|
|
1762
|
+
const { entities: s } = e.budget, o = e.budget.archetypes ?? fn, i = e.budget.bytesPerEntity ?? un;
|
|
1763
|
+
if (R("budget.entities", s), R("budget.archetypes", o), R("budget.bytes_per_entity", i), s > 1 << 20)
|
|
1764
|
+
throw new S(
|
|
1765
|
+
w.INVALID_MEMORY_OPTIONS,
|
|
1766
|
+
`memory.budget.entities=${s} exceeds the EntityID index space (1<<20 = ${1 << 20})`
|
|
1767
|
+
);
|
|
1768
|
+
const c = n ?? F(xe(Math.ceil(s / o)), 64, 1 << 20), a = F(xe(s * 2), 4096, 1 << 20), l = a * D, d = s * i * $e, f = ze(
|
|
1769
|
+
Math.max(l + d, Pe),
|
|
1770
|
+
Me
|
|
1771
|
+
);
|
|
1772
|
+
return {
|
|
1773
|
+
source: "budget",
|
|
1774
|
+
allocator: K(f),
|
|
1775
|
+
columnCapacity: c,
|
|
1776
|
+
entityIndexCapacity: a,
|
|
1777
|
+
capBytes: f,
|
|
1778
|
+
intentLabel: `budget of ${s} entities`,
|
|
1779
|
+
budgetEntities: s,
|
|
1780
|
+
derivation: [
|
|
1781
|
+
`column_capacity = ${n !== void 0 ? `${c} (pinned)` : `pow2(${s}/${o} per archetype) = ${c}`}`,
|
|
1782
|
+
`entity_index = pow2(2 × ${s}) = ${a} slots × ${D} B = ${I(l)}`,
|
|
1783
|
+
`columns = ${s} × ${i} B × ${$e} (double+holes headroom) = ${I(d)}`,
|
|
1784
|
+
`cap = align64K(max(index + columns, ${I(Pe)} floor)) = ${I(f)}`
|
|
1785
|
+
],
|
|
1786
|
+
wasmMemory: null
|
|
1787
|
+
};
|
|
1788
|
+
}
|
|
1789
|
+
if (e?.maxBytes !== void 0) {
|
|
1790
|
+
R("maxBytes", e.maxBytes);
|
|
1791
|
+
const s = n ?? B, o = F(
|
|
1792
|
+
Q(e.maxBytes / 4 / D),
|
|
1793
|
+
4096,
|
|
1794
|
+
v
|
|
1795
|
+
);
|
|
1796
|
+
return {
|
|
1797
|
+
source: "max_bytes",
|
|
1798
|
+
allocator: K(e.maxBytes),
|
|
1799
|
+
columnCapacity: s,
|
|
1800
|
+
entityIndexCapacity: o,
|
|
1801
|
+
capBytes: e.maxBytes,
|
|
1802
|
+
intentLabel: `explicit cap of ${I(e.maxBytes)}`,
|
|
1803
|
+
budgetEntities: null,
|
|
1804
|
+
derivation: [
|
|
1805
|
+
`cap = ${I(e.maxBytes)} (caller-declared)`,
|
|
1806
|
+
`column_capacity = ${s} (${n !== void 0 ? "pinned" : "default"})`,
|
|
1807
|
+
`entity_index = floor_pow2(cap/4 ÷ ${D} B) = ${o} slots`
|
|
1808
|
+
],
|
|
1809
|
+
wasmMemory: null
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
if (e?.wasm !== void 0) {
|
|
1813
|
+
const s = e.wasm, o = n ?? B;
|
|
1814
|
+
if (s.memory !== void 0) {
|
|
1815
|
+
if (!(s.memory.buffer instanceof SharedArrayBuffer))
|
|
1816
|
+
throw new S(
|
|
1817
|
+
w.INVALID_MEMORY_OPTIONS,
|
|
1818
|
+
"memory.wasm.memory must be constructed with `shared: true` — the SAB substrate requires a SharedArrayBuffer-backed WebAssembly.Memory (ADR-0004 / ADR-0018)"
|
|
1819
|
+
);
|
|
1820
|
+
return {
|
|
1821
|
+
source: "wasm",
|
|
1822
|
+
allocator: we(s.memory),
|
|
1823
|
+
columnCapacity: o,
|
|
1824
|
+
entityIndexCapacity: v,
|
|
1825
|
+
// The JS API hides a Memory's `maximum`; the caller declared it.
|
|
1826
|
+
capBytes: null,
|
|
1827
|
+
intentLabel: "caller-supplied WebAssembly.Memory",
|
|
1828
|
+
budgetEntities: null,
|
|
1829
|
+
derivation: [
|
|
1830
|
+
"backing = wasm_memory_allocator(memory) — zero-copy with the sim (is_in_place ✓)",
|
|
1831
|
+
"cap = the Memory's own `maximum` (declared by the caller; not readable from JS)",
|
|
1832
|
+
`column_capacity = ${o} (${n !== void 0 ? "pinned" : "default"})`
|
|
1833
|
+
],
|
|
1834
|
+
wasmMemory: s.memory
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
R("wasm.maximum_pages", s.maximumPages);
|
|
1838
|
+
const i = s.initialPages ?? Math.min(32, s.maximumPages);
|
|
1839
|
+
if (R("wasm.initial_pages", i), i > s.maximumPages)
|
|
1840
|
+
throw new S(
|
|
1841
|
+
w.INVALID_MEMORY_OPTIONS,
|
|
1842
|
+
`memory.wasm.initial_pages (${i}) exceeds maximum_pages (${s.maximumPages})`
|
|
1843
|
+
);
|
|
1844
|
+
const c = new WebAssembly.Memory({
|
|
1845
|
+
initial: i,
|
|
1846
|
+
maximum: s.maximumPages,
|
|
1847
|
+
shared: !0
|
|
1848
|
+
}), a = s.maximumPages * Me, l = F(
|
|
1849
|
+
Q(a / 4 / D),
|
|
1850
|
+
4096,
|
|
1851
|
+
v
|
|
1852
|
+
);
|
|
1853
|
+
return {
|
|
1854
|
+
source: "wasm",
|
|
1855
|
+
allocator: we(c),
|
|
1856
|
+
columnCapacity: o,
|
|
1857
|
+
entityIndexCapacity: l,
|
|
1858
|
+
capBytes: a,
|
|
1859
|
+
intentLabel: `engine-constructed WebAssembly.Memory (max ${s.maximumPages} pages)`,
|
|
1860
|
+
budgetEntities: null,
|
|
1861
|
+
derivation: [
|
|
1862
|
+
`cap = ${s.maximumPages} pages × 64 KiB = ${I(a)} (Memory maximum)`,
|
|
1863
|
+
`initial = ${i} pages (${s.initialPages !== void 0 ? "declared" : "default"})`,
|
|
1864
|
+
`entity_index = floor_pow2(cap/4 ÷ ${D} B) = ${l} slots`,
|
|
1865
|
+
`column_capacity = ${o} (${n !== void 0 ? "pinned" : "default"})`
|
|
1866
|
+
],
|
|
1867
|
+
wasmMemory: c
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
if (e?.allocator !== void 0) {
|
|
1871
|
+
if (e.allocator.isInPlace !== !0)
|
|
1872
|
+
throw new S(
|
|
1873
|
+
w.INVALID_MEMORY_OPTIONS,
|
|
1874
|
+
"memory.allocator must declare `is_in_place: true` (ADR-0008): a live Store's flush loops hoist entity-index views across grows, so a non-in-place allocator (e.g. DEFAULT_SAB_ALLOCATOR) corrupts the entity→row mapping. Use growable_sab_allocator / wasm_memory_allocator; non-in-place allocators are snapshot/test sizing only."
|
|
1875
|
+
);
|
|
1876
|
+
const s = n ?? B, o = e.capBytesHint;
|
|
1877
|
+
return o !== void 0 && R("cap_bytes_hint", o), {
|
|
1878
|
+
source: "allocator",
|
|
1879
|
+
allocator: e.allocator,
|
|
1880
|
+
columnCapacity: s,
|
|
1881
|
+
entityIndexCapacity: v,
|
|
1882
|
+
capBytes: o ?? null,
|
|
1883
|
+
intentLabel: o !== void 0 ? `custom in-place allocator (cap hint ${I(o)})` : "custom in-place allocator",
|
|
1884
|
+
budgetEntities: null,
|
|
1885
|
+
derivation: [
|
|
1886
|
+
"backing = caller allocator (is_in_place ✓ checked at construction)",
|
|
1887
|
+
o !== void 0 ? `cap = ${I(o)} (caller hint — diagnostics only; the allocator owns the real cap)` : "cap = allocator-owned (no hint)",
|
|
1888
|
+
`column_capacity = ${s} (${n !== void 0 ? "pinned" : "default"})`
|
|
1889
|
+
],
|
|
1890
|
+
wasmMemory: null
|
|
1891
|
+
};
|
|
1892
|
+
}
|
|
1893
|
+
if (e?.heap !== void 0) {
|
|
1894
|
+
e.heap.maxBytes !== void 0 && R("heap.maxBytes", e.heap.maxBytes);
|
|
1895
|
+
const s = e.heap.maxBytes ?? X, o = n ?? B, i = F(
|
|
1896
|
+
Q(s / 4 / D),
|
|
1897
|
+
4096,
|
|
1898
|
+
v
|
|
1899
|
+
);
|
|
1900
|
+
return {
|
|
1901
|
+
source: "heap",
|
|
1902
|
+
allocator: K(s),
|
|
1903
|
+
columnCapacity: o,
|
|
1904
|
+
entityIndexCapacity: i,
|
|
1905
|
+
capBytes: s,
|
|
1906
|
+
intentLabel: `pure-TS heap backing (${I(s)} growable cap, no SharedArrayBuffer)`,
|
|
1907
|
+
budgetEntities: null,
|
|
1908
|
+
derivation: [
|
|
1909
|
+
`backing = heap_arraybuffer_allocator(${I(s)}) — resizable ArrayBuffer, no SAB / no COOP+COEP (is_in_place ✓)`,
|
|
1910
|
+
"trade-off: no worker offload / no WASM backend (both need a transferable SharedArrayBuffer)",
|
|
1911
|
+
`column_capacity = ${o} (${n !== void 0 ? "pinned" : "default"})`,
|
|
1912
|
+
`entity_index = floor_pow2(cap/4 ÷ ${D} B) = ${i} slots`
|
|
1913
|
+
],
|
|
1914
|
+
wasmMemory: null
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1917
|
+
if (e?.shared !== void 0) {
|
|
1918
|
+
e.shared.maxBytes !== void 0 && R("shared.maxBytes", e.shared.maxBytes);
|
|
1919
|
+
const s = e.shared.maxBytes ?? X, o = n ?? B, i = F(
|
|
1920
|
+
Q(s / 4 / D),
|
|
1921
|
+
4096,
|
|
1922
|
+
v
|
|
1923
|
+
);
|
|
1924
|
+
return {
|
|
1925
|
+
source: "shared",
|
|
1926
|
+
allocator: st(s),
|
|
1927
|
+
columnCapacity: o,
|
|
1928
|
+
entityIndexCapacity: i,
|
|
1929
|
+
capBytes: s,
|
|
1930
|
+
intentLabel: `shared SharedArrayBuffer backing (${I(s)} growable cap, needs COOP/COEP)`,
|
|
1931
|
+
budgetEntities: null,
|
|
1932
|
+
derivation: [
|
|
1933
|
+
`backing = growable_sab_allocator(${I(s)}) — growable SharedArrayBuffer (is_in_place ✓); needs cross-origin isolation`,
|
|
1934
|
+
"enables worker offload + a WASM compute backend (transferable SharedArrayBuffer)",
|
|
1935
|
+
`column_capacity = ${o} (${n !== void 0 ? "pinned" : "default"})`,
|
|
1936
|
+
`entity_index = floor_pow2(cap/4 ÷ ${D} B) = ${i} slots`
|
|
1937
|
+
],
|
|
1938
|
+
wasmMemory: null
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
const r = n ?? B;
|
|
1942
|
+
return {
|
|
1943
|
+
source: "default",
|
|
1944
|
+
allocator: K(),
|
|
1945
|
+
columnCapacity: r,
|
|
1946
|
+
entityIndexCapacity: v,
|
|
1947
|
+
capBytes: X,
|
|
1948
|
+
intentLabel: `default sizing (${I(X)} growable cap)`,
|
|
1949
|
+
budgetEntities: null,
|
|
1950
|
+
derivation: [
|
|
1951
|
+
`cap = ${I(X)} (heap_arraybuffer_allocator default)`,
|
|
1952
|
+
`column_capacity = ${r} (${n !== void 0 ? "pinned" : "DEFAULT_COLUMN_CAPACITY"})`,
|
|
1953
|
+
`entity_index = ${v} slots (full EntityID space, ~12 MiB virtual)`
|
|
1954
|
+
],
|
|
1955
|
+
wasmMemory: null
|
|
1956
|
+
};
|
|
1957
|
+
}
|
|
1958
|
+
function cs(e, t) {
|
|
1959
|
+
return { def: e, values: t };
|
|
1960
|
+
}
|
|
1961
|
+
function ue(e, t) {
|
|
1962
|
+
switch (t.kind) {
|
|
1963
|
+
case "spawn": {
|
|
1964
|
+
const n = e.commands.spawn();
|
|
1965
|
+
for (const r of t.components)
|
|
1966
|
+
e.commands.add(n, r.def, r.values);
|
|
1967
|
+
return t.onSpawned?.(n), n;
|
|
1968
|
+
}
|
|
1969
|
+
case "despawn":
|
|
1970
|
+
e.commands.despawn(t.eid);
|
|
1971
|
+
return;
|
|
1972
|
+
case "add_component":
|
|
1973
|
+
e.commands.add(t.eid, t.def, t.values);
|
|
1974
|
+
return;
|
|
1975
|
+
case "remove_component":
|
|
1976
|
+
e.commands.remove(t.eid, t.def);
|
|
1977
|
+
return;
|
|
1978
|
+
case "set_field":
|
|
1979
|
+
e.setField(t.eid, t.def, t.field, t.value);
|
|
1980
|
+
return;
|
|
1981
|
+
case "disable":
|
|
1982
|
+
e.commands.disable(t.eid);
|
|
1983
|
+
return;
|
|
1984
|
+
case "enable":
|
|
1985
|
+
e.commands.enable(t.eid);
|
|
1986
|
+
return;
|
|
1987
|
+
default:
|
|
1988
|
+
return ot(t, "HostCommand kind");
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
class _n {
|
|
1992
|
+
queued = [];
|
|
1993
|
+
spawn(t, n) {
|
|
1994
|
+
this.queued.push({ kind: "spawn", components: t, onSpawned: n });
|
|
1995
|
+
}
|
|
1996
|
+
despawn(t) {
|
|
1997
|
+
this.queued.push({ kind: "despawn", eid: t });
|
|
1998
|
+
}
|
|
1999
|
+
addComponent(t, n, r) {
|
|
2000
|
+
this.queued.push({ kind: "add_component", eid: t, def: n, values: r });
|
|
2001
|
+
}
|
|
2002
|
+
removeComponent(t, n) {
|
|
2003
|
+
this.queued.push({ kind: "remove_component", eid: t, def: n });
|
|
2004
|
+
}
|
|
2005
|
+
/** Set `field` of `def` on `eid`. Applied IMMEDIATELY at the drain, unlike the
|
|
2006
|
+
* deferred structural ops — so `def` must already be on `eid`. Do NOT
|
|
2007
|
+
* `addComponent`/`spawn` `def` and `setField` it in the same frame: the add is
|
|
2008
|
+
* still pending its flush when the immediate set runs (carry the value in
|
|
2009
|
+
* `addComponent`/`spawnEntry` instead). `applyHostCommand` throws an
|
|
2010
|
+
* actionable error in `DEV` if you do. */
|
|
2011
|
+
setField(t, n, r, s) {
|
|
2012
|
+
this.queued.push({ kind: "set_field", eid: t, def: n, field: r, value: s });
|
|
2013
|
+
}
|
|
2014
|
+
disable(t) {
|
|
2015
|
+
this.queued.push({ kind: "disable", eid: t });
|
|
2016
|
+
}
|
|
2017
|
+
enable(t) {
|
|
2018
|
+
this.queued.push({ kind: "enable", eid: t });
|
|
2019
|
+
}
|
|
2020
|
+
/** Enqueue a pre-built command. The path for a SAB-ring codec, an editor's
|
|
2021
|
+
* reified inverse, or a replay log — all of which produce `HostCommand` data
|
|
2022
|
+
* directly rather than calling the typed sugar above. */
|
|
2023
|
+
push(t) {
|
|
2024
|
+
this.queued.push(t);
|
|
2025
|
+
}
|
|
2026
|
+
/** Commands buffered but not yet applied. */
|
|
2027
|
+
pending() {
|
|
2028
|
+
return this.queued.length;
|
|
2029
|
+
}
|
|
2030
|
+
/** Drop every buffered command without applying it (M15) — e.g. abandoning
|
|
2031
|
+
* queued edits on a scene unload. Returns how many were dropped. Does not
|
|
2032
|
+
* touch commands already drained into the world. */
|
|
2033
|
+
clear() {
|
|
2034
|
+
const t = this.queued.length;
|
|
2035
|
+
return this.queued.length = 0, t;
|
|
2036
|
+
}
|
|
2037
|
+
/**
|
|
2038
|
+
* Apply and clear every buffered command. Called by the blessed apply system
|
|
2039
|
+
* inside its schedule span; not part of the host-facing surface. Returns the
|
|
2040
|
+
* count applied.
|
|
2041
|
+
*
|
|
2042
|
+
* `tap`, when present, is invoked with each command in apply order just before
|
|
2043
|
+
* it is applied — the record/replay hook ({@link HostCommandRecorder}). It is
|
|
2044
|
+
* an OPT-IN observer: the tap-free path keeps the original tight loop, so an
|
|
2045
|
+
* un-recorded drain pays nothing (#702).
|
|
2046
|
+
*/
|
|
2047
|
+
drain(t, n) {
|
|
2048
|
+
const r = this.queued.length;
|
|
2049
|
+
if (r === 0) return 0;
|
|
2050
|
+
if (n === void 0)
|
|
2051
|
+
for (let s = 0; s < r; s++) ue(t, this.queued[s]);
|
|
2052
|
+
else
|
|
2053
|
+
for (let s = 0; s < r; s++) {
|
|
2054
|
+
const o = this.queued[s];
|
|
2055
|
+
n(o), ue(t, o);
|
|
2056
|
+
}
|
|
2057
|
+
return this.queued.splice(0, r), r;
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
const Je = M - 1;
|
|
2061
|
+
function hn(e) {
|
|
2062
|
+
if (e === Ee)
|
|
2063
|
+
throw new U(
|
|
2064
|
+
"cannot bind op_code 0 (reserved as the command-ring empty-slot marker)"
|
|
2065
|
+
);
|
|
2066
|
+
if (e < 0 || e > 255 || !Number.isInteger(e))
|
|
2067
|
+
throw new U(`command op_code must be a u8 in [1, 255] (got ${e})`);
|
|
2068
|
+
}
|
|
2069
|
+
function oe(e) {
|
|
2070
|
+
const t = new Uint8Array(Je);
|
|
2071
|
+
return new DataView(t.buffer).setUint32(0, e, !0), t;
|
|
2072
|
+
}
|
|
2073
|
+
function ie(e) {
|
|
2074
|
+
return new DataView(e.buffer, e.byteOffset, e.byteLength).getUint32(0, !0);
|
|
2075
|
+
}
|
|
2076
|
+
function ds(e, t) {
|
|
2077
|
+
return {
|
|
2078
|
+
encode(n) {
|
|
2079
|
+
if (n.kind !== "set_field")
|
|
2080
|
+
throw new U(
|
|
2081
|
+
`ringSetFieldCodec encodes a "set_field" command (got "${n.kind}")`
|
|
2082
|
+
);
|
|
2083
|
+
const r = new Uint8Array(Je), s = new DataView(r.buffer);
|
|
2084
|
+
return s.setUint32(0, n.eid, !0), s.setFloat64(4, n.value, !0), r;
|
|
2085
|
+
},
|
|
2086
|
+
decode(n) {
|
|
2087
|
+
const r = new DataView(n.buffer, n.byteOffset, n.byteLength);
|
|
2088
|
+
return {
|
|
2089
|
+
kind: "set_field",
|
|
2090
|
+
// boundary: branded-ID bridging — a decoded `u32` is an `EntityID` handle.
|
|
2091
|
+
eid: r.getUint32(0, !0),
|
|
2092
|
+
// schema-erased into the flat HostCommand union (the callable def is invariant in S).
|
|
2093
|
+
def: e,
|
|
2094
|
+
field: t,
|
|
2095
|
+
value: r.getFloat64(4, !0)
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
};
|
|
2099
|
+
}
|
|
2100
|
+
function ls() {
|
|
2101
|
+
return {
|
|
2102
|
+
encode(e) {
|
|
2103
|
+
if (e.kind !== "despawn")
|
|
2104
|
+
throw new U(
|
|
2105
|
+
`ring_despawn_codec encodes a "despawn" command (got "${e.kind}")`
|
|
2106
|
+
);
|
|
2107
|
+
return oe(e.eid);
|
|
2108
|
+
},
|
|
2109
|
+
decode: (e) => ({ kind: "despawn", eid: ie(e) })
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
function us() {
|
|
2113
|
+
return {
|
|
2114
|
+
encode(e) {
|
|
2115
|
+
if (e.kind !== "disable")
|
|
2116
|
+
throw new U(
|
|
2117
|
+
`ring_disable_codec encodes a "disable" command (got "${e.kind}")`
|
|
2118
|
+
);
|
|
2119
|
+
return oe(e.eid);
|
|
2120
|
+
},
|
|
2121
|
+
decode: (e) => ({ kind: "disable", eid: ie(e) })
|
|
2122
|
+
};
|
|
2123
|
+
}
|
|
2124
|
+
function fs() {
|
|
2125
|
+
return {
|
|
2126
|
+
encode(e) {
|
|
2127
|
+
if (e.kind !== "enable")
|
|
2128
|
+
throw new U(
|
|
2129
|
+
`ring_enable_codec encodes an "enable" command (got "${e.kind}")`
|
|
2130
|
+
);
|
|
2131
|
+
return oe(e.eid);
|
|
2132
|
+
},
|
|
2133
|
+
decode: (e) => ({ kind: "enable", eid: ie(e) })
|
|
2134
|
+
};
|
|
2135
|
+
}
|
|
2136
|
+
function _s(e) {
|
|
2137
|
+
return {
|
|
2138
|
+
encode(t) {
|
|
2139
|
+
if (t.kind !== "remove_component")
|
|
2140
|
+
throw new U(
|
|
2141
|
+
`ringRemoveComponentCodec encodes a "remove_component" command (got "${t.kind}")`
|
|
2142
|
+
);
|
|
2143
|
+
return oe(t.eid);
|
|
2144
|
+
},
|
|
2145
|
+
decode: (t) => ({ kind: "remove_component", eid: ie(t), def: e })
|
|
2146
|
+
};
|
|
2147
|
+
}
|
|
2148
|
+
class hs {
|
|
2149
|
+
appliers = /* @__PURE__ */ new Map();
|
|
2150
|
+
/** Bind a raw ctx-aware applier to `opCode`. Re-binding replaces. */
|
|
2151
|
+
on(t, n) {
|
|
2152
|
+
return hn(t), this.appliers.set(t, n), this;
|
|
2153
|
+
}
|
|
2154
|
+
/** Unbind `opCode` (M15). Returns whether a binding was removed; subsequent
|
|
2155
|
+
* slots carrying it hit the unknown-opcode path. */
|
|
2156
|
+
off(t) {
|
|
2157
|
+
return this.appliers.delete(t);
|
|
2158
|
+
}
|
|
2159
|
+
/** Bind a `HostCommand` codec to `opCode`: each matching slot is decoded and
|
|
2160
|
+
* run through `applyHostCommand` — the SAME dispatch the typed queue uses.
|
|
2161
|
+
* A drain-time `tap` (record/replay, #702) sees the decoded command before it
|
|
2162
|
+
* applies, so ring-sourced commands share one log with the typed transport. */
|
|
2163
|
+
onCommand(t, n) {
|
|
2164
|
+
return this.on(t, (r, s, o) => {
|
|
2165
|
+
const i = n.decode(s);
|
|
2166
|
+
o?.(i), ue(r, i);
|
|
2167
|
+
});
|
|
2168
|
+
}
|
|
2169
|
+
/** Drain every pending slot, dispatching each to its bound applier. Unbound
|
|
2170
|
+
* opcodes are skipped (the read head still advances — matching
|
|
2171
|
+
* `drainCommandRing` / `CommandDispatcher`). Returns slots drained. `tap`,
|
|
2172
|
+
* when present, is forwarded to each applier as the record/replay hook (#702);
|
|
2173
|
+
* only `onCommand`-bound (generic `HostCommand`) opcodes surface to it. */
|
|
2174
|
+
drain(t, n, r, s) {
|
|
2175
|
+
return Dt(n, r, (o, i) => {
|
|
2176
|
+
const c = this.appliers.get(o);
|
|
2177
|
+
c !== void 0 && c(t, i, s);
|
|
2178
|
+
});
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
const mn = /* @__PURE__ */ new Set([
|
|
2182
|
+
$.PRE_STARTUP,
|
|
2183
|
+
$.STARTUP,
|
|
2184
|
+
$.POST_STARTUP
|
|
2185
|
+
]), fe = /* @__PURE__ */ new WeakMap();
|
|
2186
|
+
function ms(e, t) {
|
|
2187
|
+
const n = fe.get(t);
|
|
2188
|
+
if (n === void 0) return !1;
|
|
2189
|
+
for (const r of n) e.removeSystem(r);
|
|
2190
|
+
return fe.delete(t), t.clear(), !0;
|
|
2191
|
+
}
|
|
2192
|
+
function gs(e, t) {
|
|
2193
|
+
const n = new _n(), r = [];
|
|
2194
|
+
fe.set(n, r);
|
|
2195
|
+
const s = t?.name ?? "host_command_apply", o = t?.ring, i = t?.recorder, c = i?.record, a = t?.schedules ?? [$.PRE_STARTUP, $.PRE_UPDATE];
|
|
2196
|
+
if (i !== void 0 && a.includes($.FIXED_UPDATE))
|
|
2197
|
+
throw new S(
|
|
2198
|
+
w.INVALID_RECORDER_SCHEDULE,
|
|
2199
|
+
"install_host_command_seam: a recorder cannot drain on SCHEDULE.FIXED_UPDATE — it would log the fixed-step dt instead of the host update(dt) and diverge on replay. Use a variable-update phase (PRE_UPDATE/UPDATE/POST_UPDATE)."
|
|
2200
|
+
);
|
|
2201
|
+
for (const l of a) {
|
|
2202
|
+
const d = !mn.has(l), f = e.registerSystem({
|
|
2203
|
+
name: `${s}:${l}`,
|
|
2204
|
+
// `reads`/`writes` are required by `SystemConfig` but empty here: the
|
|
2205
|
+
// apply system declares nothing because it mutates components not known
|
|
2206
|
+
// at registration. Full world access: the host may queue mutations to
|
|
2207
|
+
// anything. The deferred-flush apply point is unchanged, so structural
|
|
2208
|
+
// safety holds; `exclusive` only waives the DEV access check.
|
|
2209
|
+
reads: [],
|
|
2210
|
+
writes: [],
|
|
2211
|
+
exclusive: !0,
|
|
2212
|
+
fn: (_, g) => {
|
|
2213
|
+
if (i !== void 0 && d && i.openTick(_.ecsTick, g), n.drain(_, c), o !== void 0) {
|
|
2214
|
+
const y = e.columnStore, u = y.header.commandRingOff;
|
|
2215
|
+
u !== 0 && o.drain(_, y.view, u, c);
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
});
|
|
2219
|
+
e.addSystems(l, f), r.push(f);
|
|
2220
|
+
}
|
|
2221
|
+
return n;
|
|
2222
|
+
}
|
|
2223
|
+
export {
|
|
2224
|
+
ee as $,
|
|
2225
|
+
Kt as A,
|
|
2226
|
+
$e as B,
|
|
2227
|
+
$n as C,
|
|
2228
|
+
X as D,
|
|
2229
|
+
S as E,
|
|
2230
|
+
es as F,
|
|
2231
|
+
en as G,
|
|
2232
|
+
hs as H,
|
|
2233
|
+
ts as I,
|
|
2234
|
+
Rn as J,
|
|
2235
|
+
qn as K,
|
|
2236
|
+
ze as L,
|
|
2237
|
+
P as M,
|
|
2238
|
+
wn as N,
|
|
2239
|
+
ye as O,
|
|
2240
|
+
We as P,
|
|
2241
|
+
j as Q,
|
|
2242
|
+
Cn as R,
|
|
2243
|
+
m as S,
|
|
2244
|
+
Hn as T,
|
|
2245
|
+
In as U,
|
|
2246
|
+
zn as V,
|
|
2247
|
+
Xn as W,
|
|
2248
|
+
gt as X,
|
|
2249
|
+
ke as Y,
|
|
2250
|
+
Ne as Z,
|
|
2251
|
+
re as _,
|
|
2252
|
+
un as a,
|
|
2253
|
+
Qn as a0,
|
|
2254
|
+
ns as a1,
|
|
2255
|
+
p as a2,
|
|
2256
|
+
Zn as a3,
|
|
2257
|
+
ss as a4,
|
|
2258
|
+
Jn as a5,
|
|
2259
|
+
xn as a6,
|
|
2260
|
+
J as a7,
|
|
2261
|
+
v as a8,
|
|
2262
|
+
kn as a9,
|
|
2263
|
+
_n as aA,
|
|
2264
|
+
cs as aB,
|
|
2265
|
+
Ue as aC,
|
|
2266
|
+
An as aD,
|
|
2267
|
+
Wn as aa,
|
|
2268
|
+
N as ab,
|
|
2269
|
+
ge as ac,
|
|
2270
|
+
me as ad,
|
|
2271
|
+
Kn as ae,
|
|
2272
|
+
Jt as af,
|
|
2273
|
+
qe as ag,
|
|
2274
|
+
Sn as ah,
|
|
2275
|
+
Ye as ai,
|
|
2276
|
+
Bn as aj,
|
|
2277
|
+
Mn as ak,
|
|
2278
|
+
jn as al,
|
|
2279
|
+
z as am,
|
|
2280
|
+
Gn as an,
|
|
2281
|
+
Yn as ao,
|
|
2282
|
+
Vn as ap,
|
|
2283
|
+
is as aq,
|
|
2284
|
+
On as ar,
|
|
2285
|
+
bn as as,
|
|
2286
|
+
Nn as at,
|
|
2287
|
+
Dn as au,
|
|
2288
|
+
$ as av,
|
|
2289
|
+
os as aw,
|
|
2290
|
+
gs as ax,
|
|
2291
|
+
ms as ay,
|
|
2292
|
+
ue as az,
|
|
2293
|
+
fn as b,
|
|
2294
|
+
rs as c,
|
|
2295
|
+
ds as d,
|
|
2296
|
+
ls as e,
|
|
2297
|
+
us as f,
|
|
2298
|
+
fs as g,
|
|
2299
|
+
_s as h,
|
|
2300
|
+
Je as i,
|
|
2301
|
+
vn as j,
|
|
2302
|
+
Ln as k,
|
|
2303
|
+
_e as l,
|
|
2304
|
+
Un as m,
|
|
2305
|
+
Se as n,
|
|
2306
|
+
ft as o,
|
|
2307
|
+
lt as p,
|
|
2308
|
+
ut as q,
|
|
2309
|
+
as as r,
|
|
2310
|
+
Pn as s,
|
|
2311
|
+
Fn as t,
|
|
2312
|
+
Zt as u,
|
|
2313
|
+
yn as v,
|
|
2314
|
+
Tn as w,
|
|
2315
|
+
w as x,
|
|
2316
|
+
B as y,
|
|
2317
|
+
k as z
|
|
2318
|
+
};
|