@oasys/oecs 0.5.4 → 0.6.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 (510) hide show
  1. package/CHANGELOG.md +1223 -266
  2. package/README.md +217 -112
  3. package/dist/core/ecs/access_check.d.cts +29 -29
  4. package/dist/core/ecs/access_check.d.ts +29 -29
  5. package/dist/core/ecs/access_check.d.ts.map +1 -1
  6. package/dist/core/ecs/archetype.d.cts +217 -209
  7. package/dist/core/ecs/archetype.d.ts +217 -209
  8. package/dist/core/ecs/archetype.d.ts.map +1 -1
  9. package/dist/core/ecs/archetype_closure.d.cts +23 -0
  10. package/dist/core/ecs/archetype_closure.d.ts +23 -0
  11. package/dist/core/ecs/archetype_closure.d.ts.map +1 -0
  12. package/dist/core/ecs/archetype_graph.d.cts +33 -33
  13. package/dist/core/ecs/archetype_graph.d.ts +33 -33
  14. package/dist/core/ecs/archetype_graph.d.ts.map +1 -1
  15. package/dist/core/ecs/archetype_types.d.cts +55 -0
  16. package/dist/core/ecs/archetype_types.d.ts +55 -0
  17. package/dist/core/ecs/archetype_types.d.ts.map +1 -0
  18. package/dist/core/ecs/change_feed.d.cts +53 -0
  19. package/dist/core/ecs/change_feed.d.ts +53 -0
  20. package/dist/core/ecs/change_feed.d.ts.map +1 -0
  21. package/dist/core/ecs/changed_query.d.cts +36 -0
  22. package/dist/core/ecs/changed_query.d.ts +36 -0
  23. package/dist/core/ecs/changed_query.d.ts.map +1 -0
  24. package/dist/core/ecs/chunk_columns.d.cts +49 -0
  25. package/dist/core/ecs/chunk_columns.d.ts +49 -0
  26. package/dist/core/ecs/chunk_columns.d.ts.map +1 -0
  27. package/dist/core/ecs/command_log.d.cts +26 -26
  28. package/dist/core/ecs/command_log.d.ts +26 -26
  29. package/dist/core/ecs/command_log.d.ts.map +1 -1
  30. package/dist/core/ecs/component.d.cts +43 -42
  31. package/dist/core/ecs/component.d.ts +43 -42
  32. package/dist/core/ecs/component.d.ts.map +1 -1
  33. package/dist/core/ecs/component_registry.d.cts +53 -0
  34. package/dist/core/ecs/component_registry.d.ts +53 -0
  35. package/dist/core/ecs/component_registry.d.ts.map +1 -0
  36. package/dist/core/ecs/compute_backend.d.cts +18 -7
  37. package/dist/core/ecs/compute_backend.d.ts +18 -7
  38. package/dist/core/ecs/compute_backend.d.ts.map +1 -1
  39. package/dist/core/ecs/deferred_commands.d.cts +15 -14
  40. package/dist/core/ecs/deferred_commands.d.ts +15 -14
  41. package/dist/core/ecs/deferred_commands.d.ts.map +1 -1
  42. package/dist/core/ecs/dispatch_trace.d.cts +32 -31
  43. package/dist/core/ecs/dispatch_trace.d.ts +32 -31
  44. package/dist/core/ecs/dispatch_trace.d.ts.map +1 -1
  45. package/dist/core/ecs/ecs.d.cts +289 -270
  46. package/dist/core/ecs/ecs.d.ts +289 -270
  47. package/dist/core/ecs/ecs.d.ts.map +1 -1
  48. package/dist/core/ecs/ecs_memory.d.cts +134 -136
  49. package/dist/core/ecs/ecs_memory.d.ts +134 -136
  50. package/dist/core/ecs/ecs_memory.d.ts.map +1 -1
  51. package/dist/core/ecs/ecs_options.d.cts +89 -0
  52. package/dist/core/ecs/ecs_options.d.ts +89 -0
  53. package/dist/core/ecs/ecs_options.d.ts.map +1 -0
  54. package/dist/core/ecs/entity.d.cts +4 -4
  55. package/dist/core/ecs/entity.d.ts +4 -4
  56. package/dist/core/ecs/entity_allocator.d.cts +20 -18
  57. package/dist/core/ecs/entity_allocator.d.ts +20 -18
  58. package/dist/core/ecs/entity_allocator.d.ts.map +1 -1
  59. package/dist/core/ecs/event.d.cts +36 -22
  60. package/dist/core/ecs/event.d.ts +36 -22
  61. package/dist/core/ecs/event.d.ts.map +1 -1
  62. package/dist/core/ecs/facades.d.cts +12 -126
  63. package/dist/core/ecs/facades.d.ts +12 -126
  64. package/dist/core/ecs/facades.d.ts.map +1 -1
  65. package/dist/core/ecs/frame_stepper.d.cts +12 -12
  66. package/dist/core/ecs/frame_stepper.d.ts +12 -12
  67. package/dist/core/ecs/frame_stepper.d.ts.map +1 -1
  68. package/dist/core/ecs/frame_trace.d.cts +32 -32
  69. package/dist/core/ecs/frame_trace.d.ts +32 -32
  70. package/dist/core/ecs/frame_trace.d.ts.map +1 -1
  71. package/dist/core/ecs/host_commands.d.cts +103 -85
  72. package/dist/core/ecs/host_commands.d.ts +103 -85
  73. package/dist/core/ecs/host_commands.d.ts.map +1 -1
  74. package/dist/core/ecs/index.d.cts +21 -11
  75. package/dist/core/ecs/index.d.ts +21 -11
  76. package/dist/core/ecs/index.d.ts.map +1 -1
  77. package/dist/core/ecs/observer.d.cts +39 -120
  78. package/dist/core/ecs/observer.d.ts +39 -120
  79. package/dist/core/ecs/observer.d.ts.map +1 -1
  80. package/dist/core/ecs/phase.d.cts +79 -0
  81. package/dist/core/ecs/phase.d.ts +79 -0
  82. package/dist/core/ecs/phase.d.ts.map +1 -0
  83. package/dist/core/ecs/plugin.d.cts +125 -0
  84. package/dist/core/ecs/plugin.d.ts +125 -0
  85. package/dist/core/ecs/plugin.d.ts.map +1 -0
  86. package/dist/core/ecs/plugin_slots.d.cts +26 -0
  87. package/dist/core/ecs/plugin_slots.d.ts +26 -0
  88. package/dist/core/ecs/plugin_slots.d.ts.map +1 -0
  89. package/dist/core/ecs/query.d.cts +208 -578
  90. package/dist/core/ecs/query.d.ts +208 -578
  91. package/dist/core/ecs/query.d.ts.map +1 -1
  92. package/dist/core/ecs/query_cache.d.cts +130 -0
  93. package/dist/core/ecs/query_cache.d.ts +130 -0
  94. package/dist/core/ecs/query_cache.d.ts.map +1 -0
  95. package/dist/core/ecs/query_registry.d.cts +47 -0
  96. package/dist/core/ecs/query_registry.d.ts +47 -0
  97. package/dist/core/ecs/query_registry.d.ts.map +1 -0
  98. package/dist/core/ecs/query_terms.d.cts +126 -0
  99. package/dist/core/ecs/query_terms.d.ts +126 -0
  100. package/dist/core/ecs/query_terms.d.ts.map +1 -0
  101. package/dist/core/ecs/ref.d.cts +100 -39
  102. package/dist/core/ecs/ref.d.ts +100 -39
  103. package/dist/core/ecs/ref.d.ts.map +1 -1
  104. package/dist/core/ecs/relation.d.cts +101 -182
  105. package/dist/core/ecs/relation.d.ts +101 -182
  106. package/dist/core/ecs/relation.d.ts.map +1 -1
  107. package/dist/core/ecs/resource.d.cts +13 -13
  108. package/dist/core/ecs/resource.d.ts +13 -13
  109. package/dist/core/ecs/resource_registry.d.cts +5 -5
  110. package/dist/core/ecs/resource_registry.d.ts +5 -5
  111. package/dist/core/ecs/resource_registry.d.ts.map +1 -1
  112. package/dist/core/ecs/row_kinds.d.cts +24 -0
  113. package/dist/core/ecs/row_kinds.d.ts +24 -0
  114. package/dist/core/ecs/row_kinds.d.ts.map +1 -0
  115. package/dist/core/ecs/run_condition.d.cts +23 -23
  116. package/dist/core/ecs/run_condition.d.ts +23 -23
  117. package/dist/core/ecs/run_condition.d.ts.map +1 -1
  118. package/dist/core/ecs/schedule.d.cts +91 -120
  119. package/dist/core/ecs/schedule.d.ts +91 -120
  120. package/dist/core/ecs/schedule.d.ts.map +1 -1
  121. package/dist/core/ecs/schedule_plan.d.cts +33 -0
  122. package/dist/core/ecs/schedule_plan.d.ts +33 -0
  123. package/dist/core/ecs/schedule_plan.d.ts.map +1 -0
  124. package/dist/core/ecs/snapshot.d.cts +77 -0
  125. package/dist/core/ecs/snapshot.d.ts +77 -0
  126. package/dist/core/ecs/snapshot.d.ts.map +1 -0
  127. package/dist/core/ecs/snapshot_mount.d.cts +42 -0
  128. package/dist/core/ecs/snapshot_mount.d.ts +42 -0
  129. package/dist/core/ecs/snapshot_mount.d.ts.map +1 -0
  130. package/dist/core/ecs/sparse_store.d.cts +108 -51
  131. package/dist/core/ecs/sparse_store.d.ts +108 -51
  132. package/dist/core/ecs/sparse_store.d.ts.map +1 -1
  133. package/dist/core/ecs/store.d.cts +527 -473
  134. package/dist/core/ecs/store.d.ts +527 -473
  135. package/dist/core/ecs/store.d.ts.map +1 -1
  136. package/dist/core/ecs/store_layout_listener.d.cts +6 -6
  137. package/dist/core/ecs/store_layout_listener.d.ts +6 -6
  138. package/dist/core/ecs/store_types.d.cts +122 -0
  139. package/dist/core/ecs/store_types.d.ts +122 -0
  140. package/dist/core/ecs/store_types.d.ts.map +1 -0
  141. package/dist/core/ecs/system.d.cts +146 -61
  142. package/dist/core/ecs/system.d.ts +146 -61
  143. package/dist/core/ecs/system.d.ts.map +1 -1
  144. package/dist/core/ecs/system_context.d.cts +296 -0
  145. package/dist/core/ecs/system_context.d.ts +296 -0
  146. package/dist/core/ecs/system_context.d.ts.map +1 -0
  147. package/dist/core/ecs/system_set.d.cts +48 -0
  148. package/dist/core/ecs/system_set.d.ts +48 -0
  149. package/dist/core/ecs/system_set.d.ts.map +1 -0
  150. package/dist/core/ecs/utils/arrays.d.cts +15 -1
  151. package/dist/core/ecs/utils/arrays.d.ts +15 -1
  152. package/dist/core/ecs/utils/arrays.d.ts.map +1 -1
  153. package/dist/core/ecs/utils/error.d.cts +82 -6
  154. package/dist/core/ecs/utils/error.d.ts +82 -6
  155. package/dist/core/ecs/utils/error.d.ts.map +1 -1
  156. package/dist/core/ecs/utils/plugin_error.d.cts +10 -0
  157. package/dist/core/ecs/utils/plugin_error.d.ts +10 -0
  158. package/dist/core/ecs/utils/plugin_error.d.ts.map +1 -0
  159. package/dist/core/restore_errors.d.cts +30 -0
  160. package/dist/core/restore_errors.d.ts +30 -0
  161. package/dist/core/restore_errors.d.ts.map +1 -0
  162. package/dist/core/store/action_ring.d.cts +44 -44
  163. package/dist/core/store/action_ring.d.ts +44 -44
  164. package/dist/core/store/action_ring.d.ts.map +1 -1
  165. package/dist/core/store/allocator.d.cts +149 -95
  166. package/dist/core/store/allocator.d.ts +149 -95
  167. package/dist/core/store/allocator.d.ts.map +1 -1
  168. package/dist/core/store/buffer_backed_column.d.cts +17 -17
  169. package/dist/core/store/buffer_backed_column.d.ts +17 -17
  170. package/dist/core/store/buffer_backed_column.d.ts.map +1 -1
  171. package/dist/core/store/column_store.d.cts +124 -86
  172. package/dist/core/store/column_store.d.ts +124 -86
  173. package/dist/core/store/column_store.d.ts.map +1 -1
  174. package/dist/core/store/command_dispatch.d.cts +14 -15
  175. package/dist/core/store/command_dispatch.d.ts +14 -15
  176. package/dist/core/store/command_dispatch.d.ts.map +1 -1
  177. package/dist/core/store/command_ring.d.cts +36 -39
  178. package/dist/core/store/command_ring.d.ts +36 -39
  179. package/dist/core/store/command_ring.d.ts.map +1 -1
  180. package/dist/core/store/descriptor.d.cts +34 -17
  181. package/dist/core/store/descriptor.d.ts +34 -17
  182. package/dist/core/store/descriptor.d.ts.map +1 -1
  183. package/dist/core/store/entity_index.d.cts +34 -35
  184. package/dist/core/store/entity_index.d.ts +34 -35
  185. package/dist/core/store/entity_index.d.ts.map +1 -1
  186. package/dist/core/store/event_ring.d.cts +36 -38
  187. package/dist/core/store/event_ring.d.ts +36 -38
  188. package/dist/core/store/event_ring.d.ts.map +1 -1
  189. package/dist/core/store/extend.d.cts +13 -7
  190. package/dist/core/store/extend.d.ts +13 -7
  191. package/dist/core/store/extend.d.ts.map +1 -1
  192. package/dist/core/store/grow.d.cts +2 -2
  193. package/dist/core/store/grow.d.ts +2 -2
  194. package/dist/core/store/grow.d.ts.map +1 -1
  195. package/dist/core/store/header.d.cts +31 -27
  196. package/dist/core/store/header.d.ts +31 -27
  197. package/dist/core/store/header.d.ts.map +1 -1
  198. package/dist/core/store/index.d.cts +10 -10
  199. package/dist/core/store/index.d.ts +10 -10
  200. package/dist/core/store/index.d.ts.map +1 -1
  201. package/dist/core/store/layout_ops.d.cts +71 -62
  202. package/dist/core/store/layout_ops.d.ts +71 -62
  203. package/dist/core/store/layout_ops.d.ts.map +1 -1
  204. package/dist/core/store/region_table.d.cts +28 -21
  205. package/dist/core/store/region_table.d.ts +28 -21
  206. package/dist/core/store/region_table.d.ts.map +1 -1
  207. package/dist/core/store/snapshot.d.cts +31 -16
  208. package/dist/core/store/snapshot.d.ts +31 -16
  209. package/dist/core/store/snapshot.d.ts.map +1 -1
  210. package/dist/core/store/state_hash.d.cts +12 -12
  211. package/dist/core/store/state_hash.d.ts +12 -12
  212. package/dist/core/store/state_hash.d.ts.map +1 -1
  213. package/dist/core/store/store_regions.d.cts +10 -10
  214. package/dist/core/store/store_regions.d.ts +10 -10
  215. package/dist/core/store/store_regions.d.ts.map +1 -1
  216. package/dist/core/store/vendored_abi/abi.d.cts +27 -2
  217. package/dist/core/store/vendored_abi/abi.d.ts +27 -2
  218. package/dist/core/store/vendored_abi/abi.d.ts.map +1 -1
  219. package/dist/host_commands-B2KMx8O2.cjs +1 -0
  220. package/dist/host_commands-ClVPvhSa.cjs +2 -0
  221. package/dist/host_commands-CwxVQS1z.js +1524 -0
  222. package/dist/host_commands-nJvTy88E.js +1667 -0
  223. package/dist/index.cjs +1 -1
  224. package/dist/index.d.cts +15 -10
  225. package/dist/index.d.ts +15 -10
  226. package/dist/index.d.ts.map +1 -1
  227. package/dist/index.development.cjs +1 -1
  228. package/dist/index.development.js +5804 -5203
  229. package/dist/index.js +5323 -4764
  230. package/dist/internal.cjs +2 -2
  231. package/dist/internal.d.cts +5 -2
  232. package/dist/internal.d.ts +5 -2
  233. package/dist/internal.d.ts.map +1 -1
  234. package/dist/internal.development.cjs +1 -1
  235. package/dist/internal.development.js +70 -20
  236. package/dist/internal.js +138 -83
  237. package/dist/plugins/abi-D3V-QUSf.cjs +1 -0
  238. package/dist/plugins/abi-NP8pNxpd.js +42 -0
  239. package/dist/plugins/arrays-Dr_1hCjL.js +28 -0
  240. package/dist/plugins/arrays-Dt-Joc4i.cjs +1 -0
  241. package/dist/plugins/assertions-gtDVfbnQ.js +6 -0
  242. package/dist/plugins/assertions-z5GQd_bB.cjs +1 -0
  243. package/dist/{extensions → plugins}/editor/editor.d.cts +54 -54
  244. package/dist/{extensions → plugins}/editor/editor.d.ts +54 -54
  245. package/dist/plugins/editor/editor.d.ts.map +1 -0
  246. package/dist/{extensions → plugins}/editor/field_handle.d.cts +12 -12
  247. package/dist/{extensions → plugins}/editor/field_handle.d.ts +12 -12
  248. package/dist/plugins/editor/field_handle.d.ts.map +1 -0
  249. package/dist/plugins/editor/index.d.cts +22 -0
  250. package/dist/plugins/editor/index.d.ts +22 -0
  251. package/dist/plugins/editor/index.d.ts.map +1 -0
  252. package/dist/plugins/editor.cjs +1 -0
  253. package/dist/plugins/editor.d.cts +1 -0
  254. package/dist/plugins/editor.d.ts +1 -0
  255. package/dist/plugins/editor.development.cjs +1 -0
  256. package/dist/{extensions/editor/index.development.js → plugins/editor.development.js} +81 -64
  257. package/dist/{extensions/editor/index.js → plugins/editor.js} +81 -64
  258. package/dist/plugins/events/event_channel.d.cts +13 -0
  259. package/dist/plugins/events/event_channel.d.ts +13 -0
  260. package/dist/plugins/events/event_channel.d.ts.map +1 -0
  261. package/dist/plugins/events/event_registry.d.cts +22 -0
  262. package/dist/plugins/events/event_registry.d.ts +22 -0
  263. package/dist/plugins/events/event_registry.d.ts.map +1 -0
  264. package/dist/plugins/events/facade.d.cts +26 -0
  265. package/dist/plugins/events/facade.d.ts +26 -0
  266. package/dist/plugins/events/facade.d.ts.map +1 -0
  267. package/dist/plugins/events/index.d.cts +10 -0
  268. package/dist/plugins/events/index.d.ts +10 -0
  269. package/dist/plugins/events/index.d.ts.map +1 -0
  270. package/dist/plugins/events.cjs +1 -0
  271. package/dist/plugins/events.d.cts +1 -0
  272. package/dist/plugins/events.d.ts +1 -0
  273. package/dist/plugins/events.development.cjs +1 -0
  274. package/dist/plugins/events.development.js +174 -0
  275. package/dist/plugins/events.js +159 -0
  276. package/dist/plugins/observers/index.d.cts +23 -0
  277. package/dist/plugins/observers/index.d.ts +23 -0
  278. package/dist/plugins/observers/index.d.ts.map +1 -0
  279. package/dist/plugins/observers/observer_registry.d.cts +101 -0
  280. package/dist/plugins/observers/observer_registry.d.ts +101 -0
  281. package/dist/plugins/observers/observer_registry.d.ts.map +1 -0
  282. package/dist/plugins/observers.cjs +1 -0
  283. package/dist/plugins/observers.d.cts +1 -0
  284. package/dist/plugins/observers.d.ts +1 -0
  285. package/dist/plugins/observers.development.cjs +1 -0
  286. package/dist/plugins/observers.development.js +431 -0
  287. package/dist/plugins/observers.js +403 -0
  288. package/dist/plugins/relation_store-BsoegrZh.js +313 -0
  289. package/dist/plugins/relation_store-DQKSnxsm.cjs +1 -0
  290. package/dist/plugins/relation_store-RBhpcE28.cjs +1 -0
  291. package/dist/plugins/relation_store-RqW5Snx6.js +328 -0
  292. package/dist/plugins/relations/builtin_relations.d.cts +48 -0
  293. package/dist/plugins/relations/builtin_relations.d.ts +48 -0
  294. package/dist/plugins/relations/builtin_relations.d.ts.map +1 -0
  295. package/dist/plugins/relations/facade.d.cts +73 -0
  296. package/dist/plugins/relations/facade.d.ts +73 -0
  297. package/dist/plugins/relations/facade.d.ts.map +1 -0
  298. package/dist/plugins/relations/index.d.cts +11 -0
  299. package/dist/plugins/relations/index.d.ts +11 -0
  300. package/dist/plugins/relations/index.d.ts.map +1 -0
  301. package/dist/{core/ecs → plugins/relations}/relation_service.d.cts +85 -97
  302. package/dist/{core/ecs → plugins/relations}/relation_service.d.ts +85 -97
  303. package/dist/plugins/relations/relation_service.d.ts.map +1 -0
  304. package/dist/plugins/relations/relation_store.d.cts +177 -0
  305. package/dist/plugins/relations/relation_store.d.ts +177 -0
  306. package/dist/plugins/relations/relation_store.d.ts.map +1 -0
  307. package/dist/plugins/relations.cjs +1 -0
  308. package/dist/plugins/relations.d.cts +1 -0
  309. package/dist/plugins/relations.d.ts +1 -0
  310. package/dist/plugins/relations.development.cjs +1 -0
  311. package/dist/plugins/relations.development.js +603 -0
  312. package/dist/plugins/relations.js +553 -0
  313. package/dist/plugins/snapshots/index.d.cts +33 -0
  314. package/dist/plugins/snapshots/index.d.ts +33 -0
  315. package/dist/plugins/snapshots/index.d.ts.map +1 -0
  316. package/dist/plugins/snapshots/resume.d.cts +57 -0
  317. package/dist/plugins/snapshots/resume.d.ts +57 -0
  318. package/dist/plugins/snapshots/resume.d.ts.map +1 -0
  319. package/dist/plugins/snapshots/snapshot_service.d.cts +59 -0
  320. package/dist/plugins/snapshots/snapshot_service.d.ts +59 -0
  321. package/dist/plugins/snapshots/snapshot_service.d.ts.map +1 -0
  322. package/dist/plugins/snapshots.cjs +1 -0
  323. package/dist/plugins/snapshots.d.cts +1 -0
  324. package/dist/plugins/snapshots.d.ts +1 -0
  325. package/dist/plugins/snapshots.development.cjs +1 -0
  326. package/dist/plugins/snapshots.development.js +737 -0
  327. package/dist/plugins/snapshots.js +737 -0
  328. package/dist/plugins/solid/index.d.cts +8 -0
  329. package/dist/plugins/solid/index.d.ts +8 -0
  330. package/dist/plugins/solid/index.d.ts.map +1 -0
  331. package/dist/plugins/solid/solid.d.cts +97 -0
  332. package/dist/plugins/solid/solid.d.ts +97 -0
  333. package/dist/plugins/solid/solid.d.ts.map +1 -0
  334. package/dist/plugins/solid.cjs +1 -0
  335. package/dist/plugins/solid.d.cts +1 -0
  336. package/dist/plugins/solid.d.ts +1 -0
  337. package/dist/plugins/solid.development.cjs +1 -0
  338. package/dist/plugins/solid.development.js +319 -0
  339. package/dist/plugins/solid.js +319 -0
  340. package/dist/plugins/workers/index.d.cts +75 -0
  341. package/dist/plugins/workers/index.d.ts +75 -0
  342. package/dist/plugins/workers/index.d.ts.map +1 -0
  343. package/dist/plugins/workers/node_threads.d.cts +25 -0
  344. package/dist/plugins/workers/node_threads.d.ts +25 -0
  345. package/dist/plugins/workers/node_threads.d.ts.map +1 -0
  346. package/dist/plugins/workers/plan.d.cts +61 -0
  347. package/dist/plugins/workers/plan.d.ts +61 -0
  348. package/dist/plugins/workers/plan.d.ts.map +1 -0
  349. package/dist/plugins/workers/pool.d.cts +144 -0
  350. package/dist/plugins/workers/pool.d.ts +144 -0
  351. package/dist/plugins/workers/pool.d.ts.map +1 -0
  352. package/dist/plugins/workers/protocol.d.cts +112 -0
  353. package/dist/plugins/workers/protocol.d.ts +112 -0
  354. package/dist/plugins/workers/protocol.d.ts.map +1 -0
  355. package/dist/plugins/workers/worker_bind.d.cts +64 -0
  356. package/dist/plugins/workers/worker_bind.d.ts +64 -0
  357. package/dist/plugins/workers/worker_bind.d.ts.map +1 -0
  358. package/dist/plugins/workers/worker_loop.d.cts +14 -0
  359. package/dist/plugins/workers/worker_loop.d.ts +14 -0
  360. package/dist/plugins/workers/worker_loop.d.ts.map +1 -0
  361. package/dist/plugins/workers.cjs +1 -0
  362. package/dist/plugins/workers.d.cts +1 -0
  363. package/dist/plugins/workers.d.ts +1 -0
  364. package/dist/plugins/workers.development.cjs +1 -0
  365. package/dist/plugins/workers.development.js +596 -0
  366. package/dist/plugins/workers.js +474 -0
  367. package/dist/primitives.cjs +1 -1
  368. package/dist/primitives.d.cts +4 -4
  369. package/dist/primitives.d.ts +4 -4
  370. package/dist/primitives.development.cjs +1 -1
  371. package/dist/primitives.development.js +66 -22
  372. package/dist/primitives.js +66 -22
  373. package/dist/shared-BKl12xF1.js +132 -0
  374. package/dist/shared-Dk-pACZT.cjs +1 -0
  375. package/dist/shared.cjs +1 -1
  376. package/dist/shared.d.cts +7 -7
  377. package/dist/shared.d.ts +7 -7
  378. package/dist/shared.d.ts.map +1 -1
  379. package/dist/shared.development.cjs +1 -1
  380. package/dist/shared.development.js +4 -3
  381. package/dist/shared.js +4 -3
  382. package/dist/topological_sort-Cc_yXqPT.js +346 -0
  383. package/dist/topological_sort-vp1imU6D.cjs +1 -0
  384. package/dist/type_primitives/assertions.d.cts +12 -16
  385. package/dist/type_primitives/assertions.d.ts +12 -16
  386. package/dist/type_primitives/assertions.d.ts.map +1 -1
  387. package/dist/type_primitives/binary_heap/binary_heap.d.cts +2 -6
  388. package/dist/type_primitives/binary_heap/binary_heap.d.ts +2 -6
  389. package/dist/type_primitives/binary_heap/binary_heap.d.ts.map +1 -1
  390. package/dist/type_primitives/bitset/bitset.d.cts +7 -11
  391. package/dist/type_primitives/bitset/bitset.d.ts +7 -11
  392. package/dist/type_primitives/bitset/bitset.d.ts.map +1 -1
  393. package/dist/type_primitives/brand.d.cts +2 -7
  394. package/dist/type_primitives/brand.d.ts +2 -7
  395. package/dist/type_primitives/brand.d.ts.map +1 -1
  396. package/dist/type_primitives/error.d.cts +1 -2
  397. package/dist/type_primitives/error.d.ts +1 -2
  398. package/dist/type_primitives/error.d.ts.map +1 -1
  399. package/dist/type_primitives/index.d.cts +1 -1
  400. package/dist/type_primitives/index.d.ts +1 -1
  401. package/dist/type_primitives/sparse_map/sparse_map.d.cts +3 -7
  402. package/dist/type_primitives/sparse_map/sparse_map.d.ts +3 -7
  403. package/dist/type_primitives/sparse_map/sparse_map.d.ts.map +1 -1
  404. package/dist/type_primitives/sparse_set/sparse_set.d.cts +2 -6
  405. package/dist/type_primitives/sparse_set/sparse_set.d.ts +2 -6
  406. package/dist/type_primitives/sparse_set/sparse_set.d.ts.map +1 -1
  407. package/dist/type_primitives/topological_sort/topological_sort.d.cts +1 -5
  408. package/dist/type_primitives/topological_sort/topological_sort.d.ts +1 -5
  409. package/dist/type_primitives/topological_sort/topological_sort.d.ts.map +1 -1
  410. package/dist/type_primitives/typed_arrays/typed_arrays.d.cts +16 -15
  411. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts +16 -15
  412. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts.map +1 -1
  413. package/dist/utils/error.d.ts.map +1 -1
  414. package/dist/version.d.cts +3 -3
  415. package/dist/version.d.ts +3 -3
  416. package/dist/worker.cjs +1 -0
  417. package/dist/worker.d.cts +17 -0
  418. package/dist/worker.d.ts +17 -0
  419. package/dist/worker.d.ts.map +1 -0
  420. package/dist/worker.development.cjs +1 -0
  421. package/dist/worker.development.js +253 -0
  422. package/dist/worker.js +253 -0
  423. package/package.json +363 -191
  424. package/dist/core/ecs/builtin_relations.d.cts +0 -43
  425. package/dist/core/ecs/builtin_relations.d.ts +0 -43
  426. package/dist/core/ecs/builtin_relations.d.ts.map +0 -1
  427. package/dist/core/ecs/event_registry.d.cts +0 -22
  428. package/dist/core/ecs/event_registry.d.ts +0 -22
  429. package/dist/core/ecs/event_registry.d.ts.map +0 -1
  430. package/dist/core/ecs/relation_service.d.ts.map +0 -1
  431. package/dist/core/ecs/resume.d.cts +0 -85
  432. package/dist/core/ecs/resume.d.ts +0 -85
  433. package/dist/core/ecs/resume.d.ts.map +0 -1
  434. package/dist/core/ecs/snapshot_service.d.cts +0 -94
  435. package/dist/core/ecs/snapshot_service.d.ts +0 -94
  436. package/dist/core/ecs/snapshot_service.d.ts.map +0 -1
  437. package/dist/extensions/editor/editor.d.ts.map +0 -1
  438. package/dist/extensions/editor/field_handle.d.ts.map +0 -1
  439. package/dist/extensions/editor/index.cjs +0 -1
  440. package/dist/extensions/editor/index.d.cts +0 -21
  441. package/dist/extensions/editor/index.d.ts +0 -21
  442. package/dist/extensions/editor/index.d.ts.map +0 -1
  443. package/dist/extensions/editor/index.development.cjs +0 -1
  444. package/dist/extensions/reactive/ecs_sync.d.cts +0 -214
  445. package/dist/extensions/reactive/ecs_sync.d.ts +0 -214
  446. package/dist/extensions/reactive/ecs_sync.d.ts.map +0 -1
  447. package/dist/extensions/reactive/index.cjs +0 -1
  448. package/dist/extensions/reactive/index.d.cts +0 -23
  449. package/dist/extensions/reactive/index.d.ts +0 -23
  450. package/dist/extensions/reactive/index.d.ts.map +0 -1
  451. package/dist/extensions/reactive/index.development.cjs +0 -1
  452. package/dist/extensions/reactive/index.development.js +0 -215
  453. package/dist/extensions/reactive/index.js +0 -215
  454. package/dist/extensions/solid/index.cjs +0 -1
  455. package/dist/extensions/solid/index.d.cts +0 -6
  456. package/dist/extensions/solid/index.d.ts +0 -6
  457. package/dist/extensions/solid/index.d.ts.map +0 -1
  458. package/dist/extensions/solid/index.development.cjs +0 -1
  459. package/dist/extensions/solid/index.development.js +0 -40
  460. package/dist/extensions/solid/index.js +0 -36
  461. package/dist/extensions/solid/kernel_solid.d.cts +0 -45
  462. package/dist/extensions/solid/kernel_solid.d.ts +0 -45
  463. package/dist/extensions/solid/kernel_solid.d.ts.map +0 -1
  464. package/dist/host_commands-BlR3oZ3x.js +0 -2406
  465. package/dist/host_commands-C2cpU3yC.cjs +0 -1
  466. package/dist/internal-BoxWl4dG.js +0 -2565
  467. package/dist/internal-CGBEwfeB.cjs +0 -2
  468. package/dist/interop-CT-REx0W.cjs +0 -1
  469. package/dist/interop-CcY6ASQc.js +0 -18
  470. package/dist/interop-DqxleBo7.js +0 -18
  471. package/dist/interop-T1HZ-Dpa.cjs +0 -1
  472. package/dist/kernel-Cz2Kxlwl.js +0 -240
  473. package/dist/kernel-DgyrLFjW.js +0 -227
  474. package/dist/kernel-sw7ScKWu.cjs +0 -1
  475. package/dist/kernel-yWV3XnAb.cjs +0 -1
  476. package/dist/reactive/array.d.cts +0 -24
  477. package/dist/reactive/array.d.ts +0 -24
  478. package/dist/reactive/array.d.ts.map +0 -1
  479. package/dist/reactive/index.cjs +0 -1
  480. package/dist/reactive/index.d.cts +0 -11
  481. package/dist/reactive/index.d.ts +0 -11
  482. package/dist/reactive/index.d.ts.map +0 -1
  483. package/dist/reactive/index.development.cjs +0 -1
  484. package/dist/reactive/index.development.js +0 -18
  485. package/dist/reactive/index.js +0 -18
  486. package/dist/reactive/interop.d.cts +0 -19
  487. package/dist/reactive/interop.d.ts +0 -19
  488. package/dist/reactive/interop.d.ts.map +0 -1
  489. package/dist/reactive/kernel.d.cts +0 -73
  490. package/dist/reactive/kernel.d.ts +0 -73
  491. package/dist/reactive/kernel.d.ts.map +0 -1
  492. package/dist/reactive/map.d.cts +0 -16
  493. package/dist/reactive/map.d.ts +0 -16
  494. package/dist/reactive/map.d.ts.map +0 -1
  495. package/dist/reactive/shallow.d.cts +0 -11
  496. package/dist/reactive/shallow.d.ts +0 -11
  497. package/dist/reactive/shallow.d.ts.map +0 -1
  498. package/dist/reactive/struct.d.cts +0 -10
  499. package/dist/reactive/struct.d.ts +0 -10
  500. package/dist/reactive/struct.d.ts.map +0 -1
  501. package/dist/shallow-Bs39EPh1.js +0 -150
  502. package/dist/shallow-C5YmTbtb.cjs +0 -1
  503. package/dist/shallow-CiFC70Dz.js +0 -159
  504. package/dist/shallow-DQ8aG51_.cjs +0 -1
  505. package/dist/shared-B4v0L1cw.js +0 -109
  506. package/dist/shared-DU78k0pU.cjs +0 -1
  507. package/dist/topological_sort-BDvEyb9W.cjs +0 -1
  508. package/dist/topological_sort-DK6EjpWa.js +0 -135
  509. package/dist/typed_arrays-D3NmwtCG.cjs +0 -1
  510. package/dist/typed_arrays-DIVwVy5_.js +0 -258
