@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.
Files changed (324) hide show
  1. package/CHANGELOG.md +553 -0
  2. package/README.md +207 -267
  3. package/dist/core/ecs/access_check.d.cts +77 -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.cts +486 -0
  7. package/dist/core/ecs/archetype.d.ts +486 -0
  8. package/dist/core/ecs/archetype.d.ts.map +1 -0
  9. package/dist/core/ecs/archetype_graph.d.cts +96 -0
  10. package/dist/core/ecs/archetype_graph.d.ts +96 -0
  11. package/dist/core/ecs/archetype_graph.d.ts.map +1 -0
  12. package/dist/core/ecs/builtin_relations.d.cts +43 -0
  13. package/dist/core/ecs/builtin_relations.d.ts +43 -0
  14. package/dist/core/ecs/builtin_relations.d.ts.map +1 -0
  15. package/dist/core/ecs/command_log.d.cts +116 -0
  16. package/dist/core/ecs/command_log.d.ts +116 -0
  17. package/dist/core/ecs/command_log.d.ts.map +1 -0
  18. package/dist/core/ecs/component.d.cts +176 -0
  19. package/dist/core/ecs/component.d.ts +176 -0
  20. package/dist/core/ecs/component.d.ts.map +1 -0
  21. package/dist/core/ecs/compute_backend.d.cts +37 -0
  22. package/dist/core/ecs/compute_backend.d.ts +37 -0
  23. package/dist/core/ecs/compute_backend.d.ts.map +1 -0
  24. package/dist/core/ecs/debug_names.d.cts +7 -0
  25. package/dist/core/ecs/debug_names.d.ts +7 -0
  26. package/dist/core/ecs/debug_names.d.ts.map +1 -0
  27. package/dist/core/ecs/deferred_commands.d.cts +55 -0
  28. package/dist/core/ecs/deferred_commands.d.ts +55 -0
  29. package/dist/core/ecs/deferred_commands.d.ts.map +1 -0
  30. package/dist/core/ecs/dispatch_trace.d.cts +93 -0
  31. package/dist/core/ecs/dispatch_trace.d.ts +93 -0
  32. package/dist/core/ecs/dispatch_trace.d.ts.map +1 -0
  33. package/dist/core/ecs/ecs.d.cts +562 -0
  34. package/dist/core/ecs/ecs.d.ts +562 -0
  35. package/dist/core/ecs/ecs.d.ts.map +1 -0
  36. package/dist/core/ecs/ecs_memory.d.cts +179 -0
  37. package/dist/core/ecs/ecs_memory.d.ts +179 -0
  38. package/dist/core/ecs/ecs_memory.d.ts.map +1 -0
  39. package/dist/core/ecs/entity.d.cts +34 -0
  40. package/dist/core/ecs/entity.d.ts +34 -0
  41. package/dist/core/ecs/entity.d.ts.map +1 -0
  42. package/dist/core/ecs/entity_allocator.d.cts +59 -0
  43. package/dist/core/ecs/entity_allocator.d.ts +59 -0
  44. package/dist/core/ecs/entity_allocator.d.ts.map +1 -0
  45. package/dist/core/ecs/event.d.cts +79 -0
  46. package/dist/core/ecs/event.d.ts +79 -0
  47. package/dist/core/ecs/event.d.ts.map +1 -0
  48. package/dist/core/ecs/event_registry.d.cts +22 -0
  49. package/dist/core/ecs/event_registry.d.ts +22 -0
  50. package/dist/core/ecs/event_registry.d.ts.map +1 -0
  51. package/dist/core/ecs/facades.d.cts +158 -0
  52. package/dist/core/ecs/facades.d.ts +158 -0
  53. package/dist/core/ecs/facades.d.ts.map +1 -0
  54. package/dist/core/ecs/frame_stepper.d.cts +58 -0
  55. package/dist/core/ecs/frame_stepper.d.ts +58 -0
  56. package/dist/core/ecs/frame_stepper.d.ts.map +1 -0
  57. package/dist/core/ecs/frame_trace.d.cts +133 -0
  58. package/dist/core/ecs/frame_trace.d.ts +133 -0
  59. package/dist/core/ecs/frame_trace.d.ts.map +1 -0
  60. package/dist/core/ecs/host_commands.d.cts +274 -0
  61. package/dist/core/ecs/host_commands.d.ts +274 -0
  62. package/dist/core/ecs/host_commands.d.ts.map +1 -0
  63. package/dist/core/ecs/index.d.cts +46 -0
  64. package/dist/core/ecs/index.d.ts +46 -0
  65. package/dist/core/ecs/index.d.ts.map +1 -0
  66. package/dist/core/ecs/observer.d.cts +173 -0
  67. package/dist/core/ecs/observer.d.ts +173 -0
  68. package/dist/core/ecs/observer.d.ts.map +1 -0
  69. package/dist/core/ecs/query.d.cts +718 -0
  70. package/dist/core/ecs/query.d.ts +718 -0
  71. package/dist/core/ecs/query.d.ts.map +1 -0
  72. package/dist/core/ecs/ref.d.cts +31 -0
  73. package/dist/core/ecs/ref.d.ts +31 -0
  74. package/dist/core/ecs/ref.d.ts.map +1 -0
  75. package/dist/core/ecs/relation.d.cts +243 -0
  76. package/dist/core/ecs/relation.d.ts +243 -0
  77. package/dist/core/ecs/relation.d.ts.map +1 -0
  78. package/dist/core/ecs/relation_service.d.cts +235 -0
  79. package/dist/core/ecs/relation_service.d.ts +235 -0
  80. package/dist/core/ecs/relation_service.d.ts.map +1 -0
  81. package/dist/core/ecs/resource.d.cts +53 -0
  82. package/dist/core/ecs/resource.d.ts +53 -0
  83. package/dist/core/ecs/resource.d.ts.map +1 -0
  84. package/dist/core/ecs/resource_registry.d.cts +20 -0
  85. package/dist/core/ecs/resource_registry.d.ts +20 -0
  86. package/dist/core/ecs/resource_registry.d.ts.map +1 -0
  87. package/dist/core/ecs/resume.d.cts +85 -0
  88. package/dist/core/ecs/resume.d.ts +85 -0
  89. package/dist/core/ecs/resume.d.ts.map +1 -0
  90. package/dist/core/ecs/run_condition.d.cts +81 -0
  91. package/dist/core/ecs/run_condition.d.ts +81 -0
  92. package/dist/core/ecs/run_condition.d.ts.map +1 -0
  93. package/dist/core/ecs/schedule.d.cts +142 -0
  94. package/dist/core/ecs/schedule.d.ts +142 -0
  95. package/dist/core/ecs/schedule.d.ts.map +1 -0
  96. package/dist/core/ecs/snapshot_service.d.cts +94 -0
  97. package/dist/core/ecs/snapshot_service.d.ts +94 -0
  98. package/dist/core/ecs/snapshot_service.d.ts.map +1 -0
  99. package/dist/core/ecs/sparse_store.d.cts +110 -0
  100. package/dist/core/ecs/sparse_store.d.ts +110 -0
  101. package/dist/core/ecs/sparse_store.d.ts.map +1 -0
  102. package/dist/core/ecs/store.d.cts +950 -0
  103. package/dist/core/ecs/store.d.ts +950 -0
  104. package/dist/core/ecs/store.d.ts.map +1 -0
  105. package/dist/core/ecs/store_layout_listener.d.cts +23 -0
  106. package/dist/core/ecs/store_layout_listener.d.ts +23 -0
  107. package/dist/core/ecs/store_layout_listener.d.ts.map +1 -0
  108. package/dist/core/ecs/system.d.cts +250 -0
  109. package/dist/core/ecs/system.d.ts +250 -0
  110. package/dist/core/ecs/system.d.ts.map +1 -0
  111. package/dist/core/ecs/utils/arrays.d.cts +7 -0
  112. package/dist/{utils → core/ecs/utils}/arrays.d.ts +2 -1
  113. package/dist/core/ecs/utils/arrays.d.ts.map +1 -0
  114. package/dist/core/ecs/utils/constants.d.ts +12 -0
  115. package/dist/core/ecs/utils/constants.d.ts.map +1 -0
  116. package/dist/core/ecs/utils/error.d.cts +61 -0
  117. package/dist/core/ecs/utils/error.d.ts +61 -0
  118. package/dist/core/ecs/utils/error.d.ts.map +1 -0
  119. package/dist/core/store/action_ring.d.cts +136 -0
  120. package/dist/core/store/action_ring.d.ts +136 -0
  121. package/dist/core/store/action_ring.d.ts.map +1 -0
  122. package/dist/core/store/allocator.d.cts +238 -0
  123. package/dist/core/store/allocator.d.ts +238 -0
  124. package/dist/core/store/allocator.d.ts.map +1 -0
  125. package/dist/core/store/buffer_backed_column.d.cts +69 -0
  126. package/dist/core/store/buffer_backed_column.d.ts +69 -0
  127. package/dist/core/store/buffer_backed_column.d.ts.map +1 -0
  128. package/dist/core/store/column_store.d.cts +273 -0
  129. package/dist/core/store/column_store.d.ts +273 -0
  130. package/dist/core/store/column_store.d.ts.map +1 -0
  131. package/dist/core/store/command_dispatch.d.cts +52 -0
  132. package/dist/core/store/command_dispatch.d.ts +52 -0
  133. package/dist/core/store/command_dispatch.d.ts.map +1 -0
  134. package/dist/core/store/command_ring.d.cts +107 -0
  135. package/dist/core/store/command_ring.d.ts +107 -0
  136. package/dist/core/store/command_ring.d.ts.map +1 -0
  137. package/dist/core/store/descriptor.d.cts +80 -0
  138. package/dist/core/store/descriptor.d.ts +80 -0
  139. package/dist/core/store/descriptor.d.ts.map +1 -0
  140. package/dist/core/store/entity_index.d.cts +108 -0
  141. package/dist/core/store/entity_index.d.ts +108 -0
  142. package/dist/core/store/entity_index.d.ts.map +1 -0
  143. package/dist/core/store/event_ring.d.cts +95 -0
  144. package/dist/core/store/event_ring.d.ts +95 -0
  145. package/dist/core/store/event_ring.d.ts.map +1 -0
  146. package/dist/core/store/extend.d.cts +39 -0
  147. package/dist/core/store/extend.d.ts +39 -0
  148. package/dist/core/store/extend.d.ts.map +1 -0
  149. package/dist/core/store/grow.d.cts +34 -0
  150. package/dist/core/store/grow.d.ts +34 -0
  151. package/dist/core/store/grow.d.ts.map +1 -0
  152. package/dist/core/store/header.d.cts +64 -0
  153. package/dist/core/store/header.d.ts +64 -0
  154. package/dist/core/store/header.d.ts.map +1 -0
  155. package/dist/core/store/index.d.cts +17 -0
  156. package/dist/core/store/index.d.ts +17 -0
  157. package/dist/core/store/index.d.ts.map +1 -0
  158. package/dist/core/store/layout_ops.d.cts +152 -0
  159. package/dist/core/store/layout_ops.d.ts +152 -0
  160. package/dist/core/store/layout_ops.d.ts.map +1 -0
  161. package/dist/core/store/region_table.d.cts +74 -0
  162. package/dist/core/store/region_table.d.ts +74 -0
  163. package/dist/core/store/region_table.d.ts.map +1 -0
  164. package/dist/core/store/snapshot.d.cts +43 -0
  165. package/dist/core/store/snapshot.d.ts +43 -0
  166. package/dist/core/store/snapshot.d.ts.map +1 -0
  167. package/dist/core/store/state_hash.d.cts +38 -0
  168. package/dist/core/store/state_hash.d.ts +38 -0
  169. package/dist/core/store/state_hash.d.ts.map +1 -0
  170. package/dist/core/store/store_regions.d.cts +38 -0
  171. package/dist/core/store/store_regions.d.ts +38 -0
  172. package/dist/core/store/store_regions.d.ts.map +1 -0
  173. package/dist/core/store/vendored_abi/abi.d.cts +43 -0
  174. package/dist/core/store/vendored_abi/abi.d.ts +43 -0
  175. package/dist/core/store/vendored_abi/abi.d.ts.map +1 -0
  176. package/dist/dev_flag.d.cts +17 -0
  177. package/dist/dev_flag.d.ts +17 -0
  178. package/dist/dev_flag.d.ts.map +1 -0
  179. package/dist/extensions/editor/editor.d.cts +170 -0
  180. package/dist/extensions/editor/editor.d.ts +170 -0
  181. package/dist/extensions/editor/editor.d.ts.map +1 -0
  182. package/dist/extensions/editor/field_handle.d.cts +40 -0
  183. package/dist/extensions/editor/field_handle.d.ts +40 -0
  184. package/dist/extensions/editor/field_handle.d.ts.map +1 -0
  185. package/dist/extensions/editor/index.cjs +1 -0
  186. package/dist/extensions/editor/index.d.cts +21 -0
  187. package/dist/extensions/editor/index.d.ts +21 -0
  188. package/dist/extensions/editor/index.d.ts.map +1 -0
  189. package/dist/extensions/editor/index.js +237 -0
  190. package/dist/extensions/reactive/ecs_sync.d.cts +214 -0
  191. package/dist/extensions/reactive/ecs_sync.d.ts +214 -0
  192. package/dist/extensions/reactive/ecs_sync.d.ts.map +1 -0
  193. package/dist/extensions/reactive/index.cjs +1 -0
  194. package/dist/extensions/reactive/index.d.cts +23 -0
  195. package/dist/extensions/reactive/index.d.ts +23 -0
  196. package/dist/extensions/reactive/index.d.ts.map +1 -0
  197. package/dist/extensions/reactive/index.js +215 -0
  198. package/dist/extensions/solid/index.cjs +1 -0
  199. package/dist/extensions/solid/index.d.cts +6 -0
  200. package/dist/extensions/solid/index.d.ts +6 -0
  201. package/dist/extensions/solid/index.d.ts.map +1 -0
  202. package/dist/extensions/solid/index.js +36 -0
  203. package/dist/extensions/solid/kernel_solid.d.cts +45 -0
  204. package/dist/extensions/solid/kernel_solid.d.ts +45 -0
  205. package/dist/extensions/solid/kernel_solid.d.ts.map +1 -0
  206. package/dist/host_commands-BF8QMi3c.cjs +1 -0
  207. package/dist/host_commands-i4cAeyL5.js +2318 -0
  208. package/dist/index.cjs +1 -1
  209. package/dist/index.d.cts +66 -0
  210. package/dist/index.d.ts +65 -12
  211. package/dist/index.d.ts.map +1 -1
  212. package/dist/index.js +7080 -1289
  213. package/dist/internal.cjs +2 -0
  214. package/dist/internal.d.cts +20 -0
  215. package/dist/internal.d.ts +20 -0
  216. package/dist/internal.d.ts.map +1 -0
  217. package/dist/internal.js +141 -0
  218. package/dist/interop-CT-REx0W.cjs +1 -0
  219. package/dist/interop-CcY6ASQc.js +18 -0
  220. package/dist/kernel-DgyrLFjW.js +227 -0
  221. package/dist/kernel-yWV3XnAb.cjs +1 -0
  222. package/dist/primitives.cjs +1 -0
  223. package/dist/primitives.d.cts +18 -0
  224. package/dist/primitives.d.ts +18 -0
  225. package/dist/primitives.d.ts.map +1 -0
  226. package/dist/primitives.js +45 -0
  227. package/dist/reactive/array.d.cts +24 -0
  228. package/dist/reactive/array.d.ts +24 -0
  229. package/dist/reactive/array.d.ts.map +1 -0
  230. package/dist/reactive/index.cjs +1 -0
  231. package/dist/reactive/index.d.cts +11 -0
  232. package/dist/reactive/index.d.ts +11 -0
  233. package/dist/reactive/index.d.ts.map +1 -0
  234. package/dist/reactive/index.js +18 -0
  235. package/dist/reactive/interop.d.cts +19 -0
  236. package/dist/reactive/interop.d.ts +19 -0
  237. package/dist/reactive/interop.d.ts.map +1 -0
  238. package/dist/reactive/kernel.d.cts +73 -0
  239. package/dist/reactive/kernel.d.ts +73 -0
  240. package/dist/reactive/kernel.d.ts.map +1 -0
  241. package/dist/reactive/map.d.cts +16 -0
  242. package/dist/reactive/map.d.ts +16 -0
  243. package/dist/reactive/map.d.ts.map +1 -0
  244. package/dist/reactive/shallow.d.cts +11 -0
  245. package/dist/reactive/shallow.d.ts +11 -0
  246. package/dist/reactive/shallow.d.ts.map +1 -0
  247. package/dist/reactive/struct.d.cts +10 -0
  248. package/dist/reactive/struct.d.ts +10 -0
  249. package/dist/reactive/struct.d.ts.map +1 -0
  250. package/dist/shallow-DQ8aG51_.cjs +1 -0
  251. package/dist/shallow-DfnAm9vG.js +150 -0
  252. package/dist/shared-BU1Cd40h.js +103 -0
  253. package/dist/shared-BymrGTyR.cjs +1 -0
  254. package/dist/shared.cjs +1 -0
  255. package/dist/shared.d.cts +22 -0
  256. package/dist/shared.d.ts +22 -0
  257. package/dist/shared.d.ts.map +1 -0
  258. package/dist/shared.js +7 -0
  259. package/dist/topological_sort-BDvEyb9W.cjs +1 -0
  260. package/dist/topological_sort-DK6EjpWa.js +135 -0
  261. package/dist/type_primitives/assertions.d.cts +32 -0
  262. package/dist/type_primitives/assertions.d.ts +25 -9
  263. package/dist/type_primitives/assertions.d.ts.map +1 -1
  264. package/dist/type_primitives/binary_heap/binary_heap.d.cts +37 -0
  265. package/dist/type_primitives/binary_heap/binary_heap.d.ts +6 -2
  266. package/dist/type_primitives/binary_heap/binary_heap.d.ts.map +1 -1
  267. package/dist/type_primitives/bitset/bitset.d.cts +54 -0
  268. package/dist/type_primitives/bitset/bitset.d.ts +16 -4
  269. package/dist/type_primitives/bitset/bitset.d.ts.map +1 -1
  270. package/dist/type_primitives/brand.d.cts +23 -0
  271. package/dist/type_primitives/brand.d.ts +6 -1
  272. package/dist/type_primitives/brand.d.ts.map +1 -1
  273. package/dist/type_primitives/error.d.cts +16 -0
  274. package/dist/type_primitives/error.d.ts +8 -3
  275. package/dist/type_primitives/error.d.ts.map +1 -1
  276. package/dist/type_primitives/index.d.cts +13 -0
  277. package/dist/type_primitives/index.d.ts +12 -9
  278. package/dist/type_primitives/index.d.ts.map +1 -1
  279. package/dist/type_primitives/sparse_map/sparse_map.d.cts +30 -0
  280. package/dist/type_primitives/sparse_map/sparse_map.d.ts +7 -3
  281. package/dist/type_primitives/sparse_map/sparse_map.d.ts.map +1 -1
  282. package/dist/type_primitives/sparse_set/sparse_set.d.cts +28 -0
  283. package/dist/type_primitives/sparse_set/sparse_set.d.ts +4 -0
  284. package/dist/type_primitives/sparse_set/sparse_set.d.ts.map +1 -1
  285. package/dist/type_primitives/topological_sort/topological_sort.d.cts +29 -0
  286. package/dist/type_primitives/topological_sort/topological_sort.d.ts +7 -3
  287. package/dist/type_primitives/topological_sort/topological_sort.d.ts.map +1 -1
  288. package/dist/type_primitives/typed_arrays/typed_arrays.d.cts +127 -0
  289. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts +53 -16
  290. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts.map +1 -1
  291. package/dist/typed_arrays-BcXcnzB4.js +258 -0
  292. package/dist/typed_arrays-D3NmwtCG.cjs +1 -0
  293. package/dist/utils/error.d.cts +6 -0
  294. package/dist/utils/error.d.ts +2 -20
  295. package/dist/utils/error.d.ts.map +1 -1
  296. package/dist/version.d.cts +10 -0
  297. package/dist/version.d.ts +10 -0
  298. package/dist/version.d.ts.map +1 -0
  299. package/package.json +115 -5
  300. package/dist/archetype.d.ts +0 -108
  301. package/dist/archetype.d.ts.map +0 -1
  302. package/dist/component.d.ts +0 -45
  303. package/dist/component.d.ts.map +0 -1
  304. package/dist/ecs.d.ts +0 -104
  305. package/dist/ecs.d.ts.map +0 -1
  306. package/dist/entity.d.ts +0 -11
  307. package/dist/entity.d.ts.map +0 -1
  308. package/dist/event.d.ts +0 -30
  309. package/dist/event.d.ts.map +0 -1
  310. package/dist/query.d.ts +0 -94
  311. package/dist/query.d.ts.map +0 -1
  312. package/dist/ref.d.ts +0 -23
  313. package/dist/ref.d.ts.map +0 -1
  314. package/dist/resource.d.ts +0 -23
  315. package/dist/resource.d.ts.map +0 -1
  316. package/dist/schedule.d.ts +0 -45
  317. package/dist/schedule.d.ts.map +0 -1
  318. package/dist/store.d.ts +0 -118
  319. package/dist/store.d.ts.map +0 -1
  320. package/dist/system.d.ts +0 -16
  321. package/dist/system.d.ts.map +0 -1
  322. package/dist/utils/arrays.d.ts.map +0 -1
  323. package/dist/utils/constants.d.ts.map +0 -1
  324. /package/dist/{utils/constants.d.ts → core/ecs/utils/constants.d.cts} +0 -0
