@oasys/oecs 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +196 -267
  2. package/dist/array-CxbPyiHO.cjs +1 -0
  3. package/dist/array-uFR7Q8fU.js +132 -0
  4. package/dist/core/ecs/access_check.d.ts +77 -0
  5. package/dist/core/ecs/access_check.d.ts.map +1 -0
  6. package/dist/core/ecs/archetype.d.ts +474 -0
  7. package/dist/core/ecs/archetype.d.ts.map +1 -0
  8. package/dist/core/ecs/builtin_relations.d.ts +43 -0
  9. package/dist/core/ecs/builtin_relations.d.ts.map +1 -0
  10. package/dist/core/ecs/command_log.d.ts +113 -0
  11. package/dist/core/ecs/command_log.d.ts.map +1 -0
  12. package/dist/core/ecs/component.d.ts +106 -0
  13. package/dist/core/ecs/component.d.ts.map +1 -0
  14. package/dist/core/ecs/compute_backend.d.ts +37 -0
  15. package/dist/core/ecs/compute_backend.d.ts.map +1 -0
  16. package/dist/core/ecs/dispatch_trace.d.ts +93 -0
  17. package/dist/core/ecs/dispatch_trace.d.ts.map +1 -0
  18. package/dist/core/ecs/ecs.d.ts +533 -0
  19. package/dist/core/ecs/ecs.d.ts.map +1 -0
  20. package/dist/core/ecs/ecs_memory.d.ts +179 -0
  21. package/dist/core/ecs/ecs_memory.d.ts.map +1 -0
  22. package/dist/core/ecs/entity.d.ts +28 -0
  23. package/dist/core/ecs/entity.d.ts.map +1 -0
  24. package/dist/core/ecs/event.d.ts +54 -0
  25. package/dist/core/ecs/event.d.ts.map +1 -0
  26. package/dist/core/ecs/frame_trace.d.ts +133 -0
  27. package/dist/core/ecs/frame_trace.d.ts.map +1 -0
  28. package/dist/core/ecs/host_commands.d.ts +252 -0
  29. package/dist/core/ecs/host_commands.d.ts.map +1 -0
  30. package/dist/core/ecs/index.d.ts +41 -0
  31. package/dist/core/ecs/index.d.ts.map +1 -0
  32. package/dist/core/ecs/observer.d.ts +142 -0
  33. package/dist/core/ecs/observer.d.ts.map +1 -0
  34. package/dist/core/ecs/query.d.ts +557 -0
  35. package/dist/core/ecs/query.d.ts.map +1 -0
  36. package/dist/core/ecs/ref.d.ts +31 -0
  37. package/dist/core/ecs/ref.d.ts.map +1 -0
  38. package/dist/core/ecs/relation.d.ts +231 -0
  39. package/dist/core/ecs/relation.d.ts.map +1 -0
  40. package/dist/core/ecs/resource.d.ts +33 -0
  41. package/dist/core/ecs/resource.d.ts.map +1 -0
  42. package/dist/core/ecs/resume.d.ts +85 -0
  43. package/dist/core/ecs/resume.d.ts.map +1 -0
  44. package/dist/core/ecs/run_condition.d.ts +75 -0
  45. package/dist/core/ecs/run_condition.d.ts.map +1 -0
  46. package/dist/core/ecs/schedule.d.ts +133 -0
  47. package/dist/core/ecs/schedule.d.ts.map +1 -0
  48. package/dist/core/ecs/sparse_store.d.ts +107 -0
  49. package/dist/core/ecs/sparse_store.d.ts.map +1 -0
  50. package/dist/core/ecs/store.d.ts +1149 -0
  51. package/dist/core/ecs/store.d.ts.map +1 -0
  52. package/dist/core/ecs/store_layout_listener.d.ts +23 -0
  53. package/dist/core/ecs/store_layout_listener.d.ts.map +1 -0
  54. package/dist/core/ecs/system.d.ts +134 -0
  55. package/dist/core/ecs/system.d.ts.map +1 -0
  56. package/dist/core/ecs/utils/arrays.d.ts +7 -0
  57. package/dist/core/ecs/utils/arrays.d.ts.map +1 -0
  58. package/dist/core/ecs/utils/constants.d.ts +12 -0
  59. package/dist/core/ecs/utils/constants.d.ts.map +1 -0
  60. package/dist/core/ecs/utils/error.d.ts +51 -0
  61. package/dist/core/ecs/utils/error.d.ts.map +1 -0
  62. package/dist/core/reactive/array.d.ts +24 -0
  63. package/dist/core/reactive/array.d.ts.map +1 -0
  64. package/dist/core/reactive/index.cjs +1 -0
  65. package/dist/core/reactive/index.d.ts +10 -0
  66. package/dist/core/reactive/index.d.ts.map +1 -0
  67. package/dist/core/reactive/index.js +17 -0
  68. package/dist/core/reactive/interop.d.ts +19 -0
  69. package/dist/core/reactive/interop.d.ts.map +1 -0
  70. package/dist/core/reactive/kernel.d.ts +71 -0
  71. package/dist/core/reactive/kernel.d.ts.map +1 -0
  72. package/dist/core/reactive/map.d.ts +16 -0
  73. package/dist/core/reactive/map.d.ts.map +1 -0
  74. package/dist/core/reactive/struct.d.ts +10 -0
  75. package/dist/core/reactive/struct.d.ts.map +1 -0
  76. package/dist/core/store/__generated__/abi.d.ts +43 -0
  77. package/dist/core/store/__generated__/abi.d.ts.map +1 -0
  78. package/dist/core/store/action_ring.d.ts +136 -0
  79. package/dist/core/store/action_ring.d.ts.map +1 -0
  80. package/dist/core/store/allocator.d.ts +238 -0
  81. package/dist/core/store/allocator.d.ts.map +1 -0
  82. package/dist/core/store/buffer_backed_column.d.ts +69 -0
  83. package/dist/core/store/buffer_backed_column.d.ts.map +1 -0
  84. package/dist/core/store/column_store.d.ts +265 -0
  85. package/dist/core/store/column_store.d.ts.map +1 -0
  86. package/dist/core/store/command_dispatch.d.ts +52 -0
  87. package/dist/core/store/command_dispatch.d.ts.map +1 -0
  88. package/dist/core/store/command_ring.d.ts +107 -0
  89. package/dist/core/store/command_ring.d.ts.map +1 -0
  90. package/dist/core/store/descriptor.d.ts +80 -0
  91. package/dist/core/store/descriptor.d.ts.map +1 -0
  92. package/dist/core/store/entity_index.d.ts +108 -0
  93. package/dist/core/store/entity_index.d.ts.map +1 -0
  94. package/dist/core/store/event_ring.d.ts +95 -0
  95. package/dist/core/store/event_ring.d.ts.map +1 -0
  96. package/dist/core/store/extend.d.ts +109 -0
  97. package/dist/core/store/extend.d.ts.map +1 -0
  98. package/dist/core/store/grow.d.ts +39 -0
  99. package/dist/core/store/grow.d.ts.map +1 -0
  100. package/dist/core/store/header.d.ts +64 -0
  101. package/dist/core/store/header.d.ts.map +1 -0
  102. package/dist/core/store/index.d.ts +16 -0
  103. package/dist/core/store/index.d.ts.map +1 -0
  104. package/dist/core/store/region_table.d.ts +74 -0
  105. package/dist/core/store/region_table.d.ts.map +1 -0
  106. package/dist/core/store/snapshot.d.ts +43 -0
  107. package/dist/core/store/snapshot.d.ts.map +1 -0
  108. package/dist/core/store/state_hash.d.ts +38 -0
  109. package/dist/core/store/state_hash.d.ts.map +1 -0
  110. package/dist/core/store/store_regions.d.ts +38 -0
  111. package/dist/core/store/store_regions.d.ts.map +1 -0
  112. package/dist/extensions/editor/editor.d.ts +149 -0
  113. package/dist/extensions/editor/editor.d.ts.map +1 -0
  114. package/dist/extensions/editor/field_handle.d.ts +35 -0
  115. package/dist/extensions/editor/field_handle.d.ts.map +1 -0
  116. package/dist/extensions/editor/index.cjs +1 -0
  117. package/dist/extensions/editor/index.d.ts +21 -0
  118. package/dist/extensions/editor/index.d.ts.map +1 -0
  119. package/dist/extensions/editor/index.js +209 -0
  120. package/dist/extensions/reactive/ecs_sync.d.ts +210 -0
  121. package/dist/extensions/reactive/ecs_sync.d.ts.map +1 -0
  122. package/dist/extensions/reactive/index.cjs +1 -0
  123. package/dist/extensions/reactive/index.d.ts +23 -0
  124. package/dist/extensions/reactive/index.d.ts.map +1 -0
  125. package/dist/extensions/reactive/index.js +225 -0
  126. package/dist/extensions/solid/index.cjs +1 -0
  127. package/dist/extensions/solid/index.d.ts +6 -0
  128. package/dist/extensions/solid/index.d.ts.map +1 -0
  129. package/dist/extensions/solid/index.js +32 -0
  130. package/dist/extensions/solid/kernel_solid.d.ts +42 -0
  131. package/dist/extensions/solid/kernel_solid.d.ts.map +1 -0
  132. package/dist/index.cjs +2 -1
  133. package/dist/index.d.ts +16 -12
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +8565 -1310
  136. package/dist/interop-CT-REx0W.cjs +1 -0
  137. package/dist/interop-CcY6ASQc.js +18 -0
  138. package/dist/kernel-DgyrLFjW.js +227 -0
  139. package/dist/kernel-yWV3XnAb.cjs +1 -0
  140. package/dist/log/console_sink.d.ts +4 -0
  141. package/dist/log/console_sink.d.ts.map +1 -0
  142. package/dist/log/index.d.ts +3 -0
  143. package/dist/log/index.d.ts.map +1 -0
  144. package/dist/log/logger.d.ts +27 -0
  145. package/dist/log/logger.d.ts.map +1 -0
  146. package/dist/primitives.cjs +1 -0
  147. package/dist/primitives.d.ts +18 -0
  148. package/dist/primitives.d.ts.map +1 -0
  149. package/dist/primitives.js +44 -0
  150. package/dist/shared-BXSZnxx4.cjs +1 -0
  151. package/dist/shared-C678TAPY.js +99 -0
  152. package/dist/shared.cjs +1 -0
  153. package/dist/shared.d.ts +22 -0
  154. package/dist/shared.d.ts.map +1 -0
  155. package/dist/shared.js +7 -0
  156. package/dist/topological_sort-DlRpSrxu.js +391 -0
  157. package/dist/topological_sort-WAT-VHb-.cjs +1 -0
  158. package/dist/type_primitives/assertions.d.ts +12 -8
  159. package/dist/type_primitives/assertions.d.ts.map +1 -1
  160. package/dist/type_primitives/binary_heap/binary_heap.d.ts +6 -2
  161. package/dist/type_primitives/binary_heap/binary_heap.d.ts.map +1 -1
  162. package/dist/type_primitives/bitset/bitset.d.ts +16 -4
  163. package/dist/type_primitives/bitset/bitset.d.ts.map +1 -1
  164. package/dist/type_primitives/brand.d.ts +6 -1
  165. package/dist/type_primitives/brand.d.ts.map +1 -1
  166. package/dist/type_primitives/error.d.ts +4 -0
  167. package/dist/type_primitives/error.d.ts.map +1 -1
  168. package/dist/type_primitives/index.d.ts +3 -0
  169. package/dist/type_primitives/index.d.ts.map +1 -1
  170. package/dist/type_primitives/sparse_map/sparse_map.d.ts +7 -3
  171. package/dist/type_primitives/sparse_map/sparse_map.d.ts.map +1 -1
  172. package/dist/type_primitives/sparse_set/sparse_set.d.ts +4 -0
  173. package/dist/type_primitives/sparse_set/sparse_set.d.ts.map +1 -1
  174. package/dist/type_primitives/topological_sort/topological_sort.d.ts +7 -3
  175. package/dist/type_primitives/topological_sort/topological_sort.d.ts.map +1 -1
  176. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts +53 -16
  177. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts.map +1 -1
  178. package/dist/utils/arrays.d.ts +1 -1
  179. package/dist/utils/arrays.d.ts.map +1 -1
  180. package/dist/utils/error.d.ts +2 -20
  181. package/dist/utils/error.d.ts.map +1 -1
  182. package/package.json +36 -9
  183. package/dist/archetype.d.ts +0 -108
  184. package/dist/archetype.d.ts.map +0 -1
  185. package/dist/component.d.ts +0 -45
  186. package/dist/component.d.ts.map +0 -1
  187. package/dist/ecs.d.ts +0 -104
  188. package/dist/ecs.d.ts.map +0 -1
  189. package/dist/entity.d.ts +0 -11
  190. package/dist/entity.d.ts.map +0 -1
  191. package/dist/event.d.ts +0 -30
  192. package/dist/event.d.ts.map +0 -1
  193. package/dist/query.d.ts +0 -94
  194. package/dist/query.d.ts.map +0 -1
  195. package/dist/ref.d.ts +0 -23
  196. package/dist/ref.d.ts.map +0 -1
  197. package/dist/resource.d.ts +0 -23
  198. package/dist/resource.d.ts.map +0 -1
  199. package/dist/schedule.d.ts +0 -45
  200. package/dist/schedule.d.ts.map +0 -1
  201. package/dist/store.d.ts +0 -118
  202. package/dist/store.d.ts.map +0 -1
  203. package/dist/system.d.ts +0 -16
  204. package/dist/system.d.ts.map +0 -1