@@ -1,140 +1,145 @@
1
1
  import { Template, TemplateOverrides } from './store.cjs';
2
2
  import { FrameTraceSink } from './frame_trace.cjs';
3
- import { ObserverHandle, EntitySetObserverConfig, ArchetypeSetObserverConfig, StructuralObserverConfig } from './observer.cjs';
4
- import { ColumnStore, ColumnStoreRegionHandle, StoreRegionSpec } from '../store/index.cjs';
5
- import { ECSRelations, ECSEvents, ECSResources, ECSSnapshots } from './facades.cjs';
6
- import { SCHEDULE, SystemEntry, SystemSet, SystemSetConfig } from './schedule.cjs';
3
+ import { ColumnStore, ColumnStoreRegionHandle } from '../store/index.cjs';
4
+ import { ECSResources, ECSSnapshots } from './facades.cjs';
5
+ import { Plugin, PluginsOf } from './plugin.cjs';
6
+ import { Phase, PhaseConfig, SchedulePhase } from './phase.cjs';
7
7
  import { Archetype, ArchetypeID } from './archetype.cjs';
8
- import { SystemContext, Query, QueryBuilder, QueryCache, QueryResolver } from './query.cjs';
8
+ import { Query, QueryBuilder } from './query.cjs';
9
+ import { QueryCache, QueryResolver } from './query_cache.cjs';
10
+ import { QueryTerms } from './query_terms.cjs';
11
+ import { SystemContext } from './system_context.cjs';
9
12
  import { EntityID } from './entity.cjs';
