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