@@ -0,0 +1,235 @@
1
+ import { BitSet, TypedArrayTag } from '../../type_primitives/index.cjs';
2
+ import { Archetype } from './archetype.cjs';
3
+ import { EntityID } from './entity.cjs';
4
+ import { RelationDef, RelationOptions, RelationStore } from './relation.cjs';
5
+ import { SparseComponentDef, SparseComponentID, SparseComponentStore } from './sparse_store.cjs';
6
+ /** What the relation service needs from `Store` — nothing more. The accessor
7
+ * members re-read the live field on every call, so capacity growth that
8
+ * reallocates `entityGenerations` / `entityArchetype` / `entityRow` is always
9
+ * observed; never cache their return values across mutations. */
10
+ export interface RelationServiceHost {
11
+ isAlive(id: EntityID): boolean;
12
+ hasSparse(entityId: EntityID, def: SparseComponentDef): boolean;
13
+ pushSparseStore(fieldNames: string[], fieldTypes: TypedArrayTag[]): SparseComponentDef;
14
+ sparseStoreOf(def: SparseComponentDef): SparseComponentStore;
15
+ sparseStores(): readonly SparseComponentStore[];
16
+ entityGenerations(): Int32Array;
17
+ entityArchetype(): Int32Array;
18
+ entityRow(): Int32Array;
19
+ archetypes(): readonly Archetype[];
20
+ forEachSparseMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], denseArchetypes: readonly Archetype[], cb: (entityId: EntityID) => void, includeDisabled: boolean): void;
21
+ }
22
+ export declare class RelationService {
23
+ private readonly host;
24
+ private readonly relations;
25
+ private _hasTargetCleanup;
26
+ private readonly _hierarchyRadixOut;
27
+ private readonly _hierarchyRadixC0;
28
+ private readonly _hierarchyRadixC1;
29
+ constructor(host: RelationServiceHost);
30
+ /** The registry, indexed by RelationID — the read-only view the Store's
31
+ * `stateHash` / snapshot / restore paths iterate. */
32
+ get stores(): readonly RelationStore[];
33
+ /** Number of registered relations. */
34
+ get count(): number;
35
+ /** Whether any relation registered a non-`orphan` `onDeleteTarget` policy —
36
+ * the destroy paths' gate for `cleanupTarget` (#473). */
37
+ get hasTargetCleanup(): boolean;
38
+ /** Register a relation kind. `exclusive` (the default) → one target per
39
+ * source, stored in a backing `{ target: f64 }` sparse component, so the
40
+ * forward index rides the sparse store and inherits query membership (#469),
41
+ * `stateHash` + snapshot/restore (#470) for free. `multi` → a set of
42
+ * targets per source, backed by a sparse tag for membership plus a side
43
+ * forward index the relation owns. The two cardinalities are mutually
44
+ * exclusive. `onDeleteTarget` selects the cleanup policy run when a target
45
+ * is destroyed — `delete` (cascade-destroy sources), `clear` (drop the link,
46
+ * sources survive), or `orphan` (default: leave it dangling, #473). See
47
+ * ADR-0011 and `relation.ts`.
48
+ *
49
+ * The backing sparse store is resolved and handed to the relation so it can
50
+ * drive forward/membership rows directly — the cardinality-specific
51
+ * interaction is `ExclusiveRelationStore` / `MultiRelationStore`'s, not a
52
+ * branch here (#498). */
53
+ registerRelation(opts?: RelationOptions): RelationDef;
54
+ private relationOf;
55
+ /** Add a `(R, tgt)` pair to `src`. No archetype transition. Exclusive:
56
+ * replaces any existing target (engine-enforced one-per-source), a no-op if
57
+ * `tgt` is already the target. Multi: adds `tgt` to the set, a no-op if
58
+ * already present. A dead `src` *or* `tgt` is caller error: it throws in
59
+ * `DEV` and is a no-op in production — symmetric, so a production build
60
+ * never links a reverse-index entry keyed by a destroyed handle (#495). */
61
+ addRelation(src: EntityID, def: RelationDef, tgt: EntityID): void;
62
+ /** Remove a `(R, tgt)` pair from `src`. No archetype transition. Exclusive:
63
+ * `tgt` is optional and the removal is a no-op when it names a target other
64
+ * than the current one. Multi: omitting `tgt` removes *all* of `src`'s
65
+ * targets; passing one removes just that pair (dropping membership when the
66
+ * set empties). */
67
+ removeRelation(src: EntityID, def: RelationDef, tgt?: EntityID): void;
68
+ /** The single target of `src` under an exclusive relation, or `undefined`.
69
+ * Throws in `DEV` on a multi-target relation (use `targetsOf`). */
70
+ targetOf(src: EntityID, def: RelationDef): EntityID | undefined;
71
+ /** All targets of `src` under `R` — one or zero for exclusive, the full set
72
+ * for multi — ascending by id. */
73
+ targetsOf(src: EntityID, def: RelationDef): EntityID[];
74
+ /** Sources that point at `tgt` under `R` (the reverse index), ascending by
75
+ * id; empty when none. */
76
+ sourcesOf(tgt: EntityID, def: RelationDef): EntityID[];
77
+ /** Whether `src` holds any pair under `R`. */
78
+ hasRelation(src: EntityID, def: RelationDef): boolean;
79
+ /** All `(source, target)` pairs of relation `R` — the `(R, *)` wildcard
80
+ * (#472). Sources are emitted in **canonical entity-index order** (the #470
81
+ * determinism convention): exclusive relations ride the backing sparse
82
+ * store's `canonicalIndices`, multi relations ride the same
83
+ * `forEachCanonicalTargetSet` traversal `stateHash` / `snapshotRelations`
84
+ * use; a multi source's targets follow ascending by id. Empty when the
85
+ * relation holds no pairs. Cold path — allocates the result array (and, for
86
+ * multi, sorts each source's target set); not for per-tick use. The
87
+ * point-query forms are `targetOf` / `targetsOf`. */
88
+ pairsOf(def: RelationDef): readonly (readonly [EntityID, EntityID])[];
89
+ /** Every `(relation, source)` pointing at `tgt`, across **all** registered
90
+ * relation kinds — the `(*, T)` wildcard (#472). Walks the relation registry
91
+ * in id order (each relation's reverse index already returns sources
92
+ * ascending by id), so the result is ordered by relation id then source id.
93
+ * Empty when nothing targets `tgt`. The single-relation form is
94
+ * `sourcesOf(tgt, def)`. */
95
+ sourcesOfAny(tgt: EntityID): readonly (readonly [RelationDef, EntityID])[];
96
+ /** The backing sparse component id of relation `R` — the membership store a
97
+ * `(R, *)` wildcard term (`Query.withRelation`) drives through the shared
98
+ * sparse-match path. Exclusive relations back a `{ target: f64 }` sparse
99
+ * component, multi a tag; both carry per-source membership, so "has any
100
+ * `(R, *)` pair" is exactly membership in this store (including an
101
+ * orphan-dangling source, whose membership row persists — consistent with
102
+ * `pairsOf`). The def is engine-owned and never handed to callers; this hands
103
+ * the query builder only its erased id for the `sparseInclude` list. */
104
+ relationBackingSparseId(def: RelationDef): SparseComponentID;
105
+ /** Drive a `(*, T)` wildcard query (`Query.forEachRelatedTo`): every source
106
+ * related to `target` under **any** relation, intersected with the query's
107
+ * dense mask + sparse require/exclude terms + the default enabled-row filter,
108
+ * each source yielded once. Unions `sourcesOf(target, R)` across every
109
+ * relation into a `Set` (dedup by full `EntityID` — a source related to `T`
110
+ * via two relations is yielded once), then sorts ascending: the cross-relation
111
+ * union has no inherent order, so one cold sort gives a deterministic,
112
+ * canonical `(*, T)` order matching `sourcesOf` / `sourcesOfAny` (which sort
113
+ * the same way). Cold/structural — not a per-tick hot loop over many targets.
114
+ * `sparseInclude`/`sparseExclude` carry both raw sparse terms and the backing
115
+ * stores of any composed `(R, *)` terms, so it intersects with them uniformly. */
116
+ forEachRelationTargetMatch(target: EntityID, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
117
+ /** Reclaim reverse-index memory: drop every relation's reverse entries whose
118
+ * **target** has been destroyed, returning the total dropped across all
119
+ * relations (#491). Under the default `orphan` policy a destroyed target
120
+ * leaves its reverse entry intact until each source re-targets or dies, so a
121
+ * long-lived source that orphan-points at a churn of short-lived targets and
122
+ * never re-targets accumulates dead-target keys without bound. This cold-path
123
+ * hook drops them on demand — call it at scene or snapshot boundaries.
124
+ *
125
+ * Purely a memory reclaim with no observable state change: forward links stay
126
+ * dangling (so `orphan`'s `targetOf`-returns-the-dead-handle contract is
127
+ * unchanged), `stateHash` is unaffected (the reverse index is derived, never
128
+ * folded), and the dropped entries are faithfully rebuilt by snapshot/restore
129
+ * from the surviving forward links (`Store._rebuildRelationIndices`). The only
130
+ * difference a caller can see is `sourcesOf(deadHandle, R)` going from the
131
+ * dangling sources to `[]` — both meaningless once the target is gone.
132
+ * No-op (returns 0) when no relations are registered. */
133
+ compactRelations(): number;
134
+ /** Walk exclusive relation `R` from `src` toward the root, returning the
135
+ * **up**-chain `[src, parent, grandparent, …, root]` (nearest-ancestor-first,
136
+ * inclusive of both endpoints). A source with no target returns `[src]`. The
137
+ * root is the first entity in the chain with no `R`-target, **or** a dangling
138
+ * dead target handle (see below). Throws `RELATION_MODE_MISMATCH` on a multi
139
+ * relation and `RELATION_CYCLE` on a cycle (both `DEV`-only; in production
140
+ * a cycle stops at the repeated node).
141
+ *
142
+ * **Dangling links terminate the chain.** Under the `orphan` policy a source
143
+ * keeps pointing at a destroyed target (a dead handle). The walk must *not*
144
+ * advance through such a handle: the backing store is keyed by entity
145
+ * **index**, so reading the dead handle's index would return whatever now
146
+ * occupies that recycled slot — splicing the chain onto an unrelated entity
147
+ * (the ABA the `EntityID`-keyed reverse index avoids for `cascadeOf`). So a
148
+ * dead next-hop is appended as the chain's (dangling) terminus and the walk
149
+ * stops; the caller can detect it with `isAlive`, exactly as `targetOf`
150
+ * returns a dead handle. */
151
+ ancestorsOf(src: EntityID, def: RelationDef): EntityID[];
152
+ /** The root of `src`'s exclusive-relation chain — the last entity of
153
+ * `ancestorsOf` (the one with no `R`-target). `src` itself when it has no
154
+ * target. If the chain ends in a dangling dead target handle (orphan policy),
155
+ * that handle is the root — `isAlive`-check the result if dangling links are
156
+ * possible. Same `DEV` guards as `ancestorsOf`. */
157
+ rootOf(src: EntityID, def: RelationDef): EntityID;
158
+ /** Walk exclusive relation `R` **down** from `root` over the reverse index,
159
+ * returning the subtree (including `root`) breadth-first — **parents before
160
+ * children** (the `cascade` order). Children of each node come from
161
+ * `sourcesOf` (ascending by id), so the traversal is deterministic. Throws
162
+ * `RELATION_MODE_MISMATCH` on a multi relation and `RELATION_CYCLE` on a cycle
163
+ * (both `DEV`-only; in production an already-visited node is skipped, so
164
+ * it never hangs). */
165
+ cascadeOf(root: EntityID, def: RelationDef): EntityID[];
166
+ /** Purge a destroyed entity from the relation indices — its **source** role
167
+ * only: drop its forward target(s) and unlink it from every target's reverse
168
+ * set. The backing sparse membership row is dropped separately by the Store's
169
+ * `_purgeSparse`, so this must run *before* it (it reads the sparse target
170
+ * field for exclusive relations). The entity's **target** role is left
171
+ * intact: the reverse index is keyed by full `EntityID`, so a recycled slot
172
+ * never aliases the dead target's sources. The destroyed entity's **target**
173
+ * role is handled separately by `cleanupTarget` per each relation's
174
+ * `OnDeleteTarget` policy (#473). Gated by the caller on `count > 0`. */
175
+ purgeSource(entityId: EntityID): void;
176
+ /** Apply each relation's `OnDeleteTarget` policy for a destroyed **target**
177
+ * `targetId` (#473). Walks the registry; for every relation whose reverse
178
+ * index has sources pointing at the dead target:
179
+ *
180
+ * - **`delete`** — append each source to `cascade`; the caller destroys them
181
+ * through the same path, so chains/trees cascade recursively. The sources'
182
+ * own source-role purge (`purgeSource`) drops their forward link and
183
+ * unlinks them from `targetId`'s reverse set, so no reverse entry leaks.
184
+ * - **`clear`** — drop each source's link to the dead target in place via
185
+ * `rs.unlink(src, targetId)` (exclusive drops the row; multi removes the
186
+ * target from the set, dropping membership when it empties). Sources
187
+ * survive — the cardinality bookkeeping is the relation's, not branched here.
188
+ * - **`orphan`** — skipped (the link is left dangling; safe because the
189
+ * reverse key carries the generation).
190
+ *
191
+ * `sourcesOf` returns a fresh snapshot, so mutating the reverse index while
192
+ * iterating is safe. Gated by the caller on `hasTargetCleanup`, so the
193
+ * whole walk is skipped when no relation opts into a non-`orphan` policy. */
194
+ cleanupTarget(targetId: EntityID, cascade: EntityID[]): void;
195
+ /** Fourth query-match path (#581): yield the matched entities — the exact
196
+ * sparse-match intersection (dense mask + sparse require/exclude + the
197
+ * default enabled-row filter) — in canonical **hierarchy depth order** over
198
+ * exclusive relation `R`: depth ascending (parents before children), **entity
199
+ * index ascending within each depth band**. Entities deeper than `maxDepth`
200
+ * are skipped (`Infinity` = unbounded). Only reached via `Query.forEachEntity`
201
+ * on a query carrying a `.hierarchy(R)` term.
202
+ *
203
+ * `.hierarchy(R)` does not narrow the matched set — it reorders it — so an
204
+ * entity with no `R`-parent is a root (depth 0) and is yielded first. Depth is a
205
+ * structural property of the *full* tree (an ancestor outside the matched set
206
+ * still counts toward depth), computed by a memoised upward walk shared across
207
+ * the whole batch, so a shared/deep chain costs O(nodes), not O(nodes²).
208
+ *
209
+ * The canonical order is produced without a comparator sort (which the observer
210
+ * bench measured at 2–4× — `observer.ts`): (1) collect the matched ids via
211
+ * the host's `forEachSparseMatch`; (2) `radixSortByIndex` → entity-index
212
+ * ascending; (3) stable-bucket by depth — since the input is index-ascending
213
+ * and the bucket append is stable, each depth band stays index-ascending.
214
+ * Tuned for the motivating per-tick case (transform propagation): the radix
215
+ * scratch is reused instance state (`_hierarchyRadix*`), so a per-tick pass
216
+ * churns no histograms; the working set (`matched` / `buckets` / `depthMemo` /
217
+ * `visiting`) is still allocated per call, as it must stay call-local for
218
+ * re-entrancy.
219
+ *
220
+ * Exclusive-only — a multi relation throws `RELATION_MODE_MISMATCH` in `DEV`
221
+ * (mirrors `cascadeOf` / `ancestorsOf`); a cycle is a loud `RELATION_CYCLE` in
222
+ * `DEV` and a safe break in production. */
223
+ forEachHierarchyMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], denseArchetypes: readonly Archetype[], relation: RelationDef, maxDepth: number, includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
224
+ /** Depth of entity index `idx` in the exclusive-relation tree backing `store`
225
+ * (root = 0), for `forEachHierarchyMatch`. Memoised across the batch (`memo`),
226
+ * so a shared ancestor chain is walked once. Walks upward via the backing store's
227
+ * target field 0 (mirroring `ancestorsOf`), stopping at: a root (no target), an
228
+ * already-memoised node, or a dangling/dead parent (the child is then treated as
229
+ * a root — never advance through a recycled slot, the ABA `ancestorsOf` guards).
230
+ * `visiting` flags the nodes on the current upward path to catch a cycle —
231
+ * `RELATION_CYCLE` in `DEV`, treated as a root in production — and is emptied
232
+ * on the way back down so it can be reused for the next entity. */
233
+ private _hierarchyDepthOf;
234
+ }
235
+ //# sourceMappingURL=relation_service.d.ts.map
@@ -0,0 +1,235 @@
1
+ import { BitSet, TypedArrayTag } from '../../type_primitives/index.js';
2
+ import { Archetype } from './archetype.js';
3
+ import { EntityID } from './entity.js';
4
+ import { RelationDef, RelationOptions, RelationStore } from './relation.js';
5
+ import { SparseComponentDef, SparseComponentID, SparseComponentStore } from './sparse_store.js';
6
+ /** What the relation service needs from `Store` — nothing more. The accessor
7
+ * members re-read the live field on every call, so capacity growth that
8
+ * reallocates `entityGenerations` / `entityArchetype` / `entityRow` is always
9
+ * observed; never cache their return values across mutations. */
10
+ export interface RelationServiceHost {
11
+ isAlive(id: EntityID): boolean;
12
+ hasSparse(entityId: EntityID, def: SparseComponentDef): boolean;
13
+ pushSparseStore(fieldNames: string[], fieldTypes: TypedArrayTag[]): SparseComponentDef;
14
+ sparseStoreOf(def: SparseComponentDef): SparseComponentStore;
15
+ sparseStores(): readonly SparseComponentStore[];
16
+ entityGenerations(): Int32Array;
17
+ entityArchetype(): Int32Array;
18
+ entityRow(): Int32Array;
19
+ archetypes(): readonly Archetype[];
20
+ forEachSparseMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], denseArchetypes: readonly Archetype[], cb: (entityId: EntityID) => void, includeDisabled: boolean): void;
21
+ }
22
+ export declare class RelationService {
23
+ private readonly host;
24
+ private readonly relations;
25
+ private _hasTargetCleanup;
26
+ private readonly _hierarchyRadixOut;
27
+ private readonly _hierarchyRadixC0;
28
+ private readonly _hierarchyRadixC1;
29
+ constructor(host: RelationServiceHost);
30
+ /** The registry, indexed by RelationID — the read-only view the Store's
31
+ * `stateHash` / snapshot / restore paths iterate. */
32
+ get stores(): readonly RelationStore[];
33
+ /** Number of registered relations. */
34
+ get count(): number;
35
+ /** Whether any relation registered a non-`orphan` `onDeleteTarget` policy —
36
+ * the destroy paths' gate for `cleanupTarget` (#473). */
37
+ get hasTargetCleanup(): boolean;
38
+ /** Register a relation kind. `exclusive` (the default) → one target per
39
+ * source, stored in a backing `{ target: f64 }` sparse component, so the
40
+ * forward index rides the sparse store and inherits query membership (#469),
41
+ * `stateHash` + snapshot/restore (#470) for free. `multi` → a set of
42
+ * targets per source, backed by a sparse tag for membership plus a side
43
+ * forward index the relation owns. The two cardinalities are mutually
44
+ * exclusive. `onDeleteTarget` selects the cleanup policy run when a target
45
+ * is destroyed — `delete` (cascade-destroy sources), `clear` (drop the link,
46
+ * sources survive), or `orphan` (default: leave it dangling, #473). See
47
+ * ADR-0011 and `relation.ts`.
48
+ *
49
+ * The backing sparse store is resolved and handed to the relation so it can
50
+ * drive forward/membership rows directly — the cardinality-specific
51
+ * interaction is `ExclusiveRelationStore` / `MultiRelationStore`'s, not a
52
+ * branch here (#498). */
53
+ registerRelation(opts?: RelationOptions): RelationDef;
54
+ private relationOf;
55
+ /** Add a `(R, tgt)` pair to `src`. No archetype transition. Exclusive:
56
+ * replaces any existing target (engine-enforced one-per-source), a no-op if
57
+ * `tgt` is already the target. Multi: adds `tgt` to the set, a no-op if
58
+ * already present. A dead `src` *or* `tgt` is caller error: it throws in
59
+ * `DEV` and is a no-op in production — symmetric, so a production build
60
+ * never links a reverse-index entry keyed by a destroyed handle (#495). */
61
+ addRelation(src: EntityID, def: RelationDef, tgt: EntityID): void;
62
+ /** Remove a `(R, tgt)` pair from `src`. No archetype transition. Exclusive:
63
+ * `tgt` is optional and the removal is a no-op when it names a target other
64
+ * than the current one. Multi: omitting `tgt` removes *all* of `src`'s
65
+ * targets; passing one removes just that pair (dropping membership when the
66
+ * set empties). */
67
+ removeRelation(src: EntityID, def: RelationDef, tgt?: EntityID): void;
68
+ /** The single target of `src` under an exclusive relation, or `undefined`.
69
+ * Throws in `DEV` on a multi-target relation (use `targetsOf`). */
70
+ targetOf(src: EntityID, def: RelationDef): EntityID | undefined;
71
+ /** All targets of `src` under `R` — one or zero for exclusive, the full set
72
+ * for multi — ascending by id. */
73
+ targetsOf(src: EntityID, def: RelationDef): EntityID[];
74
+ /** Sources that point at `tgt` under `R` (the reverse index), ascending by
75
+ * id; empty when none. */
76
+ sourcesOf(tgt: EntityID, def: RelationDef): EntityID[];
77
+ /** Whether `src` holds any pair under `R`. */
78
+ hasRelation(src: EntityID, def: RelationDef): boolean;
79
+ /** All `(source, target)` pairs of relation `R` — the `(R, *)` wildcard
80
+ * (#472). Sources are emitted in **canonical entity-index order** (the #470
81
+ * determinism convention): exclusive relations ride the backing sparse
82
+ * store's `canonicalIndices`, multi relations ride the same
83
+ * `forEachCanonicalTargetSet` traversal `stateHash` / `snapshotRelations`
84
+ * use; a multi source's targets follow ascending by id. Empty when the
85
+ * relation holds no pairs. Cold path — allocates the result array (and, for
86
+ * multi, sorts each source's target set); not for per-tick use. The
87
+ * point-query forms are `targetOf` / `targetsOf`. */
88
+ pairsOf(def: RelationDef): readonly (readonly [EntityID, EntityID])[];
89
+ /** Every `(relation, source)` pointing at `tgt`, across **all** registered
90
+ * relation kinds — the `(*, T)` wildcard (#472). Walks the relation registry
91
+ * in id order (each relation's reverse index already returns sources
92
+ * ascending by id), so the result is ordered by relation id then source id.
93
+ * Empty when nothing targets `tgt`. The single-relation form is
94
+ * `sourcesOf(tgt, def)`. */
95
+ sourcesOfAny(tgt: EntityID): readonly (readonly [RelationDef, EntityID])[];
96
+ /** The backing sparse component id of relation `R` — the membership store a
97
+ * `(R, *)` wildcard term (`Query.withRelation`) drives through the shared
98
+ * sparse-match path. Exclusive relations back a `{ target: f64 }` sparse
99
+ * component, multi a tag; both carry per-source membership, so "has any
100
+ * `(R, *)` pair" is exactly membership in this store (including an
101
+ * orphan-dangling source, whose membership row persists — consistent with
102
+ * `pairsOf`). The def is engine-owned and never handed to callers; this hands
103
+ * the query builder only its erased id for the `sparseInclude` list. */
104
+ relationBackingSparseId(def: RelationDef): SparseComponentID;
105
+ /** Drive a `(*, T)` wildcard query (`Query.forEachRelatedTo`): every source
106
+ * related to `target` under **any** relation, intersected with the query's
107
+ * dense mask + sparse require/exclude terms + the default enabled-row filter,
108
+ * each source yielded once. Unions `sourcesOf(target, R)` across every
109
+ * relation into a `Set` (dedup by full `EntityID` — a source related to `T`
110
+ * via two relations is yielded once), then sorts ascending: the cross-relation
111
+ * union has no inherent order, so one cold sort gives a deterministic,
112
+ * canonical `(*, T)` order matching `sourcesOf` / `sourcesOfAny` (which sort
113
+ * the same way). Cold/structural — not a per-tick hot loop over many targets.
114
+ * `sparseInclude`/`sparseExclude` carry both raw sparse terms and the backing
115
+ * stores of any composed `(R, *)` terms, so it intersects with them uniformly. */
116
+ forEachRelationTargetMatch(target: EntityID, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
117
+ /** Reclaim reverse-index memory: drop every relation's reverse entries whose
118
+ * **target** has been destroyed, returning the total dropped across all
119
+ * relations (#491). Under the default `orphan` policy a destroyed target
120
+ * leaves its reverse entry intact until each source re-targets or dies, so a
121
+ * long-lived source that orphan-points at a churn of short-lived targets and
122
+ * never re-targets accumulates dead-target keys without bound. This cold-path
123
+ * hook drops them on demand — call it at scene or snapshot boundaries.
124
+ *
125
+ * Purely a memory reclaim with no observable state change: forward links stay
126
+ * dangling (so `orphan`'s `targetOf`-returns-the-dead-handle contract is
127
+ * unchanged), `stateHash` is unaffected (the reverse index is derived, never
128
+ * folded), and the dropped entries are faithfully rebuilt by snapshot/restore
129
+ * from the surviving forward links (`Store._rebuildRelationIndices`). The only
130
+ * difference a caller can see is `sourcesOf(deadHandle, R)` going from the
131
+ * dangling sources to `[]` — both meaningless once the target is gone.
132
+ * No-op (returns 0) when no relations are registered. */
133
+ compactRelations(): number;
134
+ /** Walk exclusive relation `R` from `src` toward the root, returning the
135
+ * **up**-chain `[src, parent, grandparent, …, root]` (nearest-ancestor-first,
136
+ * inclusive of both endpoints). A source with no target returns `[src]`. The
137
+ * root is the first entity in the chain with no `R`-target, **or** a dangling
138
+ * dead target handle (see below). Throws `RELATION_MODE_MISMATCH` on a multi
139
+ * relation and `RELATION_CYCLE` on a cycle (both `DEV`-only; in production
140
+ * a cycle stops at the repeated node).
141
+ *
142
+ * **Dangling links terminate the chain.** Under the `orphan` policy a source
143
+ * keeps pointing at a destroyed target (a dead handle). The walk must *not*
144
+ * advance through such a handle: the backing store is keyed by entity
145
+ * **index**, so reading the dead handle's index would return whatever now
146
+ * occupies that recycled slot — splicing the chain onto an unrelated entity
147
+ * (the ABA the `EntityID`-keyed reverse index avoids for `cascadeOf`). So a
148
+ * dead next-hop is appended as the chain's (dangling) terminus and the walk
149
+ * stops; the caller can detect it with `isAlive`, exactly as `targetOf`
150
+ * returns a dead handle. */
151
+ ancestorsOf(src: EntityID, def: RelationDef): EntityID[];
152
+ /** The root of `src`'s exclusive-relation chain — the last entity of
153
+ * `ancestorsOf` (the one with no `R`-target). `src` itself when it has no
154
+ * target. If the chain ends in a dangling dead target handle (orphan policy),
155
+ * that handle is the root — `isAlive`-check the result if dangling links are
156
+ * possible. Same `DEV` guards as `ancestorsOf`. */
157
+ rootOf(src: EntityID, def: RelationDef): EntityID;
158
+ /** Walk exclusive relation `R` **down** from `root` over the reverse index,
159
+ * returning the subtree (including `root`) breadth-first — **parents before
160
+ * children** (the `cascade` order). Children of each node come from
161
+ * `sourcesOf` (ascending by id), so the traversal is deterministic. Throws
162
+ * `RELATION_MODE_MISMATCH` on a multi relation and `RELATION_CYCLE` on a cycle
163
+ * (both `DEV`-only; in production an already-visited node is skipped, so
164
+ * it never hangs). */
165
+ cascadeOf(root: EntityID, def: RelationDef): EntityID[];
166
+ /** Purge a destroyed entity from the relation indices — its **source** role
167
+ * only: drop its forward target(s) and unlink it from every target's reverse
168
+ * set. The backing sparse membership row is dropped separately by the Store's
169
+ * `_purgeSparse`, so this must run *before* it (it reads the sparse target
170
+ * field for exclusive relations). The entity's **target** role is left
171
+ * intact: the reverse index is keyed by full `EntityID`, so a recycled slot
172
+ * never aliases the dead target's sources. The destroyed entity's **target**
173
+ * role is handled separately by `cleanupTarget` per each relation's
174
+ * `OnDeleteTarget` policy (#473). Gated by the caller on `count > 0`. */
175
+ purgeSource(entityId: EntityID): void;
176
+ /** Apply each relation's `OnDeleteTarget` policy for a destroyed **target**
177
+ * `targetId` (#473). Walks the registry; for every relation whose reverse
178
+ * index has sources pointing at the dead target:
179
+ *
180
+ * - **`delete`** — append each source to `cascade`; the caller destroys them
181
+ * through the same path, so chains/trees cascade recursively. The sources'
182
+ * own source-role purge (`purgeSource`) drops their forward link and
183
+ * unlinks them from `targetId`'s reverse set, so no reverse entry leaks.
184
+ * - **`clear`** — drop each source's link to the dead target in place via
185
+ * `rs.unlink(src, targetId)` (exclusive drops the row; multi removes the
186
+ * target from the set, dropping membership when it empties). Sources
187
+ * survive — the cardinality bookkeeping is the relation's, not branched here.
188
+ * - **`orphan`** — skipped (the link is left dangling; safe because the
189
+ * reverse key carries the generation).
190
+ *
191
+ * `sourcesOf` returns a fresh snapshot, so mutating the reverse index while
192
+ * iterating is safe. Gated by the caller on `hasTargetCleanup`, so the
193
+ * whole walk is skipped when no relation opts into a non-`orphan` policy. */
194
+ cleanupTarget(targetId: EntityID, cascade: EntityID[]): void;
195
+ /** Fourth query-match path (#581): yield the matched entities — the exact
196
+ * sparse-match intersection (dense mask + sparse require/exclude + the
197
+ * default enabled-row filter) — in canonical **hierarchy depth order** over
198
+ * exclusive relation `R`: depth ascending (parents before children), **entity
199
+ * index ascending within each depth band**. Entities deeper than `maxDepth`
200
+ * are skipped (`Infinity` = unbounded). Only reached via `Query.forEachEntity`
201
+ * on a query carrying a `.hierarchy(R)` term.
202
+ *
203
+ * `.hierarchy(R)` does not narrow the matched set — it reorders it — so an
204
+ * entity with no `R`-parent is a root (depth 0) and is yielded first. Depth is a
205
+ * structural property of the *full* tree (an ancestor outside the matched set
206
+ * still counts toward depth), computed by a memoised upward walk shared across
207
+ * the whole batch, so a shared/deep chain costs O(nodes), not O(nodes²).
208
+ *
209
+ * The canonical order is produced without a comparator sort (which the observer
210
+ * bench measured at 2–4× — `observer.ts`): (1) collect the matched ids via
211
+ * the host's `forEachSparseMatch`; (2) `radixSortByIndex` → entity-index
212
+ * ascending; (3) stable-bucket by depth — since the input is index-ascending
213
+ * and the bucket append is stable, each depth band stays index-ascending.
214
+ * Tuned for the motivating per-tick case (transform propagation): the radix
215
+ * scratch is reused instance state (`_hierarchyRadix*`), so a per-tick pass
216
+ * churns no histograms; the working set (`matched` / `buckets` / `depthMemo` /
217
+ * `visiting`) is still allocated per call, as it must stay call-local for
218
+ * re-entrancy.
219
+ *
220
+ * Exclusive-only — a multi relation throws `RELATION_MODE_MISMATCH` in `DEV`
221
+ * (mirrors `cascadeOf` / `ancestorsOf`); a cycle is a loud `RELATION_CYCLE` in
222
+ * `DEV` and a safe break in production. */
223
+ forEachHierarchyMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], denseArchetypes: readonly Archetype[], relation: RelationDef, maxDepth: number, includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
224
+ /** Depth of entity index `idx` in the exclusive-relation tree backing `store`
225
+ * (root = 0), for `forEachHierarchyMatch`. Memoised across the batch (`memo`),
226
+ * so a shared ancestor chain is walked once. Walks upward via the backing store's
227
+ * target field 0 (mirroring `ancestorsOf`), stopping at: a root (no target), an
228
+ * already-memoised node, or a dangling/dead parent (the child is then treated as
229
+ * a root — never advance through a recycled slot, the ABA `ancestorsOf` guards).
230
+ * `visiting` flags the nodes on the current upward path to catch a cycle —
231
+ * `RELATION_CYCLE` in `DEV`, treated as a root in production — and is emptied
232
+ * on the way back down so it can be reused for the next entity. */
233
+ private _hierarchyDepthOf;
234
+ }
235
+ //# sourceMappingURL=relation_service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation_service.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/relation_service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /***
2
+ * Resource — Typed singleton key-value storage.
3
+ *
4
+ * Resources are global singletons that don't belong to any entity.
5
+ * Think: time, input state, camera config, game settings.
6
+ *
7
+ * Each resource is identified by a unique symbol (ResourceKey<T>) and
8
+ * stores an arbitrary typed value. The key carries the value type as a
9
+ * phantom type parameter, so reads are type-safe at compile time.
10
+ *
11
+ * Lifecycle (#798). A resource is register-once *until removed*: a second
12
+ * `registerResource` for a live key throws RESOURCE_ALREADY_REGISTERED, but
13
+ * `removeResource(key)` drops it (failing closed on a missing key) and frees the
14
+ * key to be registered again — the present → absent → present axis. Removal is
15
+ * access-checked as a *write* (a system must declare the key in `resourceWrites`),
16
+ * and resources stay out of `stateHash` and snapshot/resume regardless, so a
17
+ * lifecycle change never perturbs the determinism hash.
18
+ *
19
+ * Usage:
20
+ *
21
+ * const TimeRes = resourceKey<{ delta: number; elapsed: number }>("Time");
22
+ * ecs.resources.register(TimeRes, { delta: 0, elapsed: 0 });
23
+ * const time = ecs.resources.get(TimeRes);
24
+ * // time.delta → number, time.elapsed → number
25
+ * ecs.resources.remove(TimeRes); // present → absent
26
+ * ecs.resources.register(TimeRes, { delta: 0, elapsed: 0 }); // → present again
27
+ *
28
+ ***/
29
+ /**
30
+ * `T` is deliberately INVARIANT (via the function-typed phantom — an `in out`
31
+ * annotation is not legal on an intersection alias, so the structure carries
32
+ * the variance): a key is used for both reads (`resource`, covariant) and
33
+ * writes (`setResource`, contravariant), so either one-sided variance is a
34
+ * soundness hole — a covariant `T` let `ResourceKey<Cat>` widen to
35
+ * `ResourceKey<Animal>` and `setResource` then stored a `Dog` behind a `Cat`
36
+ * key. Invariance also makes keys with different `T` mutually unassignable,
37
+ * which is what the typed system seam's `resourceReads`/`resourceWrites`
38
+ * narrowing keys on (§typestate). Schema-erased positions (access checks,
39
+ * declaration lists) must use `ResourceKey<any>` — `ResourceKey<unknown>` no
40
+ * longer erases.
41
+ */
42
+ declare const __resourceValue: unique symbol;
43
+ export type ResourceKey<T> = symbol & {
44
+ readonly [__resourceValue]: (value: T) => T;
45
+ };
46
+ export declare function resourceKey<T>(name: string): ResourceKey<T>;
47
+ /** Recover a key's value type: `ResourceValueOf<typeof TimeRes>` is the Time
48
+ * shape. The typed `SystemContext` resource surface infers the KEY type (to
49
+ * check it against the declared-access union) and recovers `T` through this,
50
+ * instead of taking `ResourceKey<T>` directly. */
51
+ export type ResourceValueOf<K> = K extends ResourceKey<infer T> ? T : never;
52
+ export {};
53
+ //# sourceMappingURL=resource.d.ts.map
@@ -0,0 +1,53 @@
1
+ /***
2
+ * Resource — Typed singleton key-value storage.
3
+ *
4
+ * Resources are global singletons that don't belong to any entity.
5
+ * Think: time, input state, camera config, game settings.
6
+ *
7
+ * Each resource is identified by a unique symbol (ResourceKey<T>) and
8
+ * stores an arbitrary typed value. The key carries the value type as a
9
+ * phantom type parameter, so reads are type-safe at compile time.
10
+ *
11
+ * Lifecycle (#798). A resource is register-once *until removed*: a second
12
+ * `registerResource` for a live key throws RESOURCE_ALREADY_REGISTERED, but
13
+ * `removeResource(key)` drops it (failing closed on a missing key) and frees the
14
+ * key to be registered again — the present → absent → present axis. Removal is
15
+ * access-checked as a *write* (a system must declare the key in `resourceWrites`),
16
+ * and resources stay out of `stateHash` and snapshot/resume regardless, so a
17
+ * lifecycle change never perturbs the determinism hash.
18
+ *
19
+ * Usage:
20
+ *
21
+ * const TimeRes = resourceKey<{ delta: number; elapsed: number }>("Time");
22
+ * ecs.resources.register(TimeRes, { delta: 0, elapsed: 0 });
23
+ * const time = ecs.resources.get(TimeRes);
24
+ * // time.delta → number, time.elapsed → number
25
+ * ecs.resources.remove(TimeRes); // present → absent
26
+ * ecs.resources.register(TimeRes, { delta: 0, elapsed: 0 }); // → present again
27
+ *
28
+ ***/
29
+ /**
30
+ * `T` is deliberately INVARIANT (via the function-typed phantom — an `in out`
31
+ * annotation is not legal on an intersection alias, so the structure carries
32
+ * the variance): a key is used for both reads (`resource`, covariant) and
33
+ * writes (`setResource`, contravariant), so either one-sided variance is a
34
+ * soundness hole — a covariant `T` let `ResourceKey<Cat>` widen to
35
+ * `ResourceKey<Animal>` and `setResource` then stored a `Dog` behind a `Cat`
36
+ * key. Invariance also makes keys with different `T` mutually unassignable,
37
+ * which is what the typed system seam's `resourceReads`/`resourceWrites`
38
+ * narrowing keys on (§typestate). Schema-erased positions (access checks,
39
+ * declaration lists) must use `ResourceKey<any>` — `ResourceKey<unknown>` no
40
+ * longer erases.
41
+ */
42
+ declare const __resourceValue: unique symbol;
43
+ export type ResourceKey<T> = symbol & {
44
+ readonly [__resourceValue]: (value: T) => T;
45
+ };
46
+ export declare function resourceKey<T>(name: string): ResourceKey<T>;
47
+ /** Recover a key's value type: `ResourceValueOf<typeof TimeRes>` is the Time
48
+ * shape. The typed `SystemContext` resource surface infers the KEY type (to
49
+ * check it against the declared-access union) and recovers `T` through this,
50
+ * instead of taking `ResourceKey<T>` directly. */
51
+ export type ResourceValueOf<K> = K extends ResourceKey<infer T> ? T : never;
52
+ export {};
53
+ //# sourceMappingURL=resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2BK;AAIL;;;;;;;;;;;;GAYG;AACH,OAAO,CAAC,MAAM,eAAe,EAAE,OAAO,MAAM,CAAC;AAE7C,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAA;CAAE,CAAC;AAEtF,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAE3D;AAED;;;kDAGkD;AAClD,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC"}
@@ -0,0 +1,20 @@
1
+ /***
2
+ * ResourceRegistry — the world's symbol-keyed resource dictionary (H1 step 2).
3
+ *
4
+ * Extracted from `Store`, which keeps one-line delegations; fully
5
+ * self-contained (no Store reach-back). Resources stay out of `stateHash` and
6
+ * out of snapshot/resume — this is host-side state, not simulation state.
7
+ ***/
8
+ export declare class ResourceRegistry {
9
+ private readonly map;
10
+ register(key: symbol, value: unknown): void;
11
+ get(key: symbol): unknown;
12
+ set(key: symbol, value: unknown): void;
13
+ /** Drop a resource from the world. Fails closed on a missing key (mirrors
14
+ * `get` / `set`); afterwards the key is free to `register` again — the
15
+ * present → absent → present lifecycle (#798). Purely a host-side
16
+ * dictionary delete with no determinism-hash effect. */
17
+ remove(key: symbol): void;
18
+ has(key: symbol): boolean;
19
+ }
20
+ //# sourceMappingURL=resource_registry.d.ts.map
@@ -0,0 +1,20 @@
1
+ /***
2
+ * ResourceRegistry — the world's symbol-keyed resource dictionary (H1 step 2).
3
+ *
4
+ * Extracted from `Store`, which keeps one-line delegations; fully
5
+ * self-contained (no Store reach-back). Resources stay out of `stateHash` and
6
+ * out of snapshot/resume — this is host-side state, not simulation state.
7
+ ***/
8
+ export declare class ResourceRegistry {
9
+ private readonly map;
10
+ register(key: symbol, value: unknown): void;
11
+ get(key: symbol): unknown;
12
+ set(key: symbol, value: unknown): void;
13
+ /** Drop a resource from the world. Fails closed on a missing key (mirrors
14
+ * `get` / `set`); afterwards the key is free to `register` again — the
15
+ * present → absent → present lifecycle (#798). Purely a host-side
16
+ * dictionary delete with no determinism-hash effect. */
17
+ remove(key: symbol): void;
18
+ has(key: symbol): boolean;
19
+ }
20
+ //# sourceMappingURL=resource_registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource_registry.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/resource_registry.ts"],"names":[],"mappings":"AAAA;;;;;;KAMK;AAIL,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAmC;IAEhD,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAW3C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAWzB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAW7C;;;4DAGwD;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAWzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAGhC"}