10
13
  import { ComponentCursor, ReadonlyComponentCursor, ReadonlyComponentRef } from './ref.cjs';
11
14
  import { ComponentDef, ComponentHandle, ComponentRegisterOptions, ComponentSchema, CompleteFieldValues, Bundle, BundleOrDef, StrictBundles, DefsOf } from './component.cjs';
12
15
  import { SparseComponentDef, SparseComponentID } from './sparse_store.cjs';
13
16
  import { RelationDef } from './relation.cjs';
14
17
  import { SystemFn, SystemConfig, SystemDescriptor, TypedSystemConfig, DenseAccessDecl, SpawnsAccessDecl, DespawnsAccessDecl, TransitionsAccessDecl, SparseAccessDecl, RelationsAccessDecl, ResourcesAccessDecl } from './system.cjs';
18
+ import { SystemEntry, SystemSet, SystemSetConfig } from './system_set.cjs';
15
19
  import { BitSet, TypedArrayTag } from '../../type_primitives/index.cjs';
16
20
  import { StoreLayoutListener } from './store_layout_listener.cjs';
17
21
  import { ComputeBackend } from './compute_backend.cjs';
18
- import { ResolvedECSMemory, ECSMemoryOptions } from './ecs_memory.cjs';
19
- export interface ECSOptions {
20
- fixedTimestep?: number;
21
- maxFixedSteps?: number;
22
- /** Sink for dev-mode engine diagnostics (currently the schedule's
23
- * dropped-ordering-edge warning). Defaults to `console.warn`. Mirrors the
24
- * `FrameTraceSink` seam's injectable style no global logger. */
25
- onWarn?: (message: string) => void;
26
- /** How the world's memory is sized and backed — the single
27
- * sizing surface, replacing the pre-release `initialCapacity` +
28
- * `bufferAllocator` pair. Express intent through exactly one arm:
29
- * `{ budget: { entities } }` (derive everything), `{ maxBytes }`
30
- * (explicit cap), `{ wasm: { memory } | { maximumPages } }` (the SAB
31
- * IS a WebAssembly.Memory zero-copy with a WASM `ComputeBackend`), or
32
- * `{ allocator }` (expert escape hatch, in-place-typed).
33
- * Omitted growable backing with a 256 MiB cap and 1024-row columns.
34
- * The resolved plan is exposed as `ECS.memoryPlan`. */
35
- memory?: ECSMemoryOptions;
36
- /** Consumer-declared SAB regions, forwarded to `Store`. Each
37
- * `StoreRegionSpec` carries an opaque `region_id`, a precomputed byte size,
38
- * and an `init` closure; the engine lays them out generically and exposes
39
- * them via `regionHandle(id)` / `regionOffset(id)`. A game (e.g.
40
- * `@internal/sim`'s region specs) supplies these — the engine ships no
41
- * game regions of its own. Replaces the eight game-named region options
42
- * (`terrain_map_radius`, `spatial_grid_*`, `army_*`, `flow_field_*`,
43
- * `actionRingCapacitySlots`) the ECS used to carry. */
44
- regions?: readonly StoreRegionSpec[];
45
- /** Byte size of the opt-in sim-bindings region, forwarded to `Store`.
46
- * A consumer that attaches a WASM `ComputeBackend` passes its own size — for
47
- * this game, `@internal/sim`'s `SIM_BINDINGS_BYTES` (computed from the binding
48
- * manifest) so the host can publish the `(component_id, field_id)` IDs the
49
- * accelerated systems read. Omitted / 0 no region: a pure-TS world pays
50
- * nothing for the WASM seam. The size is a runtime input, not an engine ABI
51
- * constant; it is de-welded from the generated ABI. */
52
- bindingsRegionBytes?: number;
53
- /** Opt into the **determinism surface**, forwarded to
54
- * `Store`. Default `false`. When `false`, the canonical-ordering methods
55
- * (`stateHash`, `snapshotSparse`, `restoreSparse`) throw
56
- * `DETERMINISM_DISABLED`; when `true`, today's replay/hash behavior is
57
- * reproduced bit-for-bit. Determinism is the implementer's choice our
58
- * server match opts in (replay verification), the client stays off (it rolls
59
- * back via diffs, not re-sim). The flag gates ONLY that surface: memory-safety
60
- * invariants (the in-place SAB allocator) and the `enabled_count`
61
- * partition are always-on regardless. */
62
- deterministic?: boolean;
63
- }
64
- export declare class ECS implements QueryResolver {
65
- private readonly store;
66
- private readonly schedule;
67
- private readonly ctx;
68
- /** Component observers. Inert until `observe(...)` is
69
- * called the structural-flush fast path is byte-for-byte unchanged. */
70
- private readonly _observers;
71
- /** Relations: register/add/remove/has, wildcard + traversal reads,
72
- * reverse-index compaction. See `ECSRelations`. */
73
- readonly relations: ECSRelations;
74
- /** Host-side event channels + signals: register/registerSignal/emit/read
75
- * (system-side `ctx.emit` is unchanged). See `ECSEvents`. */
76
- readonly events: ECSEvents;
77
- /** World resources: register/get/set/remove/has. See `ECSResources`. */
22
+ import { ResolvedECSMemory } from './ecs_memory.cjs';
23
+ import { ECSOptions } from './ecs_options.cjs';
24
+ import { computeArchetypeClosure } from './archetype_closure.cjs';
25
+ /** `ECSOptions` moved to `ecs_options.ts` with the guards that read it. The
26
+ * re-export holds the name a caller already imports from this module. */
27
+ export type { ECSOptions };
28
+ /** The plugins installed on a world. Each optional subsystem contributes
29
+ * its facade property here, so a world that never installed one cannot name it.
30
+ * The empty default keeps `ECS` usable unparameterised. */
31
+ export type Plugins = object;
32
+ export declare class ECS<C extends Plugins = object> implements QueryResolver {
33
+ /** Phantom. Carries the installed-plugin surface so `C` is measurable
34
+ * to the compiler. Declared, never assigned, and erased from the emitted
35
+ * JavaScript, so it costs a world nothing. */
36
+ readonly __plugins?: C;
37
+ /** Build a world with plugins installed.
38
+ *
39
+ * The returned type is the world intersected with the facades its plugins
40
+ * contribute, so `ECS.create({ plugins: [relations()] }).relations` type-checks
41
+ * and the same read on a bare `new ECS()` does not. Reach for `new ECS()`
42
+ * when the world needs none of the optional subsystems: that world does not
43
+ * carry their code.
44
+ *
45
+ * @example
46
+ * import { relations } from "@oasys/oecs/relations";
47
+ * const world = ECS.create({ plugins: [relations()] });
48
+ * world.relations.register();
49
+ */
50
+ static create<const P extends readonly Plugin<object>[]>(options?: ECSOptions & {
51
+ readonly plugins?: P;
52
+ }): ECS<PluginsOf<P>> & PluginsOf<P>;
53
+ /** The host a plugin installs through. Built per world, once per
54
+ * install. Cold path. */
55
+ private _pluginHost;
56
+ /** Where this world's bytes are, for a plugin that reads them directly.
57
+ * Built once, at install.
58
+ *
59
+ * `backing` is a getter, because a reader can attach after a grow, and a
60
+ * grow replaces the buffer the world started with. The wasm memory
61
+ * survives a grow, so it answers first. Cold path. */
62
+ private _pluginMemory;
63
+ private readonly _store;
64
+ private readonly _schedule;
65
+ private readonly _ctx;
66
+ /** What each plugin contributes to the archetype closure `startup()`
67
+ * plants. Empty on a world that installed no such plugin, and read once, at
68
+ * startup. */
69
+ private readonly _prewarmSources;
70
+ /** What each plugin ends when the world goes away, in install order. */
71
+ private readonly _disposeHooks;
72
+ /** The consumers of the tick-tail detection point, in install order. Each
73
+ * one runs once per `update()` with the change tick of the point. Empty on
74
+ * a world that installed no consumer, and the tail reads the length once. */
75
+ private readonly _settleHooks;
76
+ /** World resources, to register, get, set, remove and test. See
77
+ * `ECSResources`. */
78
78
  readonly resources: ECSResources;
79
- /** Determinism surface: capture/restore (full + sparse), stateHash,
80
- * the `deterministic` flag. See `ECSSnapshots`. */
79
+ /** Determinism: `stateHash()` and the `deterministic` flag, both properties
80
+ * of the world itself. Capture and restore are not here. They arrive with
81
+ * the snapshot plugin, which replaces this with a widened facade, so a
82
+ * world that never installs it carries no serialization code. */
81
83
  readonly snapshots: ECSSnapshots;
82
- private readonly systems;
83
- private nextSystemId;
84
+ private readonly _systems;
85
+ private _nextSystemId;
84
86
  private _tick;
85
87
  private _updating;
86
88
  private _fixedTimestep;
87
89
  private _accumulator;
88
90
  private _maxFixedSteps;
89
- private readonly scratchMask;
91
+ private readonly _scratchMask;
90
92
  private _nextQueryIdCounter;
91
- /** @internal Query-composition caches (QueryResolver seam) not public API. */
92
- readonly _caches: QueryCache;
93
+ /** @internal Query-composition caches (QueryResolver seam), not public API. */
94
+ readonly caches: QueryCache;
93
95
  private readonly _layoutSubscribers;
94
96
  private _backend;
97
+ private _routePlanner;
95
98
  private readonly _memory;
96
99
  /** What `ECSOptions.memory` resolved to: backing allocator kind,
97
100
  * column capacity, entity-index reservation, byte cap, and a
98
- * human-readable derivation trace. Diagnostics surface log it when
101
+ * human-readable derivation trace. Diagnostics surface, log it when
99
102
  * sizing questions come up instead of reverse-engineering the SAB. */
100
103
  get memoryPlan(): ResolvedECSMemory;
101
104
  /** The backing `WebAssembly.Memory` when `memory.wasm` was used (both
102
105
  * bring-your-own and engine-constructed), else `null`. A consumer hands
103
- * this to its WASM `ComputeBackend` so the sim and the live columns
106
+ * this to its WASM `ComputeBackend` so the module and the live columns
104
107
  * share the same bytes. */
105
108
  get wasmMemory(): WebAssembly.Memory | null;
106
109
  constructor(options?: ECSOptions);
107
110
  /** Batch variant of `regionHandle` for hosts wiring several consumer
108
- * regions at startup: returns the handles in argument order, never null
109
- * throws ONE `REGION_NOT_DECLARED` naming every missing region id instead
111
+ * regions at startup: returns the handles in argument order, never null,
112
+ * throws one `REGION_NOT_DECLARED` naming every missing region id instead
110
113
  * of a null-guard per region. Same staleness rule as `regionHandle`:
111
114
  * re-fetch after a SAB grow. */
112
115
  regionHandles(...regionIds: number[]): ColumnStoreRegionHandle[];
113
- /** Subscribe to SAB-layout publications. `listener.setLayout(0)` is
114
- * called immediately to seed the initial layout, then again after
115
- * every SAB grow / extend (the `view_stamp` republish protocol).
116
- * Returns an unsubscribe function.
116
+ /** Subscribe to store-layout publications. `listener.setLayout(storeBase)`
117
+ * is called immediately to seed the initial layout, then again after every
118
+ * grow and extend (the `view_stamp` republish protocol). The argument is the
119
+ * byte offset of the header inside the backing, and every offset the
120
+ * listener then reads from the bytes is relative to it. Returns an
121
+ * unsubscribe function.
117
122
  *
118
- * The engine has no concept of what subscribes it publishes SAB layouts
123
+ * The engine has no concept of what subscribes. It publishes SAB layouts
119
124
  * and walks away. A consumer subscribes whatever wrapper it owns (a compute
120
125
  * backend, a Worker proxy, a debug recorder) and drives it from its own
121
126
  * code. A `ComputeBackend` is subscribed automatically by `attachBackend`,
122
127
  * so most consumers call that rather than this directly. */
123
- onStoreLayoutPublished(listener: StoreLayoutListener): () => void;
128
+ subscribeLayout(listener: StoreLayoutListener): () => void;
124
129
  /** Attach an opt-in compute backend. Default is none: a bare `ECS`
125
130
  * runs pure-TS systems and the schedule's dispatch is byte-for-byte the
126
131
  * no-backend path. Once attached, a scheduled system carrying a
127
132
  * `backendHandle` (its `SystemConfig`) is executed via `backend.run(handle)`
128
- * instead of its `fn` closure; systems without a handle are unaffected.
133
+ * instead of its `fn` closure. Systems without a handle are unaffected.
129
134
  *
130
135
  * The backend is also subscribed as a SAB-layout listener (seeded now, then
131
- * republished on every grow), folding in the `onStoreLayoutPublished` seam.
136
+ * republished on every grow), folding in the `subscribeLayout` seam.
132
137
  * Returns a detach function that unsubscribes the layout listener and reverts
133
138
  * the schedule to the pure-TS path.
134
139
  *
135
140
  * One backend per ECS: attaching while one is already attached throws in
136
141
  * `DEV` (detach first). The engine never inspects the backend beyond
137
- * `setLayout` / `run` it carries no game vocabulary. */
142
+ * `setLayout` and `run`. It carries no game vocabulary. */
138
143
  attachBackend(backend: ComputeBackend): () => void;
139
144
  get fixedTimestep(): number;
140
145
  set fixedTimestep(value: number);
@@ -144,19 +149,19 @@ export declare class ECS implements QueryResolver {
144
149
  * flush, command, observer firing, and event during `update()`, so a consumer
145
150
  * can reconstruct exactly what travelled through the ECS each frame. The sink
146
151
  * also receives a `phaseBoundary(phase)` at each phase's post-flush settle
147
- * point the safe seam to read `stateHash()` between phases of one frame and
152
+ * point, the safe seam to read `stateHash()` between phases of one frame and
148
153
  * bisect a divergence to the exact phase. The seam is
149
- * `DEV`-gated end to end in a production build this setter keeps an empty
150
- * body and the world never retains a sink. The sink only observes; it does not
154
+ * `DEV`-gated end to end, in a production build this setter keeps an empty
155
+ * body and the world never retains a sink. The sink only observes. It does not
151
156
  * perturb `stateHash`, ordering, or any behaviour. */
152
157
  setTrace(sink: FrameTraceSink | null): void;
153
158
  /**
154
159
  * Register a dense component and get back its typed handle. Record syntax
155
- * gives per-field type control; the array shorthand types every field the
156
- * same (default `"f64"` rejected on a `{ deterministic: true }` world,
160
+ * gives per-field type control. The array shorthand types every field the
161
+ * same (default `"f64"`, rejected on a `{ deterministic: true }` world,
157
162
  * pass an explicit integer type there). An empty schema `{}` is a
158
163
  * tag. `opts.name` labels dev-mode diagnostics (`'Pos' (component 5)`
159
- * instead of `component 5`) diagnostic only, no behavioural effect.
164
+ * instead of `component 5`), diagnostic only, no behavioural effect.
160
165
  *
161
166
  * The handle is *callable*: `Pos({ x: 1 })` mints a `Bundle` for the
162
167
  * attach surfaces (`spawnBundle`, `ctx.commands.spawn`, `addComponent`).
@@ -165,7 +170,7 @@ export declare class ECS implements QueryResolver {
165
170
  * const Pos = ecs.registerComponent({ x: "f64", y: "f64" });
166
171
  * const Hp = ecs.registerComponent(["current", "max"], "i32");
167
172
  * const Frozen = ecs.registerComponent({}, { name: "Frozen" }); // tag
168
- * ecs.getField(e, Pos, "x"); // field names/types flow from the schema
173
+ * ecs.getField(e, Pos, "x"); // field names and types flow from the schema
169
174
  */
170
175
  registerComponent<S extends Record<string, TypedArrayTag>>(schema: S, opts?: ComponentRegisterOptions): ComponentDef<S>;
171
176
  registerComponent<const F extends readonly string[], T extends TypedArrayTag = "f64">(fields: F, type?: T, opts?: ComponentRegisterOptions): ComponentDef<{
@@ -176,35 +181,42 @@ export declare class ECS implements QueryResolver {
176
181
  readonly [K in F[number]]: T;
177
182
  }>;
178
183
  /**
179
- * Spawn an entity, immediately. Bare `spawn()` creates an empty entity
184
+ * Spawn an entity, immediately. Bare `spawn()` creates an empty entity,
180
185
  * attach components afterward. `spawn(template, overrides?)` lands
181
186
  * directly in the template's archetype with zero archetype transitions,
182
187
  * applying optional flat per-field overrides on top of the template
183
188
  * defaults. Inside a system use `ctx.commands.spawn(...)` instead.
184
189
  *
190
+ * `spawn` takes a template. It does not take a component definition, and it
191
+ * does not take a bundle. For components with no template, use `spawnBundle`.
192
+ *
185
193
  * @example
186
194
  * const e = ecs.spawn();
187
195
  * ecs.addComponent(e, Pos, { x: 0, y: 0 });
188
196
  *
189
- * const Bullet = ecs.template([{ def: Pos, values: { x: 0, y: 0 } }]);
197
+ * // Build a template from callable bundles.
198
+ * const Bullet = ecs.template(Pos({ x: 0, y: 0 }), Vel({ vx: 1, vy: 0 }));
190
199
  * const b = ecs.spawn(Bullet, { x: 5 }); // override a template default
200
+ *
201
+ * // One entity, components given directly, no template.
202
+ * const c = ecs.spawnBundle(Pos({ x: 0, y: 0 }), Vel({ vx: 1, vy: 0 }));
191
203
  */
192
204
  spawn(): EntityID;
193
205
  spawn<Defs extends readonly ComponentDef[]>(template: Template<Defs>, overrides?: TemplateOverrides<Defs>): EntityID;
194
206
  /**
195
- * Spawn an entity from varargs bundles (§bundles) — the immediate
207
+ * Spawn an entity from varargs bundles, the immediate
196
208
  * host-side analog of `ctx.commands.spawn`, and the same callable-bundle
197
- * grammar as `addComponents` / `template`. `ecs.spawnBundle(Pos({x,y}),
198
- * Vel({vx:1}), IsEnemy)` collapses the attach shapes into one; each item is
209
+ * grammar as `addComponents` and `template`. `ecs.spawnBundle(Pos({x,y}),
210
+ * Vel({vx:1}), IsEnemy)` collapses the attach shapes into one. Each item is
199
211
  * checked against its own def's schema (`StrictBundles`). Bundles are applied
200
- * immediately; a single combined-archetype insertion (one transition instead
201
- * of one-per-component) is a later optimization for now this mirrors the
212
+ * immediately. A single combined-archetype insertion (one transition instead
213
+ * of one-per-component) is a later optimization, for now this mirrors the
202
214
  * per-component `addComponent` path (unlike `addComponents`, which batches).
203
215
  *
204
- * Immediate inside a system use the deferred `ctx.commands.spawn(...)`
216
+ * Immediate, inside a system use the deferred `ctx.commands.spawn(...)`
205
217
  * (calling this from a system body throws in DEV). Note the redirect trades
206
218
  * timing: `commands.spawn` returns the id now but defers the attaches to the
207
- * phase flush, so the entity sits in its empty/partial archetype until then
219
+ * phase flush, so the entity sits in its empty and partial archetype until then,
208
220
  * unlike `spawnBundle`'s immediate, fully-populated archetype.
209
221
  */
210
222
  spawnBundle<Items extends readonly BundleOrDef[]>(...items: StrictBundles<Items>): EntityID;
@@ -212,32 +224,34 @@ export declare class ECS implements QueryResolver {
212
224
  * shared `overrides` object to every spawned row (same typed keys as
213
225
  * `spawn`). Field writes are O(columns) (one `TypedArray.fill` per
214
226
  * column), not O(count×columns). Returns the new ids in spawn order.
215
- * Immediate inside a system use `ctx.commands.spawn` per entity (calling
227
+ * Immediate, inside a system use `ctx.commands.spawn` per entity (calling
216
228
  * this from a system body throws in DEV). */
217
229
  spawnMany<Defs extends readonly ComponentDef[]>(template: Template<Defs>, count: number, overrides?: TemplateOverrides<Defs>): EntityID[];
218
230
  /** DEV-only: throw when an *immediate* host structural mutator is called
219
- * from inside one of THIS world's system bodies (or an observer / onAdded
220
- * hook — they run in the same access spans). One rule for every host
221
- * structural mutator despawn, add/remove(Components), batchAdd/Remove,
222
- * disable/enable, AND the spawn family (spawn/spawnBundle/spawnMany): an
223
- * immediate structural op mid-schedule can move or swap rows a running query
224
- * is walking — or, for a spawn-append into that archetype, trip a column
225
- * realloc under it and it is invisible to observers. The archetype-level
231
+ * from inside one of this world's system bodies. An observer callback and an
232
+ * `onAdded` hook run in the same access span, so the guard covers them too.
233
+ * One rule covers every host structural mutator: `despawn`, `addComponent`,
234
+ * `addComponents`, `removeComponent`, `removeComponents`,
235
+ * `batchAddComponent`, `batchRemoveComponent`, `disable`, `enable`, and the
236
+ * spawn family (`spawn`, `spawnBundle` and `spawnMany`).
237
+ * An immediate structural op mid-schedule can move or swap rows
238
+ * a running query is walking. A spawn-append into that archetype can trip a
239
+ * column realloc under it. Neither is visible to observers. The archetype-level
226
240
  * `_iterDepth` guard only catches mutations touching the archetype currently
227
241
  * being iterated (and the append paths skip even that), so an op landing
228
- * elsewhere would silently skip observers; the receiver rule ("inside a
242
+ * elsewhere would silently skip observers. The receiver rule ("inside a
229
243
  * system, use ctx.commands") is enforced wholesale here.
230
244
  *
231
- * `_updating` scopes the guard to THIS world: the accessCheck slot is
245
+ * `_updating` scopes the guard to this world: the accessCheck slot is
232
246
  * process-global, so without it a system of world A mutating world B (a
233
- * supported pattern B is not mid-iteration) would false-throw. */
234
- private _assertHostMutationOutsideSystem;
235
- /** Immediately destroy an entity `ecs.despawn(e); ecs.isAlive(e)` is
247
+ * supported pattern. B is not mid-iteration) would false-throw. */
248
+ private _assertOutsideSystem;
249
+ /** Immediately destroy an entity, `ecs.despawn(e); ecs.isAlive(e)` is
236
250
  * `false` on the next line, matching the immediacy of every other host
237
251
  * facade mutation. Inside a system the buffered path is
238
- * `ctx.commands.despawn` (applied at the phase flush); calling this from
239
- * a system body throws in DEV, since an immediate destroy mid-iteration
240
- * can invalidate rows the running query is walking. */
252
+ * `ctx.commands.despawn`, applied at the phase flush. A call from a system
253
+ * body throws in DEV, because an immediate destroy mid-iteration can
254
+ * invalidate rows the running query is walking. */
241
255
  despawn(entityId: EntityID): this;
242
256
  /** Disable `entityId` (idempotent). Excluded from default queries until re-enabled. */
243
257
  disable(entityId: EntityID): this;
@@ -245,61 +259,61 @@ export declare class ECS implements QueryResolver {
245
259
  enable(entityId: EntityID): this;
246
260
  /**
247
261
  * Attach a component to an entity, immediately (inside a system, use the
248
- * deferred `ctx.commands.add`). Three shapes: a bare def attaches a tag; a
249
- * bundle (`Pos({ x: 1 })`) zero-fills omitted fields; the explicit
262
+ * deferred `ctx.commands.add`). Three shapes: a bare def attaches a tag. A
263
+ * bundle (`Pos({ x: 1 })`) zero-fills omitted fields. The explicit
250
264
  * `(e, def, values)` form demands every field, so a typo'd or missing
251
265
  * field is a compile error.
252
266
  *
253
267
  * @example
254
268
  * ecs.addComponent(e, Frozen); // tag
255
- * ecs.addComponent(e, Pos({ x: 1 })); // bundle y zero-fills
269
+ * ecs.addComponent(e, Pos({ x: 1 })); // bundle, y zero-fills
256
270
  * ecs.addComponent(e, Pos, { x: 1, y: 2 }); // complete values
257
271
  */
258
272
  addComponent(entityId: EntityID, def: ComponentDef<Record<string, never>>): this;
259
273
  addComponent<S extends ComponentSchema>(entityId: EntityID, bundle: Bundle<S>): this;
260
274
  addComponent<S extends ComponentSchema>(entityId: EntityID, def: ComponentDef<S>, values: CompleteFieldValues<S>): this;
261
275
  /** Batch-attach several components in one archetype transition. Takes the
262
- * same callable-bundle varargs as `spawnBundle` `world.addComponents(e,
263
- * Pos({ x, y }), Vel({ vx }), Frozen)` each item checked against its own
264
- * def's schema (a misspelled or cross-component field is a compile error;
265
- * tags refuse values). Omitted fields zero-fill. */
276
+ * same callable-bundle varargs as `spawnBundle`, `world.addComponents(e,
277
+ * Pos({ x, y }), Vel({ vx }), Frozen)`, each item checked against its own
278
+ * def's schema (a misspelled or cross-component field is a compile error,
279
+ * and a tag refuses values). Omitted fields zero-fill. */
266
280
  addComponents<Items extends readonly BundleOrDef[]>(entityId: EntityID, ...items: StrictBundles<Items>): this;
267
281
  removeComponent(entityId: EntityID, def: ComponentDef): this;
268
- /** Detach several components in one archetype transition the varargs
269
- * mirror of `addComponents` (bare defs; removing needs no values). */
282
+ /** Detach several components in one archetype transition, the varargs
283
+ * mirror of `addComponents` (bare defs, removing needs no values). */
270
284
  removeComponents(entityId: EntityID, ...defs: ComponentDef[]): this;
271
285
  /**
272
- * Bulk add a component to ALL entities in the given archetype.
286
+ * Bulk add a component to all entities in the given archetype.
273
287
  * O(columns) via TypedArray.set() instead of O(N×columns).
274
288
  *
275
289
  * Takes an `ArchetypeID` (from `ArchetypeView.id`) rather than a concrete
276
- * `Archetype` the concrete type is internal.
290
+ * `Archetype`, the concrete type is internal.
277
291
  */
278
292
  batchAddComponent(src: ArchetypeID, def: ComponentDef<Record<string, never>>): this;
279
293
  batchAddComponent<S extends ComponentSchema>(src: ArchetypeID, def: ComponentDef<S>, values: CompleteFieldValues<S>): this;
280
294
  /**
281
- * Bulk remove a component from ALL entities in the given archetype.
295
+ * Bulk remove a component from all entities in the given archetype.
282
296
  * O(columns) via TypedArray.set() instead of O(N×columns).
283
297
  *
284
- * Takes an `ArchetypeID` (from `ArchetypeView.id`); see `batchAddComponent`.
298
+ * Takes an `ArchetypeID`, from `ArchetypeView.id`. See `batchAddComponent`.
285
299
  */
286
300
  batchRemoveComponent(src: ArchetypeID, def: ComponentDef): this;
287
301
  getField<S extends ComponentSchema>(entityId: EntityID, def: ComponentDef<S>, field: string & keyof S): number;
288
302
  /** Host-side parity with `SystemContext.refRead`: a
289
- * read-only whole-component view for tooling/tests, instead of reading
290
- * field-by-field. Same advisory-`readonly` semantics as the ctx variant;
291
- * no `_changedTick` bump. Dev-throws on a dead entity, or when the entity
292
- * doesn't hold the component (tags included no fields, nothing to ref).
303
+ * read-only whole-component view for tooling and tests, instead of reading
304
+ * field-by-field. Same advisory-`readonly` semantics as the ctx variant,
305
+ * and no `_changedTick` bump. Dev-throws on a dead entity, or when the entity
306
+ * doesn't hold the component (tags included, no fields, nothing to ref).
293
307
  *
294
308
  * **Staleness:** unlike ctx refs (protected by deferred structural changes
295
- * until the phase flush), host-side structural mutations apply immediately
296
- * any `addComponent`/`removeComponent`/`despawn` after creating the ref can
309
+ * until the phase flush), host-side structural mutations apply immediately,
310
+ * any `addComponent`, `removeComponent` and `despawn` after creating the ref can
297
311
  * row-swap so the old ref silently reads *another entity's* data. The ref is
298
- * only valid until the next structural mutation; treat it as an immediate
312
+ * only valid until the next structural mutation. Treat it as an immediate
299
313
  * single-expression read and re-create it after any structural change. */
300
314
  refRead<S extends ComponentSchema>(def: ComponentDef<S>, entityId: EntityID): ReadonlyComponentRef<S>;
301
315
  /**
302
- * A re-pointable single-entity cursor over `def` the by-id sweep accessor.
316
+ * A re-pointable single-entity cursor over `def`, the by-id sweep accessor.
303
317
  *
304
318
  * `refRead` resolves an entity one time, and each field after that is almost
305
319
  * free. But it allocates one accessor for each entity. That allocation is the
@@ -308,33 +322,62 @@ export declare class ECS implements QueryResolver {
308
322
  * that exists. In a loop over a list of entities, the allocation is not
309
323
  * necessary: the code discards each accessor, and it then makes an equal
310
324
  * accessor for the next entity. You make a cursor one time, and you then
311
- * point it again:
325
+ * move it again:
312
326
  *
313
327
  * const p = ecs.cursor(Pos);
314
328
  * for (let i = 0; i < ids.length; i++) {
315
329
  * p.at(ids[i]);
316
- * p.x += p.y;
330
+ * p.x += p.y
317
331
  * }
318
332
  *
319
- * Reach for it when you touch **many entities** by id; reach for `refRead` /
320
- * `ref` for a single entity, and for `eachChunk` whenever a query can express
333
+ * Reach for it when you touch many entities by id. Reach for `refRead` or
334
+ * `ref` for a single entity, and for `forEachChunk` whenever a query can express
321
335
  * the set. A column walk resolves nothing for each row, so it stays quicker
322
- * than a cursor a cursor removes the allocation, not the resolution.
336
+ * than a cursor, a cursor removes the allocation, not the resolution.
323
337
  *
324
- * Mutable every `at()` stamps the component's change tick, like `ctx.ref`.
338
+ * Mutable, every `at()` stamps the component's change tick, like `ctx.ref`.
325
339
  * See `cursorRead` for the read-only variant.
326
340
  *
327
341
  * **Staleness:** safer than a held ref, because `at()` re-resolves the
328
- * archetype and row each time a structural mutation between two `at()` calls
342
+ * archetype and row each time, a structural mutation between two `at()` calls
329
343
  * cannot make it read the wrong entity. Only the window between one `at()` and
330
344
  * the field accesses following it must be free of structural mutation.
331
345
  */
332
346
  cursor<S extends ComponentSchema>(def: ComponentDef<S>): ComponentCursor<S>;
333
- /** Read-only {@link cursor}: no change-tick stamp on `at()`. Advisory only
347
+ /** Read-only {@link cursor}: no change-tick stamp on `at()`. Advisory only,
334
348
  * same caveat as `refRead` (the setters exist on the shared prototype). */
335
349
  cursorRead<S extends ComponentSchema>(def: ComponentDef<S>): ReadonlyComponentCursor<S>;
350
+ /**
351
+ * A re-pointable single-entity cursor over a sparse component, the sparse
352
+ * sibling of {@link cursor}, and the fastest read by id the engine has.
353
+ *
354
+ * A sparse component's columns are indexed by entity index, so `at(entity)`
355
+ * writes one field and a field access is one load: there is no archetype
356
+ * and no row to resolve, which is what a dense cursor must do on every
357
+ * `at()`. Make the cursor one time and move it in the loop:
358
+ *
359
+ * const hp = ecs.sparseCursor(Health);
360
+ * for (let i = 0; i < ids.length; i++) {
361
+ * hp.at(ids[i]);
362
+ * hp.current -= damage[i];
363
+ * }
364
+ *
365
+ * Mutable, like `cursor`. Once the component keeps row ticks
366
+ * (`trackRows`, or an entity-level `onSet`), `at()` records the entity for
367
+ * them, as the dense cursor does. See `sparseCursorRead` for the read-only
368
+ * variant.
369
+ *
370
+ * **Membership:** in development `at()` throws when the entity is dead or
371
+ * does not hold the component. In production it does not test, and a read
372
+ * then gives whatever the column holds at that index. Test with `hasSparse`
373
+ * first when the component can be absent.
374
+ */
375
+ sparseCursor<S extends ComponentSchema>(def: SparseComponentDef<S>): ComponentCursor<S>;
376
+ /** Read-only {@link sparseCursor}. Advisory only, same caveat as
377
+ * `cursorRead` (the setters exist on the shared prototype). */
378
+ sparseCursorRead<S extends ComponentSchema>(def: SparseComponentDef<S>): ReadonlyComponentCursor<S>;
336
379
  /** Total sibling of {@link getField}: `undefined` when the
337
- * entity is dead or doesn't hold the component, instead of a dev throw /
380
+ * entity is dead or doesn't hold the component, instead of a dev throw and a
338
381
  * prod garbage read. The safe way to probe-and-read in one call:
339
382
  * `ecs.tryGetField(e, Health, "current") ?? 0`. */
340
383
  tryGetField<S extends ComponentSchema>(entityId: EntityID, def: ComponentDef<S>, field: string & keyof S): number | undefined;
@@ -346,72 +389,72 @@ export declare class ECS implements QueryResolver {
346
389
  updateField<S extends ComponentSchema>(entityId: EntityID, def: ComponentDef<S>, field: string & keyof S, fn: (current: number) => number): number;
347
390
  /**
348
391
  * Get the live, cached query matching entities that have **all** of
349
- * `defs`. Queries are deduplicated by mask calling this twice with the
350
- * same terms returns the same instance so build once at setup and reuse;
351
- * the view stays live as archetypes appear. Refine with `.and()` /
352
- * `.without()` / `.anyOf()`; iterate with `eachChunk` (mutating hot path),
392
+ * `defs`. Queries are deduplicated by mask, calling this twice with the
393
+ * same terms returns the same instance, so build once at setup and reuse.
394
+ * The view stays live as archetypes appear. Refine with `.and()`,
395
+ * `.not()` or `.or()`. Iterate with `forEachChunk` (mutating hot path),
353
396
  * `forEach` (per-archetype), or `forEachEntity` (per-entity).
354
397
  *
355
398
  * @example
356
399
  * const movers = ecs.query(Pos, Vel);
357
- * movers.eachChunk((cols, count) => {
400
+ * movers.forEachChunk((cols, count) => {
358
401
  * const { x, y } = cols.mut(Pos);
359
402
  * const { vx, vy } = cols.read(Vel);
360
403
  * for (let i = 0; i < count; i++) { x[i] += vx[i]; y[i] += vy[i]; }
361
404
  * });
362
405
  */
363
406
  query<T extends ComponentDef[]>(...defs: T): Query<T>;
364
- _nextQueryId(): number;
365
- /** QueryResolver implementation creates or retrieves a cached Query.
407
+ nextQueryId(): number;
408
+ /** QueryResolver implementation, creates or retrieves a cached Query.
366
409
  *
367
410
  * **Mask ownership: borrowed.** The three mask arguments are read, never
368
- * retained the mint path copies each one into the `Query`, into the dedup
411
+ * retained, the mint path copies each one into the `Query`, into the dedup
369
412
  * entry, and (via `Store.registerQuery`) into the registered-query record.
370
413
  * So callers may pass a scratch mask they intend to reuse (`ecs.query`) or
371
- * a live mask they still own (`Query.and` / `.without` / `.anyOf` pass
372
- * `this._include` etc.). Do NOT add a caller-side `.copy()` "for safety":
414
+ * a live mask they still own (`Query.and`, `.not` and `.or` pass
415
+ * `this._include` etc.). Do not add a caller-side `.copy()` "for safety":
373
416
  * on the cache-hit path that is a per-call BitSet + `number[]` allocation
374
417
  * for nothing. */
375
- _resolveQuery(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, defs: readonly ComponentDef[]): Query<any>;
418
+ resolveQuery(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, defs: readonly ComponentDef[]): Query<any>;
376
419
  /**
377
420
  * Register a system and get its scheduling handle. The config form is the
378
- * production shape: it declares the access surface (`reads` / `writes` are
379
- * mandatory; `spawns` / `despawns` / resource and sparse/relation terms
380
- * optional), which is enforced at runtime in dev *and* narrows `ctx` at
421
+ * production shape. It declares the access surface. `reads` and `writes` are
422
+ * mandatory. The `spawns`, `despawns`, resource, sparse and relation terms
423
+ * are optional. The runtime enforces the surface in dev, and it narrows `ctx` at
381
424
  * the type level so undeclared access fails to compile. Registration does
382
- * not schedule pass the returned descriptor to
425
+ * not schedule, pass the returned descriptor to
383
426
  * `ecs.addSystems(SCHEDULE.UPDATE, ...)`.
384
427
  *
385
428
  * @example
386
- * // Full config declared access, dev-checked and compile-checked
429
+ * // Full config, declared access, dev-checked and compile-checked
387
430
  * const move = ecs.registerSystem({
388
431
  * reads: [Vel],
389
432
  * writes: [Pos],
390
433
  * fn(ctx, dt) {
391
- * movers.eachChunk((cols, count) => { ... });
434
+ * movers.forEachChunk((cols, count) => { ... });
392
435
  * },
393
436
  * });
394
437
  * ecs.addSystems(SCHEDULE.UPDATE, move);
395
438
  *
396
439
  * @example
397
- * // Bare function (no declared access any component touch throws in dev)
440
+ * // Bare function (no declared access, any component touch throws in dev)
398
441
  * ecs.registerSystem((ctx, dt) => { ... });
399
442
  * // Function + query builder (query resolved at registration time)
400
- * ecs.registerSystem((q, ctx, dt) => { q.forEach((arch) => { ... }); }, (qb) => qb.with(Pos, Vel));
443
+ * ecs.registerSystem((q, ctx, dt) => { q.forEach((arch) => { ... }); }, (qb) => qb.and(Pos, Vel));
401
444
  */
402
445
  registerSystem(fn: SystemFn): SystemDescriptor;
403
446
  registerSystem<Defs extends readonly ComponentDef[]>(fn: (q: Query<Defs>, ctx: SystemContext, dt: number) => void, queryFn: (qb: QueryBuilder) => Query<Defs>): SystemDescriptor;
404
- /** `exclusive: true` grants full world access at runtime (§system.ts), so
405
- * the context stays fully permissive at the type layer too. Declared BEFORE
447
+ /** `exclusive: true` grants full world access at runtime (system.ts), so
448
+ * the context stays fully permissive at the type layer too. Declared before
406
449
  * the typed-config overload so exclusive configs never get narrowed. */
407
450
  registerSystem(config: SystemConfig & {
408
451
  readonly exclusive: true;
409
452
  }): SystemDescriptor;
410
- /** Config form (§typestate, system.ts): the declaration lists are inferred
411
- * as literal tuples and `fn` / `onAdded` receive
412
- * `SystemContext<DeclaredAccess<…>>` undeclared access fails to compile
453
+ /** Config form (system.ts): the declaration lists are inferred
454
+ * as literal tuples, and `fn` and `onAdded` receive
455
+ * `SystemContext<DeclaredAccess<…>>`, undeclared access fails to compile
413
456
  * with the same taxonomy the runtime `accessCheck` throws with in
414
- * `DEV`. A config VALUE typed as plain `SystemConfig` (dynamically
457
+ * `DEV`. A config value typed as plain `SystemConfig` (dynamically
415
458
  * built) still matches: its erased declaration lists compute a permissive
416
459
  * access record. Escape hatch: annotate `fn(ctx: SystemContext, dt)`
417
460
  * explicitly to keep a system permissive at compile time. */
@@ -420,10 +463,10 @@ export declare class ECS implements QueryResolver {
420
463
  get systemCount(): number;
421
464
  /**
422
465
  * Run the startup phases, once, before the first `update()`. Prewarms
423
- * every archetype the registered systems/observers can produce, runs each
466
+ * every archetype the registered systems and observers can produce, runs each
424
467
  * system's `onAdded` hook, then the `PRE_STARTUP` → `STARTUP` →
425
468
  * `POST_STARTUP` schedule. Events emitted during startup are drained at
426
- * its tail they do not leak into frame 1.
469
+ * its tail. They do not leak into frame 1.
427
470
  *
428
471
  * @example
429
472
  * ecs.addSystems(SCHEDULE.UPDATE, move);
@@ -431,15 +474,15 @@ export declare class ECS implements QueryResolver {
431
474
  * ecs.update(1 / 60); // now tick every frame
432
475
  */
433
476
  startup(): void;
434
- /** Compute the archetype closure from every registered system's AND
477
+ /** Compute the archetype closure from every registered system's and
435
478
  * observer's `spawns` + `transitions` and ask the store to plant the
436
479
  * whole set in one `extendColumnStore` call. Observers carry the same
437
480
  * access shape systems do (a synthesized `SystemDescriptor`), so an
438
- * observer that spawns/transitions gets its target archetype prewarmed
481
+ * observer that spawns and transitions gets its target archetype prewarmed
439
482
  * too rather than first-touching lazily mid-tick. Exposed as
440
- * `private` because the only caller is `startup()`; visible to tests via
441
- * the `archetype_count` delta on the public ECS facade. */
442
- private prewarmArchetypes;
483
+ * `private` because the only caller is `startup()`. Visible to tests via
484
+ * the `archetypeCount` delta on the public ECS facade. */
485
+ private _prewarmArchetypes;
443
486
  /**
444
487
  * Advance the world one frame. Runs the fixed-timestep accumulator loop
445
488
  * (`FIXED_UPDATE`, when any fixed system is registered), then
@@ -459,24 +502,24 @@ export declare class ECS implements QueryResolver {
459
502
  update(dt: number): void;
460
503
  dispose(): void;
461
504
  /** Register an archetype template. Resolves the component set +
462
- * default field values to a target archetype once (creating it if absent
463
- * fits the prewarm model), so later `spawn` / `spawnMany` calls land
464
- * entities directly in that archetype with **zero archetype transitions**.
505
+ * default field values to a target archetype once (creating it if absent,
506
+ * fits the prewarm model), so a later `spawn` or `spawnMany` call lands
507
+ * entities directly in that archetype with no archetype transition.
465
508
  *
466
509
  * const Bullet = ecs.template(Position({ x: 0, y: 0 }), Velocity({ vx: 0, vy: 0 }));
467
510
  *
468
- * Takes the same callable-bundle varargs as `spawnBundle` / `addComponents`
469
- * (each item schema-checked against its own def); the resulting
511
+ * Takes the same callable-bundle varargs as `spawnBundle` and
512
+ * `addComponents`, each item schema-checked against its own def. The resulting
470
513
  * `Template<[Position, Velocity]>` keeps the typed key set that `spawn`'s
471
- * `overrides` map over. Not a pass-through it normalizes bundles to the
514
+ * `overrides` map over. Not a pass-through. It normalizes bundles to the
472
515
  * store's entry shape, so it lives here with the other real logic, not in the
473
- * delegation band. The big win is multi-component entities and bulk spawns; a
516
+ * delegation band. The big win is multi-component entities and bulk spawns. A
474
517
  * single-component spawn is no faster than `spawn` + `addComponent`, which
475
518
  * already bump-allocates a fresh entity into the target archetype. */
476
519
  template<Items extends readonly BundleOrDef[]>(...items: StrictBundles<Items>): Template<DefsOf<Items>>;
477
520
  /** Resolve a consumer-declared SAB region's byte offset by `region_id`, or
478
521
  * 0 when absent. Generic, de-gamed replacement for the removed
479
- * game-named accessors; pair with the consumer's own region module to
522
+ * game-named accessors. Pair with the consumer's own region module to
480
523
  * materialise a typed view. Delegates to `Store.regionOffset`. */
481
524
  regionOffset(regionId: number): number;
482
525
  /** A handle (`{ buffer, view, offset, bytes }`) to a consumer-declared SAB
@@ -487,8 +530,8 @@ export declare class ECS implements QueryResolver {
487
530
  /** Look up the field index a component reserves for `fieldName`. The
488
531
  * index is assigned by `registerComponent` in insertion order and is
489
532
  * stable for the lifetime of the ECS. Used by systems that need to
490
- * pass `(component_id, field_id)` pairs across the WASM FFI the Zig
491
- * side identifies columns by these numeric IDs. */
533
+ * pass `(component_id, field_id)` pairs across the WASM FFI, because the
534
+ * module identifies columns by these numeric ids. */
492
535
  fieldId<S extends Record<string, TypedArrayTag>>(def: ComponentDef<S>, fieldName: Extract<keyof S, string>): number;
493
536
  /** Resolve an archetype's row index to the `EntityID` at that slot.
494
537
  * A WASM system that drains events from the event ring as
@@ -497,24 +540,24 @@ export declare class ECS implements QueryResolver {
497
540
  * Throws if the (archId, row) pair is out of range. */
498
541
  entityIdAtRow(archetypeId: number, row: number): EntityID;
499
542
  /** The single SAB backing every archetype's column views. Exposed for
500
- * snapshot/restore, `columnStoreStateHash`-based determinism checks, and
501
- * WASM/worker hand-off paths. Mutation flows through the
502
- * usual `addComponent` / `removeComponent` / `flush` APIs; readers
543
+ * snapshot and restore, `columnStoreStateHash`-based determinism checks, and
544
+ * WASM or worker hand-off paths. Mutation flows through the
545
+ * usual `addComponent`, `removeComponent` and `flush` APIs. Readers
503
546
  * that hold a column view across a grow must consult
504
547
  * `header.view_stamp` to detect a republish. */
505
548
  get columnStore(): ColumnStore;
506
549
  /** Count of live archetypes (including the empty one). Surfaces the
507
550
  * Store-side `archetype_count` so tests can assert the
508
- * pre-warmed closure was materialised; equally useful for diagnostics. */
551
+ * pre-warmed closure was materialised. Equally useful for diagnostics. */
509
552
  get archetypeCount(): number;
510
553
  registerTag(): ComponentDef<Record<string, never>>;
511
- /** Register a sparse tag (empty schema) membership only, no data. */
554
+ /** Register a sparse tag (empty schema), membership only, no data. */
512
555
  registerSparseTag(): SparseComponentDef<Record<string, never>>;
513
556
  isAlive(entityId: EntityID): boolean;
514
557
  get entityCount(): number;
515
558
  hasComponent(entityId: EntityID, def: ComponentDef): boolean;
516
- /** Whether `entityId` is currently disabled. Toggle via `disable` / `enable`
517
- * (immediate, above the band they carry the in-system dev guard). */
559
+ /** Whether `entityId` is currently disabled. Toggle with `disable` or `enable`
560
+ * (immediate, above the band. They carry the in-system dev guard). */
518
561
  isDisabled(entityId: EntityID): boolean;
519
562
  addSparse(entityId: EntityID, def: SparseComponentDef<Record<string, never>>): this;
520
563
  addSparse<S extends ComponentSchema>(entityId: EntityID, def: SparseComponentDef<S>, values: CompleteFieldValues<S>): this;
@@ -522,65 +565,62 @@ export declare class ECS implements QueryResolver {
522
565
  hasSparse(entityId: EntityID, def: SparseComponentDef): boolean;
523
566
  getSparseField<S extends ComponentSchema>(entityId: EntityID, def: SparseComponentDef<S>, field: string & keyof S): number;
524
567
  setSparseField<S extends ComponentSchema>(entityId: EntityID, def: SparseComponentDef<S>, field: string & keyof S, value: number): void;
525
- _getLastRunTick(): number;
526
- /** Current ECS write tick the tick `eachChunk` stamps via `cols.mut` (§eachChunk). */
527
- _getCurrentTick(): number;
528
- _getQueryDirtyEpoch(): number;
529
- /** QueryResolver implementation — sparse-membership match path. */
530
- _forEachSparseMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], denseArchetypes: readonly Archetype[], cb: (entityId: EntityID) => void, includeDisabled: boolean): void;
531
- /** QueryResolver implementation — backing sparse id of a relation, for the
532
- * `(R, *)` wildcard term (`Query.withRelation`). */
533
- _relationBackingSparseId(def: RelationDef): SparseComponentID;
534
- /** QueryResolver implementation — `(*, T)` wildcard match path. */
535
- _forEachRelationTargetMatch(target: EntityID, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
536
- /** QueryResolver implementation depth-ordered hierarchy match path. */
537
- _forEachHierarchyMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], denseArchetypes: readonly Archetype[], relation: RelationDef, maxDepth: number, includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
538
- addSystems(label: SCHEDULE, ...entries: (SystemDescriptor | SystemEntry)[]): this;
568
+ getLastRunTick(): number;
569
+ /** The change tick, the stamp `forEachChunk` makes via `cols.mut`. */
570
+ getChangeTick(): number;
571
+ /** QueryResolver implementation: a chunk loop took `cols.ticks(def)`. */
572
+ noteScan(cid: number): void;
573
+ getQueryDirtyEpoch(): number;
574
+ /** QueryResolver implementation, sparse-membership match path. */
575
+ forEachSparseMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, terms: QueryTerms, denseArchetypes: readonly Archetype[], cb: (entityId: EntityID) => void): void;
576
+ /** QueryResolver implementation, backing sparse id of a relation, for the
577
+ * `(R, *)` wildcard term (`Query.andRelation`). */
578
+ relationBackingSparseId(def: RelationDef, api: string): SparseComponentID;
579
+ /** QueryResolver implementation, `(*, T)` wildcard match path. */
580
+ forEachTargetMatch(target: EntityID, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, terms: QueryTerms, cb: (entityId: EntityID) => void): void;
581
+ /** QueryResolver implementation, depth-ordered hierarchy match path. */
582
+ forEachHierarchyMatch(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, terms: QueryTerms, denseArchetypes: readonly Archetype[], relation: RelationDef, maxDepth: number, cb: (entityId: EntityID) => void): void;
583
+ addSystems(phase: SchedulePhase, ...entries: (SystemDescriptor | SystemEntry)[]): this;
584
+ /**
585
+ * Add one phase to a loop, and hand back its handle. Setup only, cold path.
586
+ *
587
+ * A plugin that owns a slot no longer contends for insertion order inside a
588
+ * phase the application also writes to. `before` and `after` order the new
589
+ * phase against the other phases of the same loop, built-in or added.
590
+ *
591
+ * The handle belongs to this world, and identity and not name decides which
592
+ * phase it is, the rule `systemSet` follows.
593
+ *
594
+ * @example
595
+ * const physics = ecs.addPhase("physics", {
596
+ * loop: "update",
597
+ * after: [SCHEDULE.PRE_UPDATE],
598
+ * before: [SCHEDULE.UPDATE]
599
+ * });
600
+ * ecs.addSystems(physics, integrate);
601
+ */
602
+ addPhase(name: string, config: PhaseConfig): Phase;
539
603
  /**
540
- * Configure a `SystemSet` the shared run condition and/or ordering
604
+ * Configure a `SystemSet`, the shared run condition, or its ordering,
541
605
  * every member inherits. Additive and order-independent with respect to
542
606
  * `addSystems`: see `Schedule.configureSet`. Returns `this` to chain.
543
607
  */
544
608
  configureSet(set: SystemSet, config: SystemSetConfig): this;
545
609
  /**
546
- * Register a per-component observer. Reactions that were
547
- * hand-polled every tick — "on `Death` added → spawn corpse", "on `HexPos`
548
- * set mark the spatial index" become declarative.
549
- *
550
- * - **`onAdd` / `onRemove`** `(eid, ctx)` fire at the structural-flush
551
- * boundary, after the batch commits, in canonical order (access-topological
552
- * across observers, entity-id order within), looping to a fixed point so
553
- * cascades settle. Determinism: a `stateHash` replay reproduces regardless
554
- * of the order ops were queued.
555
- * - **`onDisable` / `onEnable`** `(eid, ctx)` fire at the same flush boundary
556
- * when an entity carrying the component is *disabled* / *enabled*, once
557
- * per net transition, for every component the entity carries
558
- * (a disable is a soft remove of the whole mask from default queries). Like
559
- * `onAdd`/`onRemove`, an *immediate* `ecs.disable()` does not fire — only
560
- * the deferred `ctx.commands.disable()` toggle does. `yieldExisting` seeds enabled
561
- * members only, so a disabled entity is correctly absent at seed.
562
- * - **`onSet`** fires at the post-update detection point. Default
563
- * `granularity: "archetype"` fires `(arch, ctx)` once per changed
564
- * archetype-column (the consumer iterates `arch.entityCount` rows) — free,
565
- * reusing the change tick. `granularity: "entity"` fires `(eid, ctx)` once
566
- * per changed entity, draining the opt-in per-row dirty list (registering it
567
- * enables dirty tracking for the component; the producer records via
568
- * `ctx.setField` automatically, or `ctx.markChanged` in a `getColumn`
569
- * hot loop).
570
- *
571
- * Observer callbacks that touch ECS state must declare it via `access`
572
- * (merged over an all-empty declaration) — undeclared access throws in
573
- * `DEV`, and those decls drive the firing order. `yieldExisting` replays
574
- * `onAdd` over current matches on registration. Register at world-build time
575
- * (before `startup()`); the returned handle's `dispose()` unregisters.
610
+ * Keep a change tick for each row of `def`, the row grain of change
611
+ * detection. `cols.ticksRead(def)` and `changed(def).forEachChunk` read it
612
+ * against `cols.since`, and every write path stamps it: `setField`, `ref`,
613
+ * a cursor, `markChanged`, and a store into `cols.ticks(def)`. An `onSet`
614
+ * observer with entity granularity turns it on as well. Costs one word for
615
+ * each row of every archetype that holds `def`, and one store on each by-id
616
+ * write. Never turned off. Idempotent. A sparse component keeps one tick
617
+ * for each entity index instead, read through `ctx.sparseChanged`.
576
618
  */
577
- observe(def: ComponentHandle, config: StructuralObserverConfig): ObserverHandle;
578
- observe(def: ComponentHandle, config: EntitySetObserverConfig): ObserverHandle;
579
- observe(def: ComponentHandle, config: ArchetypeSetObserverConfig): ObserverHandle;
619
+ trackRows(def: ComponentHandle | SparseComponentDef): void;
580
620
  /**
581
621
  * Stamp every SAB-backed archetype's live `length` into its SAB
582
622
  * descriptor's `row_count` field. **You usually don't need to call
583
- * this directly** `update()` publishes at tick start and
623
+ * this directly**, `update()` publishes at tick start and
584
624
  * `SystemContext.flush()` publishes at every phase boundary, so any
585
625
  * WASM scan running inside the schedule sees fresh counts for free.
586
626
  * This is an escape hatch for code that mutates archetype state
@@ -589,34 +629,13 @@ export declare class ECS implements QueryResolver {
589
629
  *
590
630
  * Cheap: walks the descriptor region once, does no column I/O.
591
631
  */
592
- publishArchetypeRowCounts(): void;
632
+ publishRowCounts(): void;
593
633
  flush(): void;
594
634
  }
595
- /** Archetype closure from a descriptor set.
596
- *
597
- * Each descriptor is a system or an observer's synthesized `SystemDescriptor`
598
- * — both carry `spawns` + `transitions`. Seeds the worklist with every
599
- * descriptor's `spawns`; iteratively applies every descriptor's `transitions`
600
- * to every discovered mask whose components cover the transition's `whenHas`.
601
- * Returns the union of seeds + reachable targets, deduplicated by hash-bucketed
602
- * mask equality.
603
- *
604
- * Termination: every transition either monotonically grows the mask (add
605
- * outpacing remove), monotonically shrinks it, or returns a mask the
606
- * `seen` map already holds. Because the universe of masks is bounded by
607
- * `2^|components|` (and in practice the in-tree spawn/transition set is
608
- * tiny — ~20 masks at most), the worklist is finite and we exit when it
609
- * empties.
610
- *
611
- * Liberal `whenHas` — over-approximation is fine; an
612
- * unreachable transition target costs one descriptor row at the SAB tail,
613
- * not column bytes. Empty `spawns` + `transitions` short-circuit to zero.
614
- */
615
- declare function computeArchetypeClosure(descriptors: Iterable<SystemDescriptor>): BitSet[];
616
- /** @internal — test seam for the closure walk. Exposed so the prewarm
617
- * tests can exercise the BFS without standing up a full Store. */
635
+ /** @internal, test seam for the closure walk that `archetype_closure.ts`
636
+ * holds. Exposed so the prewarm tests can exercise the walk without standing
637
+ * up a full Store. */
618
638
  export declare const _ecsInternals: {
619
639
  computeArchetypeClosure: typeof computeArchetypeClosure;
620
640
  };
621
- export {};
622
641
  //# sourceMappingURL=ecs.d.ts.map