@@ -0,0 +1,252 @@
1
+ import { ComponentDef, ComponentSchema, FieldValues } from './component';
2
+ import { ECS } from './ecs';
3
+ import { EntityID } from './entity';
4
+ import { SystemContext } from './query';
5
+ import { SCHEDULE } from './schedule';
6
+ import { PayloadCodec } from '../store';
7
+ /** One component to attach to a freshly spawned entity. `values` are required and
8
+ * complete: the deferred add path writes exactly the fields given and does NOT
9
+ * zero-default omitted ones (unlike Template/direct spawn), so an omitted f64
10
+ * field would read back NaN. Provide every field (use `0` for "default"); a tag
11
+ * component takes `{}`. Build type-safely with `spawnEntry`. */
12
+ export interface SpawnEntry {
13
+ readonly def: ComponentDef;
14
+ readonly values: FieldValues<ComponentSchema>;
15
+ }
16
+ /** Type-checked `SpawnEntry` constructor — keeps `values` aligned to `def`'s
17
+ * schema at the call site even though the stored entry is schema-erased. */
18
+ export declare function spawnEntry<S extends ComponentSchema>(def: ComponentDef<S>, values: FieldValues<S>): SpawnEntry;
19
+ /**
20
+ * A single world mutation, as plain data. Every transport (typed queue today, a
21
+ * SAB ring codec tomorrow) and every consumer (editor undo, record/replay)
22
+ * speaks this one vocabulary, applied by the one `applyHostCommand` dispatch.
23
+ *
24
+ * Component fields are `string` / `def: ComponentDef` (schema-erased) so the
25
+ * union stays flat; the typed `HostCommandQueue` methods preserve type-safety at
26
+ * the enqueue site. `applyHostCommand` re-applies them through `SystemContext`,
27
+ * which type-checks because `ComponentDef` defaults its schema to
28
+ * `ComponentSchema` (whose `keyof` is `string`).
29
+ */
30
+ export type HostCommand = {
31
+ readonly kind: "spawn";
32
+ readonly components: readonly SpawnEntry[];
33
+ /** Fired with the new id once the spawn applies (the id only exists
34
+ * after the deferred create) — lets a producer/editor learn it. */
35
+ readonly onSpawned?: (eid: EntityID) => void;
36
+ } | {
37
+ readonly kind: "despawn";
38
+ readonly eid: EntityID;
39
+ } | {
40
+ readonly kind: "add_component";
41
+ readonly eid: EntityID;
42
+ readonly def: ComponentDef;
43
+ readonly values: FieldValues<ComponentSchema>;
44
+ } | {
45
+ readonly kind: "remove_component";
46
+ readonly eid: EntityID;
47
+ readonly def: ComponentDef;
48
+ } | {
49
+ readonly kind: "set_field";
50
+ readonly eid: EntityID;
51
+ readonly def: ComponentDef;
52
+ readonly field: string;
53
+ readonly value: number;
54
+ } | {
55
+ readonly kind: "disable";
56
+ readonly eid: EntityID;
57
+ } | {
58
+ readonly kind: "enable";
59
+ readonly eid: EntityID;
60
+ };
61
+ /**
62
+ * THE ONE APPLY DISPATCH. Maps a `HostCommand` onto `SystemContext` ops. Only
63
+ * ever called from inside the blessed apply system, which holds the `ctx` and is
64
+ * `exclusive` (full access). Structural changes (`spawn`/`despawn`/component
65
+ * add-remove) are deferred to the phase flush, exactly like a normal system's;
66
+ * `setField` is immediate and bumps the change-tick. Returns the new entity for
67
+ * `spawn`, otherwise `undefined`.
68
+ *
69
+ * That immediate/deferred split is a sharp edge: a `setField` targeting a
70
+ * component the entity does NOT yet have — because an `addComponent`/`spawn`
71
+ * enqueued in the SAME drain is still pending its flush — would otherwise fail
72
+ * deep in `getColumn` with an opaque "component not registered". The `__DEV__`
73
+ * guard below turns that into an actionable message. The fix is structural, not a
74
+ * retry: pass the value in `addComponent`/`spawnEntry` (which carries complete
75
+ * field values), or issue the `setField` on a later frame.
76
+ */
77
+ export declare function applyHostCommand(ctx: SystemContext, cmd: HostCommand): EntityID | undefined;
78
+ /**
79
+ * The host-facing write handle. Mutating methods ENQUEUE (off-schedule, pure);
80
+ * nothing reaches the world until the apply system drains it at the next
81
+ * schedule head. Mirrors Bevy's `Commands` ergonomics over the flat `HostCommand`
82
+ * vocabulary. The returned-from-`installHostCommandSeam` instance is the
83
+ * write counterpart to the reactive bridge's returned `reactiveMap`.
84
+ */
85
+ export declare class HostCommandQueue {
86
+ private readonly queued;
87
+ /** Spawn an entity carrying `components`. `onSpawned` receives the new id
88
+ * once the spawn applies. */
89
+ spawn(components: readonly SpawnEntry[], onSpawned?: (eid: EntityID) => void): void;
90
+ despawn(eid: EntityID): void;
91
+ addComponent<S extends ComponentSchema>(eid: EntityID, def: ComponentDef<S>, values: FieldValues<S>): void;
92
+ removeComponent(eid: EntityID, def: ComponentDef): void;
93
+ /** Set `field` of `def` on `eid`. Applied IMMEDIATELY at the drain, unlike the
94
+ * deferred structural ops — so `def` must already be on `eid`. Do NOT
95
+ * `addComponent`/`spawn` `def` and `setField` it in the same frame: the add is
96
+ * still pending its flush when the immediate set runs (carry the value in
97
+ * `addComponent`/`spawnEntry` instead). `applyHostCommand` throws an
98
+ * actionable error in `__DEV__` if you do. */
99
+ setField<S extends ComponentSchema>(eid: EntityID, def: ComponentDef<S>, field: string & keyof S, value: number): void;
100
+ disable(eid: EntityID): void;
101
+ enable(eid: EntityID): void;
102
+ /** Enqueue a pre-built command. The path for a SAB-ring codec, an editor's
103
+ * reified inverse, or a replay log — all of which produce `HostCommand` data
104
+ * directly rather than calling the typed sugar above. */
105
+ push(cmd: HostCommand): void;
106
+ /** Commands buffered but not yet applied. */
107
+ pending(): number;
108
+ /**
109
+ * Apply and clear every buffered command. Called by the blessed apply system
110
+ * inside its schedule span; not part of the host-facing surface. Returns the
111
+ * count applied.
112
+ *
113
+ * `tap`, when present, is invoked with each command in apply order just before
114
+ * it is applied — the record/replay hook ({@link HostCommandRecorder}). It is
115
+ * an OPT-IN observer: the tap-free path keeps the original tight loop, so an
116
+ * un-recorded drain pays nothing (#702).
117
+ */
118
+ drain(ctx: SystemContext, tap?: (cmd: HostCommand) => void): number;
119
+ }
120
+ /** Bytes of the payload region inside one `command_ring` slot (15). The slot's
121
+ * leading byte is the opCode; `COMMAND_RING_SLOT_BYTES` (16) is the whole slot. */
122
+ export declare const HOST_COMMAND_PAYLOAD_BYTES: number;
123
+ /**
124
+ * Ring codec for a `setField` on a FIXED `(def, field)`. The component + field
125
+ * are bound INTO the codec, not carried in the bytes — the consumer-owned-codec
126
+ * rule (mirroring `command_dispatch`): the engine ships the mechanism, a
127
+ * consumer's codec knows which component+field an opcode means.
128
+ *
129
+ * Payload (15 B): `[ eid: u32 LE @0 ][ value: f64 LE @4 ][ _reserved: 3 B @12 ]`
130
+ *
131
+ * `value` rides as `f64` (covers every numeric column type losslessly within
132
+ * range); the trailing 3 bytes stay zero. Packing the id as `u32` is what makes
133
+ * `setField` fit the 15-byte slot.
134
+ */
135
+ export declare function ringSetFieldCodec<S extends ComponentSchema>(def: ComponentDef<S>, field: string & keyof S): PayloadCodec<HostCommand>;
136
+ /** Ring codec for `despawn` — `[ eid: u32 LE @0 ]`, trailing 11 B reserved-zero. */
137
+ export declare function ringDespawnCodec(): PayloadCodec<HostCommand>;
138
+ /** Ring codec for `disable` — `[ eid: u32 LE @0 ]`, trailing 11 B reserved-zero. */
139
+ export declare function ringDisableCodec(): PayloadCodec<HostCommand>;
140
+ /** Ring codec for `enable` — `[ eid: u32 LE @0 ]`, trailing 11 B reserved-zero. */
141
+ export declare function ringEnableCodec(): PayloadCodec<HostCommand>;
142
+ /**
143
+ * Ring codec for `removeComponent` of a FIXED `def` — `[ eid: u32 LE @0 ]`, the
144
+ * component bound into the codec (consumer-owned-codec rule). `spawn` /
145
+ * `addComponent` are deliberately absent: they carry component field values
146
+ * that don't fit the 15-byte slot generically, so they stay typed-transport-only
147
+ * (the prototype's finding — the in-process queue has no width limit).
148
+ */
149
+ export declare function ringRemoveComponentCodec(def: ComponentDef): PayloadCodec<HostCommand>;
150
+ /** A ctx-aware applier for one ring opcode: runs on the system `ctx` (which the
151
+ * apply system holds) with the raw 15-byte payload. `tap`, when present, is the
152
+ * record/replay hook (#702) — a generic, `onCommand`-bound applier decodes the
153
+ * slot to a `HostCommand` and feeds it to `tap` before applying, so ring-sourced
154
+ * commands land in the same log as typed-queue ones. A raw `on` applier (a
155
+ * consumer's own non-`HostCommand` op, e.g. the game's `spawn_unit`) has no
156
+ * `HostCommand` to surface and simply ignores `tap`. */
157
+ export type RingCommandApplier = (ctx: SystemContext, payload: Uint8Array, tap?: (cmd: HostCommand) => void) => void;
158
+ /**
159
+ * Drains the SAB `command_ring` as the second host-command transport, dispatching
160
+ * each opcode to a bound applier. Two binding styles:
161
+ *
162
+ * - `onCommand(op, codec)` — decode the slot to a `HostCommand` and run it
163
+ * through the ONE `applyHostCommand` (the same dispatch the typed queue
164
+ * uses). This is the generic cross-thread / wire host-write path.
165
+ * - `on(op, applier)` — a raw ctx-aware handler for a consumer's OWN ring ops
166
+ * that aren't generic host commands (e.g. the game's `spawn_unit`, which runs
167
+ * a BFS placement + game spawn). Same drain, same ring: the "one bus".
168
+ *
169
+ * Opcodes + codecs are CONSUMER-supplied — the engine ships the mechanism and the
170
+ * `ring_*_codec` factories, never the opcode numbers (mirrors `command_dispatch`).
171
+ *
172
+ * Exactly ONE dispatcher should drain a given ring — a second drain would consume
173
+ * the first's slots. The in-process apply system passes its dispatcher via
174
+ * `installHostCommandSeam({ ring })`; a system that owns a timing-coupled drain
175
+ * point (e.g. `wave_spawn`, which must drain between the spatial-index build and
176
+ * the flow-field rebuild) constructs one and calls `drain` itself.
177
+ */
178
+ export declare class HostCommandDispatcher {
179
+ private readonly appliers;
180
+ /** Bind a raw ctx-aware applier to `opCode`. Re-binding replaces. */
181
+ on(opCode: number, applier: RingCommandApplier): this;
182
+ /** Bind a `HostCommand` codec to `opCode`: each matching slot is decoded and
183
+ * run through `applyHostCommand` — the SAME dispatch the typed queue uses.
184
+ * A drain-time `tap` (record/replay, #702) sees the decoded command before it
185
+ * applies, so ring-sourced commands share one log with the typed transport. */
186
+ onCommand(opCode: number, codec: PayloadCodec<HostCommand>): this;
187
+ /** Drain every pending slot, dispatching each to its bound applier. Unbound
188
+ * opcodes are skipped (the read head still advances — matching
189
+ * `drainCommandRing` / `CommandDispatcher`). Returns slots drained. `tap`,
190
+ * when present, is forwarded to each applier as the record/replay hook (#702);
191
+ * only `onCommand`-bound (generic `HostCommand`) opcodes surface to it. */
192
+ drain(ctx: SystemContext, view: DataView, ringOff: number, tap?: (cmd: HostCommand) => void): number;
193
+ }
194
+ /**
195
+ * A per-tick sink the apply system feeds drained commands into — the record side
196
+ * of record/replay (#702). Declared structurally HERE (not imported from
197
+ * `command_log.ts`) so the seam needs no dependency on the recorder: the one-way
198
+ * edge is `command_log` → `host_commands`, never back. {@link HostCommandRecorder}
199
+ * is the in-tree implementation.
200
+ *
201
+ * The protocol the apply system follows: at each UPDATE-phase drain it calls
202
+ * `openTick(tick, dt)` to open that tick's bucket; STARTUP-phase drains skip
203
+ * `openTick`, so seed-time commands land in the recorder's startup bucket. Then
204
+ * every applied command (both transports) is handed to `record`.
205
+ */
206
+ export interface HostCommandSink {
207
+ /** Open (or reuse) the bucket for update `tick` with its `dt`. Multiple drains
208
+ * in one tick (several update phases) reuse the one bucket. */
209
+ openTick(tick: number, dt: number): void;
210
+ /** Record one applied command, in apply order. Pre-bound so it can be passed
211
+ * straight as a drain `tap` without per-tick closure allocation. */
212
+ readonly record: (cmd: HostCommand) => void;
213
+ }
214
+ /** Options for {@link installHostCommandSeam}. */
215
+ export interface HostCommandSeamOptions {
216
+ /** Schedule phases whose head drains the queue. Default
217
+ * `[PRE_STARTUP, PRE_UPDATE]` — seed-time edits plus every frame. */
218
+ readonly schedules?: readonly SCHEDULE[];
219
+ /** Apply-system name (diagnostics). Default `"host_command_apply"`. */
220
+ readonly name?: string;
221
+ /** When provided, the apply system ALSO drains the world's SAB `command_ring`
222
+ * through this dispatcher at each schedule head — the cross-thread / wire
223
+ * transport, resolving to the same `applyHostCommand` as the typed queue.
224
+ * The ECS `Store` always allocates a ring; if one is somehow absent
225
+ * (`command_ring_off === 0`) the ring drain is a no-op. Bind opcodes with the
226
+ * `ring_*_codec` factories, or `dispatcher.on` for a consumer's own ops. */
227
+ readonly ring?: HostCommandDispatcher;
228
+ /** When provided, every command the apply system drains — from BOTH transports
229
+ * (typed queue + `onCommand`-bound ring ops) — is logged into this sink,
230
+ * tagged with the tick + `dt`, for record/replay (#702). Off by default: an
231
+ * un-recorded seam keeps the original tap-free drain and pays nothing.
232
+ * {@link HostCommandRecorder} is the in-tree sink; replay it with
233
+ * `replayCommandLog`. */
234
+ readonly recorder?: HostCommandSink;
235
+ }
236
+ /**
237
+ * Install the write seam on `world`: registers the blessed `exclusive`
238
+ * command-apply system at the head of the given schedules and returns the
239
+ * {@link HostCommandQueue} to enqueue into. Opt-in and explicit, symmetric to
240
+ * the read bridge's `syncComponentToMap`.
241
+ *
242
+ * Call this BEFORE adding your own systems and BEFORE `world.startup()`: the
243
+ * apply system must be registered first so insertion order runs it at the head
244
+ * of its phase (the schedule has no dedicated "first" slot), and the PRE_STARTUP
245
+ * drain only fires if it exists before startup.
246
+ *
247
+ * Lives in engine CORE (not extensions): unlike the read bridge there is no
248
+ * external reactive kernel to quarantine — this is pure ECS plumbing over the
249
+ * deferred buffers and `SystemContext` the core already owns.
250
+ */
251
+ export declare function installHostCommandSeam(world: ECS, opts?: HostCommandSeamOptions): HostCommandQueue;
252
+ //# sourceMappingURL=host_commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host_commands.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/host_commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ export { ECS, type ECSOptions } from './ecs';
2
+ export { resolveECSMemory, DEFAULT_ECS_CAP_BYTES, BUDGET_GROWTH_HEADROOM, BUDGET_DEFAULT_BYTES_PER_ENTITY, BUDGET_DEFAULT_ARCHETYPES, type ECSMemoryOptions, type ResolvedECSMemory, type ECSMemoryCapContext, type EntityBudget, type WasmMemoryArm } from './ecs_memory';
3
+ export type { Template, TemplateEntry, TemplateEntries, TemplateOverrides } from './store';
4
+ export type { StoreLayoutListener } from './store_layout_listener';
5
+ export type { ComputeBackend, BackendSystemHandle } from './compute_backend';
6
+ export { SCHEDULE, type SystemEntry, type SystemOrdering, type SystemOrderingTarget, systemSet, type SystemSet, type SystemSetConfig } from './schedule';
7
+ export { type RunCondition, type ConditionContext, runIfResourceEq, runEveryNTicks, runIfAnyMatch } from './run_condition';
8
+ export { SystemContext } from './query';
9
+ export type { SystemFn, SystemConfig, SystemDescriptor, SystemAccessConfig, SystemAccessDeclaration, SystemTransition } from './system';
10
+ export { accessCheck } from './access_check';
11
+ export type { ObserverConfig, ObserverHandle, ObserverFn, ArchetypeObserverFn, StructuralObserverConfig, EntitySetObserverConfig, ArchetypeSetObserverConfig } from './observer';
12
+ export { installHostCommandSeam, applyHostCommand, HostCommandQueue, HostCommandDispatcher, spawnEntry, ringSetFieldCodec, ringDespawnCodec, ringDisableCodec, ringEnableCodec, ringRemoveComponentCodec, HOST_COMMAND_PAYLOAD_BYTES } from './host_commands';
13
+ export type { HostCommand, SpawnEntry, HostCommandSeamOptions, HostCommandSink, RingCommandApplier } from './host_commands';
14
+ export { HostCommandRecorder, serializeCommandLog, deserializeCommandLog, replayCommandLog } from './command_log';
15
+ export type { CommandLog, RecordedTick, ReplayResult, ReplayOptions } from './command_log';
16
+ export { FrameTraceRecorder } from './frame_trace';
17
+ export type { FrameTraceSink, FrameTrace, FrameTraceEvent, StructuralOp, ObserverOp } from './frame_trace';
18
+ export { WorldRestoreError, WORLD_SNAPSHOT_VERSION } from './resume';
19
+ export type { ComponentRef, ReadonlyComponentRef } from './ref';
20
+ export { Query, QueryBuilder, ChangedQuery, HIERARCHY_UNBOUNDED } from './query';
21
+ export type { HierarchyTerm } from './query';
22
+ export { ChunkColumns, Commands } from './query';
23
+ export type { ArchetypeView, ArchetypeID } from './archetype';
24
+ export type { EntityID, ReadonlyEntityIdArray } from './entity';
25
+ export { getEntityIndex } from './entity';
26
+ export { createEntityId, getEntityGeneration, MAX_INDEX, MAX_GENERATION, MAX_LIVE_GENERATION, RETIRED_GENERATION, MAX_ENTITY_ID } from './entity';
27
+ export type { ComponentDef, ComponentHandle, ComponentSchema, FieldValues, TagToTypedArray, ColumnsForSchema, MutableColumnsForSchema, ReadonlyColumn, ReadonlyUint32Array } from './component';
28
+ export { bundle } from './component';
29
+ export type { Bundle, BundleOrDef } from './component';
30
+ export type { SparseComponentDef, SparseComponentID } from './sparse_store';
31
+ export { SparseRestoreError } from './sparse_store';
32
+ export type { RelationDef, RelationID, RelationOptions, OnDeleteTarget } from './relation';
33
+ export { ANY_RELATION } from './relation';
34
+ export { registerIsA, registerChildOf, type BuiltinRelationOptions } from './builtin_relations';
35
+ export type { EventReader, EventKey, EventSchema, EmptyEventSchema, SignalKey } from './event';
36
+ export { eventKey, signalKey } from './event';
37
+ export type { ResourceKey } from './resource';
38
+ export { resourceKey } from './resource';
39
+ export { dispatchTrace, type DispatchTraceSnapshot, type DispatchTraceEntry } from './dispatch_trace';
40
+ export { ECSError, ECS_ERROR, isEcsError } from './utils/error';
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ import { ArchetypeView } from './archetype';
2
+ import { ComponentDef } from './component';
3
+ import { EntityID } from './entity';
4
+ import { SystemContext } from './query';
5
+ import { Store, StructuralObserverEvents } from './store';
6
+ import { SystemAccessDeclaration, SystemDescriptor } from './system';
7
+ /** Per-entity observer callback (onAdd / onRemove / onDisable / onEnable, and
8
+ * per-entity onSet). */
9
+ export type ObserverFn = (eid: EntityID, ctx: SystemContext) => void;
10
+ /** Archetype-granular onSet callback — fires once per changed archetype-column;
11
+ * the consumer iterates `arch.entityCount` rows itself. */
12
+ export type ArchetypeObserverFn = (arch: ArchetypeView, ctx: SystemContext) => void;
13
+ /** Fields common to every observer registration. `access` drives both the
14
+ * dev-mode `accessCheck` and the access-topological firing order; it is merged
15
+ * over an all-empty declaration, so a caller spells out only what it touches. */
16
+ interface ObserverConfigBase {
17
+ onAdd?: ObserverFn;
18
+ onRemove?: ObserverFn;
19
+ /** Fires when an entity carrying this component is *disabled* (#577) — at the
20
+ * deferred toggle drain, once per net transition (ADR-0023). Mirrors `onRemove`:
21
+ * a disable is a soft remove of the whole mask from default queries. An immediate
22
+ * host-side `world.disable()` does not fire (like immediate `addComponent`). */
23
+ onDisable?: ObserverFn;
24
+ /** Fires when an entity carrying this component is *enabled* (#577), symmetric
25
+ * with `onDisable` / `onAdd`. */
26
+ onEnable?: ObserverFn;
27
+ /** Access surface the callbacks touch (reads / writes / spawns / …). Partial:
28
+ * merged over `_INTERNAL_EMPTY_ACCESS`. Undeclared access throws in `__DEV__`. */
29
+ access?: Partial<SystemAccessDeclaration>;
30
+ /** flecs-style replay of current matches on registration (onAdd only — seeds the
31
+ * *enabled* members; a disabled entity is simply absent, matching default-query
32
+ * semantics), for order-independence of register-vs-spawn. */
33
+ yieldExisting?: boolean;
34
+ }
35
+ /** Per-entity onSet: `onSet(eid, ctx)` fires once per changed entity, drained
36
+ * from the opt-in per-row dirty list (registering this enables dirty tracking
37
+ * for the component — the ADR-0012 list + dedup bit). */
38
+ export interface EntitySetObserverConfig extends ObserverConfigBase {
39
+ onSet: ObserverFn;
40
+ granularity: "entity";
41
+ }
42
+ /** Archetype-granular onSet (default): `onSet(arch, ctx)` fires once per
43
+ * changed archetype-column (the change tick), in canonical archetype order. Free
44
+ * write path. */
45
+ export interface ArchetypeSetObserverConfig extends ObserverConfigBase {
46
+ onSet: ArchetypeObserverFn;
47
+ granularity?: "archetype";
48
+ }
49
+ /** Structural-only observer — no onSet. */
50
+ export interface StructuralObserverConfig extends ObserverConfigBase {
51
+ onSet?: undefined;
52
+ granularity?: undefined;
53
+ }
54
+ export type ObserverConfig = StructuralObserverConfig | EntitySetObserverConfig | ArchetypeSetObserverConfig;
55
+ /** Handle returned by `world.observe(...)`. `dispose()` unregisters; safe to
56
+ * call more than once. */
57
+ export interface ObserverHandle {
58
+ dispose(): void;
59
+ }
60
+ /**
61
+ * Registry of component observers. Owned by `ECS`; the `Store` calls back into
62
+ * `dispatchStructural` between fixed-point rounds during `flushStructural`,
63
+ * and `ECS.update` calls `dispatchSet` at the post-update detection point.
64
+ */
65
+ export declare class ObserverRegistry {
66
+ private readonly store;
67
+ private readonly ctx;
68
+ private readonly entries;
69
+ /** ComponentID → its observers (structural + onSet). */
70
+ private readonly byCid;
71
+ /** Cached access-topological order; invalidated on register / dispose. */
72
+ private _topo;
73
+ private readonly _addBuckets;
74
+ private readonly _remBuckets;
75
+ private readonly _disBuckets;
76
+ private readonly _enaBuckets;
77
+ private readonly _radixOut;
78
+ private readonly _radixC0;
79
+ private readonly _radixC1;
80
+ private readonly _setDrainCache;
81
+ constructor(store: Store, ctx: SystemContext);
82
+ get count(): number;
83
+ /** The synthesized `SystemDescriptor`s of every registered observer, in
84
+ * registration order (`dispose()` splices entries out, so none are stale).
85
+ * Fed into the `startup()` archetype-prewarm closure so an observer's declared
86
+ * `spawns` / `transitions` create their target archetypes eagerly, exactly as a
87
+ * system's do (#768). Without this an observer-spawned/-transitioned archetype
88
+ * first-touches lazily mid-tick — the one asymmetry left in the otherwise
89
+ * uniform "no lazy archetypes" prewarm. */
90
+ descriptors(): SystemDescriptor[];
91
+ register(def: ComponentDef, config: ObserverConfig): ObserverHandle;
92
+ private _dispose;
93
+ /** Recompute the component's hot-path observation flags from its live
94
+ * observers and push them to the store (which owns the flags + fast-path
95
+ * counters). */
96
+ private _reconfigureComponent;
97
+ private getTopo;
98
+ /**
99
+ * Fire onAdd / onRemove / onDisable / onEnable for one fixed-point round's
100
+ * effective events, in canonical order: access-topological across observers,
101
+ * entity-id order (radix) within each observer. Called by
102
+ * `Store.flushStructural` after the batch commits; observer callbacks may
103
+ * enqueue further structural ops (or toggles) onto the deferred buffers (the
104
+ * store loops until quiescent).
105
+ *
106
+ * The events arrive as flat `(comp, eid)` parallel arrays collected during the
107
+ * flush; we bucket by component once (O(K)), then walk observers in topo order
108
+ * so a producer's writes are visible to a consumer (glitch-free). A round
109
+ * carries either structural (add/rem) OR toggle (dis/ena) events, never both —
110
+ * toggles drain only once add/remove/destroy are quiescent (`flushStructural`)
111
+ * — but we bucket all four uniformly; the empty pairs are no-ops. Within an
112
+ * observer the fire order is remove, add, disable, enable (the "leaving" edges
113
+ * before the "entering" edges).
114
+ */
115
+ dispatchStructural(ev: StructuralObserverEvents): void;
116
+ /** Radix-sort `eids` by entity index (canonical within-observer order), then
117
+ * fire `fn` per entity under the observer's access scope. */
118
+ private _fireEach;
119
+ private _bucket;
120
+ private _clearBuckets;
121
+ /**
122
+ * Fire onSet observers for the current tick, in canonical order. Per-entity
123
+ * onSet drains the opt-in dirty list (once per changed entity); archetype-
124
+ * granular onSet scans the change tick (once per changed archetype-column).
125
+ * Called by `ECS.update` after all phases, with `tick === store._tick`.
126
+ */
127
+ dispatchSet(tick: number): void;
128
+ private _dispatchSetEntity;
129
+ private _dispatchSetArch;
130
+ private _yieldExisting;
131
+ }
132
+ /**
133
+ * O(K) LSD radix sort of entity ids by their 20-bit dense index (two 10-bit
134
+ * passes), in place. This is the canonical within-observer order — *never* a
135
+ * comparator `Array.sort`, which the bench measured at 2–4× the entire flush
136
+ * (`observer_dispatch_probe.ts`). Distinct live entities have distinct indices,
137
+ * so index order is a total canonical order. `out` is scratch (grown to length);
138
+ * `c0` / `c1` are 1024-entry histograms (reused).
139
+ */
140
+ export declare function radixSortByIndex(eids: number[], out: number[], c0: Int32Array, c1: Int32Array): void;
141
+ export {};
142
+ //# sourceMappingURL=observer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/observer.ts"],"names":[],"mappings":"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"}