@oasys/oecs 0.5.3 → 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 +1399 -276
  2. package/README.md +327 -169
  3. package/dist/core/ecs/access_check.d.cts +31 -31
  4. package/dist/core/ecs/access_check.d.ts +31 -31
  5. package/dist/core/ecs/access_check.d.ts.map +1 -1
  6. package/dist/core/ecs/archetype.d.cts +273 -205
  7. package/dist/core/ecs/archetype.d.ts +273 -205
  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 +34 -34
  13. package/dist/core/ecs/archetype_graph.d.ts +34 -34
  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 +30 -30
  28. package/dist/core/ecs/command_log.d.ts +30 -30
  29. package/dist/core/ecs/command_log.d.ts.map +1 -1
  30. package/dist/core/ecs/component.d.cts +45 -44
  31. package/dist/core/ecs/component.d.ts +45 -44
  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 +337 -276
  46. package/dist/core/ecs/ecs.d.ts +337 -276
  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 +24 -22
  57. package/dist/core/ecs/entity_allocator.d.ts +24 -22
  58. package/dist/core/ecs/entity_allocator.d.ts.map +1 -1
  59. package/dist/core/ecs/event.d.cts +37 -23
  60. package/dist/core/ecs/event.d.ts +37 -23
  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 +34 -34
  69. package/dist/core/ecs/frame_trace.d.ts +34 -34
  70. package/dist/core/ecs/frame_trace.d.ts.map +1 -1
  71. package/dist/core/ecs/host_commands.d.cts +107 -89
  72. package/dist/core/ecs/host_commands.d.ts +107 -89
  73. package/dist/core/ecs/host_commands.d.ts.map +1 -1
  74. package/dist/core/ecs/index.d.cts +22 -12
  75. package/dist/core/ecs/index.d.ts +22 -12
  76. package/dist/core/ecs/index.d.ts.map +1 -1
  77. package/dist/core/ecs/observer.d.cts +41 -122
  78. package/dist/core/ecs/observer.d.ts +41 -122
  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 +219 -568
  90. package/dist/core/ecs/query.d.ts +219 -568
  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 +129 -16
  102. package/dist/core/ecs/ref.d.ts +129 -16
  103. package/dist/core/ecs/ref.d.ts.map +1 -1
  104. package/dist/core/ecs/relation.d.cts +105 -186
  105. package/dist/core/ecs/relation.d.ts +105 -186
  106. package/dist/core/ecs/relation.d.ts.map +1 -1
  107. package/dist/core/ecs/resource.d.cts +14 -14
  108. package/dist/core/ecs/resource.d.ts +14 -14
  109. package/dist/core/ecs/resource_registry.d.cts +6 -6
  110. package/dist/core/ecs/resource_registry.d.ts +6 -6
  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 +98 -114
  119. package/dist/core/ecs/schedule.d.ts +98 -114
  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 +110 -53
  131. package/dist/core/ecs/sparse_store.d.ts +110 -53
  132. package/dist/core/ecs/sparse_store.d.ts.map +1 -1
  133. package/dist/core/ecs/store.d.cts +644 -511
  134. package/dist/core/ecs/store.d.ts +644 -511
  135. package/dist/core/ecs/store.d.ts.map +1 -1
  136. package/dist/core/ecs/store_layout_listener.d.cts +8 -8
  137. package/dist/core/ecs/store_layout_listener.d.ts +8 -8
  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 +151 -66
  142. package/dist/core/ecs/system.d.ts +151 -66
  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 +87 -4
  154. package/dist/core/ecs/utils/error.d.ts +87 -4
  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 +48 -49
  163. package/dist/core/store/action_ring.d.ts +48 -49
  164. package/dist/core/store/action_ring.d.ts.map +1 -1
  165. package/dist/core/store/allocator.d.cts +166 -114
  166. package/dist/core/store/allocator.d.ts +166 -114
  167. package/dist/core/store/allocator.d.ts.map +1 -1
  168. package/dist/core/store/buffer_backed_column.d.cts +21 -22
  169. package/dist/core/store/buffer_backed_column.d.ts +21 -22
  170. package/dist/core/store/buffer_backed_column.d.ts.map +1 -1
  171. package/dist/core/store/column_store.d.cts +138 -100
  172. package/dist/core/store/column_store.d.ts +138 -100
  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 +41 -45
  178. package/dist/core/store/command_ring.d.ts +41 -45
  179. package/dist/core/store/command_ring.d.ts.map +1 -1
  180. package/dist/core/store/descriptor.d.cts +35 -18
  181. package/dist/core/store/descriptor.d.ts +35 -18
  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 +40 -42
  187. package/dist/core/store/event_ring.d.ts +40 -42
  188. package/dist/core/store/event_ring.d.ts.map +1 -1
  189. package/dist/core/store/extend.d.cts +15 -9
  190. package/dist/core/store/extend.d.ts +15 -9
  191. package/dist/core/store/extend.d.ts.map +1 -1
  192. package/dist/core/store/grow.d.cts +3 -3
  193. package/dist/core/store/grow.d.ts +3 -3
  194. package/dist/core/store/grow.d.ts.map +1 -1
  195. package/dist/core/store/header.d.cts +37 -33
  196. package/dist/core/store/header.d.ts +37 -33
  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 +72 -63
  202. package/dist/core/store/layout_ops.d.ts +72 -63
  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 +14 -14
  211. package/dist/core/store/state_hash.d.ts +14 -14
  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 +16 -11
  225. package/dist/index.d.ts +16 -11
  226. package/dist/index.d.ts.map +1 -1
  227. package/dist/index.development.cjs +1 -1
  228. package/dist/index.development.js +6709 -5729
  229. package/dist/index.js +5664 -4743
  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 +56 -56
  244. package/dist/{extensions → plugins}/editor/editor.d.ts +56 -56
  245. package/dist/plugins/editor/editor.d.ts.map +1 -0
  246. package/dist/{extensions → plugins}/editor/field_handle.d.cts +13 -13
  247. package/dist/{extensions → plugins}/editor/field_handle.d.ts +13 -13
  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} +83 -66
  257. package/dist/{extensions/editor/index.js → plugins/editor.js} +83 -66
  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 +93 -105
  302. package/dist/{core/ecs → plugins/relations}/relation_service.d.ts +93 -105
  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 +18 -17
  411. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts +18 -17
  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 +4 -4
  415. package/dist/version.d.ts +4 -4
  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-3jyFfWNg.js +0 -2326
  465. package/dist/host_commands-DNf0f6ko.cjs +0 -1
  466. package/dist/internal-C9jjL90H.js +0 -2485
  467. package/dist/internal-RZN14uMw.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-9S1pY_Iw.js +0 -159
  502. package/dist/shallow-C5YmTbtb.cjs +0 -1
  503. package/dist/shallow-DQ8aG51_.cjs +0 -1
  504. package/dist/shallow-DfnAm9vG.js +0 -150
  505. package/dist/shared-BMXh9hxm.cjs +0 -1
  506. package/dist/shared-DQKK0i-E.js +0 -109
  507. package/dist/topological_sort-BDvEyb9W.cjs +0 -1
  508. package/dist/topological_sort-DK6EjpWa.js +0 -135
  509. package/dist/typed_arrays-BcXcnzB4.js +0 -258
  510. package/dist/typed_arrays-D3NmwtCG.cjs +0 -1
@@ -1,415 +1,304 @@
1
- import { Store } from './store.cjs';
2
- import { FrameTraceSink } from './frame_trace.cjs';
3
1
  import { Archetype, ArchetypeView } from './archetype.cjs';
4
2
  import { EntityID } from './entity.cjs';
5
- import { ComponentDef, ComponentHandle, ComponentID, MutableColumnsForSchema, ColumnsForSchema, AttachValuesArg, SchemaOf, FieldValues, DeclaredQueryTerm } from './component.cjs';
6
- import { SparseComponentDef, SparseComponentID, SparseSchemaOf } from './sparse_store.cjs';
3
+ import { ComponentDef } from './component.cjs';
4
+ import { SparseComponentDef } from './sparse_store.cjs';
7
5
  import { RelationDef } from './relation.cjs';
8
- import { SystemAccess, DeclaredRead, DeclaredWrite, DeclaredAdd, DeclaredRemove, DeclaredSparseRead, DeclaredSparseWrite, DeclaredRelationRead, DeclaredRelationWrite, DeclaredResourceRead, DeclaredResourceWrite, DespawnArg } from './system.cjs';
9
- import { ComponentRef, ReadonlyComponentRef } from './ref.cjs';
10
- import { EventKey, EventReader, EventShape, SignalKey } from './event.cjs';
11
- import { ResourceKey, ResourceValueOf } from './resource.cjs';
12
6
  import { BitSet } from '../../type_primitives/index.cjs';
13
- /** The query-driver seam on `Store` — the typed contract behind the
14
- * underscore members `ecs.ts` and the query internals reach (M1). `Store`
15
- * implements this; when the cache/driver layer is extracted (M2/H1) the
16
- * interface retargets at the collaborator without touching consumers.
17
- * `_tick` / `_trace` are deliberately mutable: `ECS.update()` advances the
18
- * change tick and `ECS.setTrace` installs the sink through this seam. */
19
- export interface QueryHost {
20
- /** Change tick — advanced by `ECS.update()` each frame. */
21
- _tick: number;
22
- /** Dev-only frame-trace sink (`ECS.setTrace`); always null in prod. */
23
- _trace: FrameTraceSink | null;
24
- /** True once any component observer opted into per-entity dirty tracking —
25
- * gates `_noteSet` at every write site. */
26
- readonly _anyDirtyTracked: boolean;
27
- /** Bumped when an archetype crosses empty↔non-empty — cached query
28
- * archetype lists rebuild when their observed epoch is stale (#327). */
29
- readonly _queryDirtyEpoch: number;
30
- /** Record a per-entity onSet dirty mark for `def` (gated by
31
- * `_anyDirtyTracked` at the call site). */
32
- _noteSet(def: ComponentHandle, eid: EntityID): void;
33
- /** Dev-only: buffered event count across dirty channels (mid-update emit
34
- * detection in `ECS.update()`). */
35
- _devBufferedEventCount(): number;
36
- /** Second query-match path: sparse-term intersection (#469 / ADR-0011). */
37
- _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;
38
- /** Third query-match path: the `(*, T)` wildcard (#579). */
39
- _forEachRelationTargetMatch(target: EntityID, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
40
- /** Fourth query-match path: hierarchy depth ordering (#581). */
41
- _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;
42
- }
43
- export interface QueryCacheEntry {
44
- includeMask: BitSet;
45
- excludeMask: BitSet | null;
46
- anyOfMask: BitSet | null;
47
- query: Query<any>;
48
- }
49
- /** One owner for every query-resolution cache (M2). Previously the dedup
50
- * bucket map lived on `ECS` while `Query` populated eleven composition maps
51
- * declared on the resolver interface — ownership split across two modules.
52
- * All entries are structural (a query is minted once per unique term set and
53
- * lives for the world's lifetime; components and queries are never
54
- * unregistered), so there is no invalidation lifecycle — the maps are
55
- * append-only. Key encodings are unchanged from the pre-extraction fields.
56
- *
57
- * The composition maps are exposed as readonly fields (not per-kind accessor
58
- * pairs): the mutation protocol is uniform (`get` → miss → build → `set`) and
59
- * hot enough that composition sites keep direct map access; the invariant
60
- * this class carries is single ownership, not access mediation. */
61
- export declare class QueryCache {
62
- private readonly dedup;
63
- readonly andSingle: Map<number, Query<any>>;
64
- readonly notSingle: Map<number, Query<any>>;
65
- readonly anyOfSingle: Map<number, Query<any>>;
66
- readonly changedSingle: Map<number, ChangedQuery<any>>;
67
- readonly optionalSingle: Map<number, Query<any>>;
68
- readonly withSparseSingle: Map<number, Query<any>>;
69
- readonly withoutSparseSingle: Map<number, Query<any>>;
70
- readonly withRelationSingle: Map<number, Query<any>>;
71
- readonly withoutRelationSingle: Map<number, Query<any>>;
72
- readonly includeDisabledSingle: Map<number, Query<any>>;
73
- readonly hierarchySingle: Map<number, Query<any>>;
74
- /** Dedup lookup: bucket scan with full mask equality (buckets are
75
- * typically 1–2 entries). */
76
- findDedup(key: number, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null): QueryCacheEntry | undefined;
77
- /** Record a freshly minted query under its dedup key. */
78
- addDedup(key: number, entry: QueryCacheEntry): void;
79
- }
80
- export interface QueryResolver {
81
- _resolveQuery(include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, defs: readonly ComponentDef[]): Query<any>;
82
- _getLastRunTick(): number;
83
- /** Current ECS write tick — the tick `eachChunk` stamps via `cols.mut` (§eachChunk). */
84
- _getCurrentTick(): number;
85
- _getQueryDirtyEpoch(): number;
86
- _nextQueryId(): number;
87
- /** All query-resolution caches — dedup + composition (M2). One owner; see
88
- * `QueryCache` for the per-map keying/id-space notes. */
89
- readonly _caches: QueryCache;
90
- /** Second query-match path (#469 / ADR-0011): drive iteration by sparse
91
- * membership rather than the archetype mask, yielding entities — sparse
92
- * members are scattered across archetypes, so there is no archetype-column
93
- * span to hand back. With a sparse require term, drive from the smallest
94
- * required store and filter; with only sparse excludes, drive the dense
95
- * archetype list and skip excluded rows; with neither, walk dense entities.
96
- * Only entered via `Query.forEachEntity`, so dense `forEach` never pays.
97
- * `includeDisabled` widens the per-archetype row scan from enabled rows to
98
- * all rows (#577). */
99
- _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;
100
- /** Backing sparse id of a relation — resolves a `(R, *)` wildcard term
101
- * (`withRelation`, #579) to the membership store the sparse-match path
102
- * already drives. */
103
- _relationBackingSparseId(def: RelationDef): SparseComponentID;
104
- /** Third query-match path (#579): `(*, T)` — drive iteration from the union of
105
- * every relation's `sourcesOf(target)` (dedup + canonical sort), intersected
106
- * with the dense mask + sparse terms + the enabled-row filter. Only entered via
107
- * `Query.forEachRelatedTo`. */
108
- _forEachRelationTargetMatch(target: EntityID, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, sparseInclude: readonly SparseComponentID[], sparseExclude: readonly SparseComponentID[], includeDisabled: boolean, cb: (entityId: EntityID) => void): void;
109
- /** Fourth query-match path (#581): yield the matched entities (dense mask +
110
- * sparse terms + enabled-row filter, exactly the `_forEachSparseMatch`
111
- * intersection) in canonical **hierarchy depth order** over exclusive relation
112
- * `relation` — depth ascending (parents before children), entity index
113
- * ascending within a depth band. Entities deeper than `maxDepth` are skipped
114
- * (`HIERARCHY_UNBOUNDED` = no limit). Only entered via `Query.forEachEntity`
115
- * on a query carrying a `.hierarchy(R)` term. */
116
- _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;
117
- }
118
- /** No depth limit on a `.hierarchy(R)` term (#581) — yield every matched entity
119
- * regardless of its depth in the tree. The default `maxDepth`. */
120
- export declare const HIERARCHY_UNBOUNDED: number;
121
- /** A `.hierarchy(R)` depth-ordering term (#581). Records the exclusive relation
122
- * whose tree defines the order and the (optional) max depth to yield. Stored on
123
- * the Query and consumed by the `forEachEntity` hierarchy match path; absent
124
- * (`null`) for the common case. */
125
- export interface HierarchyTerm {
126
- /** The exclusive relation whose chain/tree defines the depth ordering. */
127
- readonly relation: RelationDef;
128
- /** Inclusive max depth to yield (root = 0); entities deeper than this are
129
- * skipped. `HIERARCHY_UNBOUNDED` for no limit (bitECS `Hierarchy()` depth arg). */
130
- readonly maxDepth: number;
131
- }
132
- /**
133
- * eachChunk cursor (§eachChunk). One instance is allocated per `eachChunk`
134
- * pass and reused across every matched archetype in that pass — only `_arch`/
135
- * `_tick` are re-pointed per archetype, so the inner loop allocates nothing.
136
- * Per-call (not cached on the query) so a nested `eachChunk` on the same query
137
- * gets its own cursor and can't re-point an outer pass's position. `.mut(def)` /
138
- * `.read(def)` resolve a whole component's columns at once into a field-keyed
139
- * object (a per-archetype-per-component cache refreshed in place), hiding the
140
- * change tick. Destructure the group immediately; don't retain it across calls.
141
- */
142
- export declare class ChunkColumns<out Defs extends readonly ComponentDef<any>[] = readonly ComponentDef<any>[]> {
143
- /** @internal */ _arch: Archetype;
144
- /** @internal */ _tick: number;
145
- /** Mutable column group — `const { x, y } = cols.mut(Pos)`. Stamps the tick.
146
- * `def` must be a term of the iterating query (POLISH_AUDIT #6). */
147
- mut<D extends ComponentDef<any>>(def: D & DeclaredQueryTerm<Defs, D>): MutableColumnsForSchema<SchemaOf<D>>;
148
- /** Read-only column group — `const { vx, vy } = cols.read(Vel)`. No tick bump.
149
- * `def` must be a term of the iterating query (POLISH_AUDIT #6). */
150
- read<D extends ComponentDef<any>>(def: D & DeclaredQueryTerm<Defs, D>): ColumnsForSchema<SchemaOf<D>>;
151
- }
7
+ import { ArchetypeTerm, QueryTerms } from './query_terms.cjs';
8
+ import { QueryResolver } from './query_cache.cjs';
9
+ import { ChunkColumns } from './chunk_columns.cjs';
10
+ import { ChangedQuery } from './changed_query.cjs';
152
11
  export declare class Query<Defs extends readonly ComponentDef[]> {
153
12
  private readonly _archetypes;
154
- readonly _defs: Defs;
13
+ readonly defs: Defs;
155
14
  private readonly _resolver;
156
- readonly _include: BitSet;
15
+ readonly include: BitSet;
157
16
  private readonly _exclude;
158
17
  private readonly _anyOf;
159
18
  private _nonEmptyArchetypes;
160
19
  private _lastSeenEpoch;
161
- readonly _id: number;
162
- readonly _sparseInclude: readonly SparseComponentID[];
163
- readonly _sparseExclude: readonly SparseComponentID[];
164
- readonly _optional: readonly ComponentID[];
165
- readonly _includeDisabled: boolean;
166
- readonly _relationIncludes: readonly RelationDef[];
167
- readonly _relationExcludes: readonly RelationDef[];
168
- readonly _hierarchy: HierarchyTerm | null;
169
- constructor(archetypes: Archetype[], defs: Defs, resolver: QueryResolver, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, id: number, sparseInclude?: readonly SparseComponentID[], sparseExclude?: readonly SparseComponentID[], optional?: readonly ComponentID[], includeDisabled?: boolean, relationIncludes?: readonly RelationDef[], relationExcludes?: readonly RelationDef[], hierarchy?: HierarchyTerm | null);
170
- /** Guard the dense-only methods (`count` / `forEach` / `archetype_count`)
171
- * against a query carrying sparse terms. These walk the dense archetype
172
- * list and never consult `_sparseInclude` / `_sparseExclude`, so on a
173
- * sparse-derived query they'd **fail open** — returning the unfiltered dense
20
+ readonly id: number;
21
+ readonly terms: QueryTerms;
22
+ readonly includesDisabled: boolean;
23
+ constructor(archetypes: Archetype[], defs: Defs, resolver: QueryResolver, include: BitSet, exclude: BitSet | null, anyOf: BitSet | null, id: number, terms?: QueryTerms);
24
+ /** Guard the dense-only methods `entityCount`, `archetypeCount`, `forEach`,
25
+ * `forEachChunk` and `some` against a query carrying sparse terms. These
26
+ * walk the dense archetype
27
+ * list and never consult `sparseIncludes` or `sparseExcludes`, so on a
28
+ * sparse-derived query they would fail open, returning the unfiltered dense
174
29
  * result instead of the sparse-filtered one. Throw in `DEV` (compiled
175
30
  * out of prod) steering the caller to `forEachEntity`, the only path that
176
- * honors sparse membership (#469). Mirrors `ChangedQuery`'s dev-guard on its
31
+ * honors sparse membership. Mirrors `ChangedQuery`'s dev-guard on its
177
32
  * include-mask invariant. */
178
33
  private _assertDenseOnly;
179
- /** Whether this query carries only dense terms the precondition for the
34
+ /** Refuse a reader that answers from the unfiltered dense list. Three do:
35
+ * `archetypeCount`, `archetypes` and `excludeWords`. Each would report the
36
+ * archetypes the mask picked and not the ones the term kept, which is a
37
+ * wider set and a wrong answer. Dev-only, and prod keeps the reader. */
38
+ private _assertNoArchetypeTerm;
39
+ /** Whether this query carries only dense terms, the precondition for the
180
40
  * archetype-walk fast paths (`entityCount`, `firstEntity`, `singleEntity`). */
181
41
  private _isDenseOnly;
182
- /** First matching entity, or `undefined` when the query matches none the
42
+ /** First matching entity, or `undefined` when the query matches none, the
183
43
  * singleton read (`player`, `camera`) without hand-rolling a forEach +
184
- * closure capture (POLISH_AUDIT M8). Dense-only queries answer from the
185
- * first non-empty archetype in O(archetypes); queries with sparse /
186
- * relation / hierarchy terms fall back to a full `forEachEntity` walk.
187
- * "First" is iteration order, not spawn order with more than one match
44
+ * closure capture. Dense-only queries answer from the
45
+ * first non-empty archetype in O(archetypes). A query with a sparse, relation
46
+ * or hierarchy term falls back to a full `forEachEntity` walk.
47
+ * "First" is iteration order, not spawn order, with more than one match
188
48
  * the pick is arbitrary (use `singleEntity` to assert uniqueness). */
189
49
  firstEntity(): EntityID | undefined;
190
50
  /** The query's one matching entity. Dev-throws `QUERY_NOT_SINGLETON` when
191
- * the match count is 0 or >1 the singleton assertion for entities that
51
+ * the match count is 0 or >1, the singleton assertion for entities that
192
52
  * must be unique (player, camera). Prod skips the count and returns the
193
53
  * first match (`undefined` if none). */
194
54
  singleEntity(): EntityID;
195
- /** Count for non-dense queries full `forEachEntity` walk. */
55
+ /** Count for non-dense queries, full `forEachEntity` walk. */
196
56
  private _countViaWalk;
197
57
  /** Number of matching archetypes (including empty ones). */
198
58
  get archetypeCount(): number;
199
- /** Total entity count across all matching archetypes enabled rows only by
200
- * default, or all rows when `includeDisabled()` (#577). Reads the partition
59
+ /** Total entity count across all matching archetypes, enabled rows only by
60
+ * default, or all rows when `includeDisabled`. Reads the partition
201
61
  * fields directly (not the archetype's flag-dependent `entityCount`
202
62
  * getter). */
203
63
  get entityCount(): number;
64
+ /** @internal The exclude-mask as raw words, or `null` when the query has no
65
+ * `not` term. A worker resolves the matched archetypes from the masks
66
+ * alone, so the parallel plan carries these words to the pool. */
67
+ get excludeWords(): readonly number[] | null;
204
68
  get archetypes(): readonly ArchetypeView<Defs>[];
205
- /** Carry this query's non-dense terms optional fetch-if-present (#575) and
206
- * sparse membership (#469) — onto a freshly composed dense query. `and` /
207
- * `not` / `anyOf` build the new dense mask via `_resolveQuery`, which is
208
- * keyed on the mask alone and so hands back a query carrying NONE of these
209
- * terms; before #592 that silently dropped them, making composition
210
- * order-dependent (`q.optional(V).and(H)` lost `V`; `q.and(H).optional(V)`
69
+ /** Carry this query's non-dense terms, optional fetch-if-present and
70
+ * sparse membership, onto a freshly composed dense query. `and`,
71
+ * `not` and `or` build the new dense mask via `resolveQuery`, which is
72
+ * keyed on the mask alone and so hands back a query carrying none of these
73
+ * terms. An earlier version silently dropped them, which made composition
74
+ * order-dependent (`q.optional(V).and(H)` lost `V`, `q.and(H).optional(V)`
211
75
  * kept it). When this query carries no non-dense terms (the common case)
212
76
  * `base` is already correct and returned as-is, preserving the mask-cached
213
77
  * singleton with zero allocation. Otherwise re-derive on top of `base`'s dense
214
78
  * state, threading the terms forward so composition is symmetric regardless of
215
- * order. Reading `base`'s private fields is allowed same-class instance. */
79
+ * order. Reading `base`'s private fields is allowed, same-class instance. */
216
80
  private _carryNondense;
217
81
  /** Extend required component set. Returns a new (cached) Query. */
218
82
  and<D extends ComponentDef[]>(...comps: D): Query<[...Defs, ...D]>;
219
- /** @internal cold cache-miss path for single-arg `and`, split out (#649) so
220
- * the hot `and` body is just key-compute + cache hit. The miss path runs once
221
- * per unique composition, then every repeat is a cache hit; keeping it out of
83
+ /** @internal, cold cache-miss path for single-arg `and`, split out so
84
+ * the hot `and` body is only key-compute + cache hit. The miss path runs once
85
+ * per unique composition, then every repeat is a cache hit. Keeping it out of
222
86
  * line shrinks `and`'s inlined footprint when several composes share one hot
223
- * function (the `query_compose` shape). Same rationale for `_notMiss` /
224
- * `_anyOfMiss` / `_changedMiss`. */
87
+ * function (the `query_compose` shape). Same rationale for `_notMiss`,
88
+ * `_orMiss` and `_changedMiss`. */
225
89
  private _andMiss;
226
90
  /** Exclude archetypes that have any of these components. */
227
- without(...comps: ComponentDef[]): Query<Defs>;
228
- /** @internal cold cache-miss path for single-arg `not` (#649); see `_andMiss`. */
91
+ not(...comps: ComponentDef[]): Query<Defs>;
92
+ /** @internal, cold cache-miss path for single-arg `not`. See `_andMiss`. */
229
93
  private _notMiss;
230
- /** Require a sparse component (#469): match only entities that hold it,
94
+ /** Require a sparse component: match only entities that hold it,
231
95
  * across every archetype. A sparse term doesn't touch the dense mask, so
232
- * the returned (cached) query reuses this one's live archetype list; it is
96
+ * the returned (cached) query reuses this one's live archetype list. It is
233
97
  * iterated via `forEachEntity`, never `forEach` (sparse members are
234
98
  * scattered within archetypes, so there is no SoA column span to yield). */
235
- withSparse(...defs: SparseComponentDef[]): Query<Defs>;
236
- /** One-id `withSparse` composition, cached on `(parent_id, sparseId)` in
99
+ andSparse(...defs: SparseComponentDef[]): Query<Defs>;
100
+ /** One-id `andSparse` composition, cached on `(parent_id, sparseId)` in
237
101
  * the resolver's shared single-term map. Both the single- and multi-arg public
238
102
  * forms fold over this, so all sparse-require composition is deduplicated. */
239
- private _withSparseOne;
240
- /** Exclude a sparse component (#469): drop entities that hold it. Same
241
- * dense-list reuse and `forEachEntity` iteration as `withSparse`. */
242
- withoutSparse(...defs: SparseComponentDef[]): Query<Defs>;
243
- /** One-id `withoutSparse` composition, cached on `(parent_id, sparseId)`. The
244
- * multi-arg form folds over this (#497) — mirrors `_withSparseOne`. */
245
- private _withoutSparseOne;
103
+ private _andSparseOne;
104
+ /** Exclude a sparse component: drop entities that hold it. Same
105
+ * dense-list reuse and `forEachEntity` iteration as `andSparse`. */
106
+ notSparse(...defs: SparseComponentDef[]): Query<Defs>;
107
+ /** One-id `notSparse` composition, cached on `(parent_id, sparseId)`. The
108
+ * multi-arg form folds over this, mirrors `_andSparseOne`. */
109
+ private _notSparseOne;
246
110
  /** Build a derived query carrying new sparse terms. Reuses this query's
247
- * dense state by reference the masks are never mutated in place (`and` /
248
- * `not` / `anyOf` copy before mutating), and `_archetypes` is the same
111
+ * dense state by reference, the masks are never mutated in place (`and`,
112
+ * `not` and `or` copy before mutating), and `_archetypes` is the same
249
113
  * live array the store appends to, so the derived query stays live too.
250
- * Carries the existing `_optional` terms through unchanged (the two axes
114
+ * Carries the existing `optionalTerms` terms through unchanged (the two axes
251
115
  * compose). */
252
116
  private _deriveSparse;
253
- /** Require the `(R, *)` wildcard (#579): match only sources that hold **any**
117
+ /** Narrow the matched archetypes by an expression, or by a term a plugin
118
+ * built.
119
+ *
120
+ * A chained term asks one flat question of the mask. An expression nests,
121
+ * so `q.where(or(and(Pos, Vel), Frozen))` says what no chain says. Build it
122
+ * from the free `and`, `or` and `not`, which take a component definition as
123
+ * a leaf and each other as a node.
124
+ *
125
+ * A plugin supplies its own `ArchetypeTerm` instead, and `where` accepts it
126
+ * on the same footing.
127
+ *
128
+ * It composes both ways. `q.where(t).not(D)` and `q.not(D).where(t)`
129
+ * are the same set, because the derive threads the terms record forward the
130
+ * way every other non-dense term is threaded.
131
+ *
132
+ * What it costs. One predicate call per archetype, per query, at the
133
+ * rebuild the store's dirty epoch triggers. `forEach`, `forEachChunk` and
134
+ * `forEachEntity` are untouched: they walk the list the rebuild produced.
135
+ *
136
+ * What it refuses. `archetypeCount`, `archetypes` and `excludeWords` all
137
+ * answer from the unfiltered dense list, so a term-carrying query refuses
138
+ * them in a dev build rather than answering too wide.
139
+ *
140
+ * Cached per (term, parent query), so a repeated call gives one instance. */
141
+ where(term: ArchetypeTerm): Query<Defs>;
142
+ /** Require the `(R, *)` wildcard: match only sources that hold **any**
254
143
  * target under relation `R`. "Has any `(R, *)` pair" is exactly membership in
255
- * R's backing sparse store (exclusive `{target}` row / multi tag), so this is a
256
- * relation-typed front door over `withSparse` it pushes R's backing sparse
257
- * id onto `_sparseInclude` and reuses the `forEachEntity` sparse-match path
258
- * (insertion order; canonical sorting is reserved for `stateHash`/snapshot, and
259
- * costs 4–5× here for no determinism benefit — see the §579 bench report).
260
- * Membership semantics: each source once; fetch its targets with
144
+ * R's backing sparse store (exclusive `{target}` row and multi tag), so this is a
145
+ * relation-typed front door over `andSparse`. It pushes R's backing sparse
146
+ * id onto `sparseIncludes` and reuses the `forEachEntity` sparse-match path
147
+ * (insertion order, canonical sorting is reserved for `stateHash` and the
148
+ * snapshot, and costs much more here for no determinism benefit).
149
+ * Membership semantics: each source once. Fetch its targets with
261
150
  * `ctx.targetsOf(e, R)`. Requires `relationReads: [R]` (checked at iteration).
262
- * Cached per `(parent_id, relation_id)` like the sparse terms (#497). */
263
- withRelation(...defs: RelationDef[]): Query<Defs>;
264
- private _withRelationOne;
265
- /** Exclude the `(R, *)` wildcard (#579): drop sources that hold any target
266
- * under `R`. Mirror of `withRelation` on the exclude side (pushes R's
267
- * backing sparse id onto `_sparseExclude`). */
268
- withoutRelation(...defs: RelationDef[]): Query<Defs>;
269
- private _withoutRelationOne;
151
+ * Cached per `(parent_id, relation_id)` like the sparse terms. */
152
+ andRelation(...defs: RelationDef[]): Query<Defs>;
153
+ private _andRelationOne;
154
+ /** Exclude the `(R, *)` wildcard: drop sources that hold any target
155
+ * under `R`. Mirror of `andRelation` on the exclude side (pushes R's
156
+ * backing sparse id onto `sparseExcludes`). */
157
+ notRelation(...defs: RelationDef[]): Query<Defs>;
158
+ private _notRelationOne;
270
159
  /** Build a derived query carrying new relation-wildcard terms. Threads the
271
160
  * backing-sparse ids (which the driver actually consumes) plus the relation
272
- * ids (which only the `DEV` access check consumes), reusing the dense /
273
- * optional / disabled state by reference same rationale as `_deriveSparse`. */
161
+ * ids (which only the `DEV` access check consumes), reusing the dense,
162
+ * optional and disabled state by reference, same rationale as `_deriveSparse`. */
274
163
  private _deriveRelation;
275
164
  /** Order this query's matched entities in **hierarchy depth order** over the
276
- * exclusive relation `R` parents before children and (optionally) drop any
277
- * deeper than `maxDepth` (#581; flecs `cascade` / bitECS `Hierarchy()`). The
278
- * matched *set* is unchanged (still the dense mask + sparse + `(R, *)` + disabled
279
- * terms); `.hierarchy(R)` only **reorders** + depth-limits it, so an entity with
165
+ * exclusive relation `R`, parents before children, and (optionally) drop any
166
+ * deeper than `maxDepth` (flecs `cascade`, bitECS `Hierarchy()`). The
167
+ * matched set is unchanged, still the dense mask plus the sparse, `(R, *)`
168
+ * and disabled terms. `.hierarchy(R)` only reorders and depth-limits it, so an entity with
280
169
  * no `R`-parent is a root at depth 0 and still yielded (first). The canonical
281
170
  * order is depth ascending, then **entity index ascending within each depth
282
- * band** a total, insertion-order-independent order (identical across lockstep
171
+ * band**, a total, insertion-order-independent order (identical across lockstep
283
172
  * peers), produced by an O(K) radix on the entity index, never a comparator sort.
284
173
  *
285
174
  * Iterate with `forEachEntity`: members scatter across archetypes, so there is
286
- * no SoA column span `forEach` / `count` reject a hierarchy query (like a
287
- * sparse term). **Exclusive relations only** (matches the traversal constraint
288
- * #474); a multi relation throws `RELATION_MODE_MISMATCH` at iteration, and a
175
+ * no SoA column span, and `forEach` and `entityCount` reject a hierarchy query (like
176
+ * a sparse term). Exclusive relations only, which matches the traversal
177
+ * constraint. A multi relation throws `RELATION_MODE_MISMATCH` at iteration, and a
289
178
  * cycle is a loud `RELATION_CYCLE` in `DEV` (a safe break in production).
290
179
  * Requires `relationReads: [R]` (checked at iteration). Carried through
291
- * `and`/`not`/`anyOf` like the sparse terms (`_carryNondense`).
180
+ * `and`, `not` and `or` like the sparse terms (`_carryNondense`).
292
181
  *
293
- * `Defs` is unchanged `R` is an ordering, not a required component (like
294
- * `not` / `anyOf`). Returns a new query; the unbounded form is cached. */
182
+ * `Defs` is unchanged, `R` is an ordering, not a required component (like
183
+ * `not` and `or`). Returns a new query. The unbounded form is cached. */
295
184
  hierarchy(relation: RelationDef<"exclusive">, maxDepth?: number): Query<Defs>;
296
185
  /** Build a derived query carrying a hierarchy ordering term. Reuses this
297
- * query's dense / sparse / optional / disabled / relation-wildcard state by
298
- * reference (the matched set is unchanged) same rationale as `_deriveSparse`. */
186
+ * query's dense, sparse, optional, disabled and relation-wildcard state by
187
+ * reference (the matched set is unchanged), same rationale as `_deriveSparse`. */
299
188
  private _deriveHierarchy;
300
189
  /** Assert every `(R, *)` wildcard term on this query was declared in the
301
- * system's `relationReads` (#579 / #496). Iteration-time (`forEachEntity` /
190
+ * system's `relationReads`. Iteration-time (`forEachEntity` and
302
191
  * `forEachRelatedTo`), not construction-time, so it is robust to queries
303
- * built outside a system same rationale as the data-op checks. `DEV` only;
304
- * outside a system `checkRelationRead` is a no-op. */
305
- private _checkRelationAccess;
306
- /** Iterate every source related to `target` under **any** relation the
307
- * `(*, T)` wildcard (#579) — intersected with this query's dense + sparse +
192
+ * built outside a system, same rationale as the data-op checks. `DEV` only
193
+ * outside a system `assertRelationRead` is a no-op. */
194
+ private _assertRelationAccess;
195
+ /** Iterate every source related to `target` under **any** relation, the
196
+ * `(*, T)` wildcard, intersected with this query's dense + sparse +
308
197
  * `(R, *)` + disabled predicate, each source yielded once in ascending-EntityID
309
- * order (the `sourcesOf` / `sourcesOfAny` convention). `target` is supplied
198
+ * order (the `sourcesOf` and `sourcesOfAny` convention). `target` is supplied
310
199
  * here rather than as a chained term because it is a runtime `EntityID`: baking
311
200
  * it into a cached `Query` would key the cache on a recycled value and churn
312
- * query-ids, and `(*, T)` is the rare/cold shape. Composes with
313
- * `withRelation` / `withSparse` / dense terms on the receiver. Reads
201
+ * query-ids, and `(*, T)` is the rare or cold shape. Composes with
202
+ * `andRelation`, `andSparse` and dense terms on the receiver. Reads
314
203
  * every relation's reverse index, so the system must declare
315
- * `relationReads: [ANY_RELATION]` (plus `[R]` for any composed `withRelation`).
316
- * Cold/structural not a per-tick hot loop over many targets. */
204
+ * `relationReads: [ANY_RELATION]` (plus `[R]` for any composed `andRelation`).
205
+ * Cold and structural, not a per-tick hot loop over many targets. */
317
206
  forEachRelatedTo(target: EntityID, cb: (entityId: EntityID) => void): void;
318
- /** Add optional fetch-if-present terms (#575). Does NOT narrow the matched
319
- * set the dense mask is untouched, so iteration still spans archetypes with
207
+ /** Add optional fetch-if-present terms. Does not narrow the matched
208
+ * set, the dense mask is untouched, so iteration still spans archetypes with
320
209
  * and without each `T`. Read each column per archetype span via
321
210
  * `arch.getOptionalColumnRead(T, field)` (column when present, `undefined`
322
211
  * when absent). `.optional(T)` is the *declaration* that authorizes that fetch:
323
212
  * inside `forEach`, `getOptionalColumnRead` throws in `DEV` if `T` was
324
- * not declared here (#592) — the read-side analog of `reads:[T]`, which is also
213
+ * not declared here, the read-side analog of `reads:[T]`, which is also
325
214
  * still required for access coverage (both checks fire, even on the absent
326
- * span). The term is carried through `and`/`not`/`anyOf` (see
215
+ * span). The term is carried through `and`, `not` and `or` (see
327
216
  * `_carryNondense`), so it survives composition in any order. Returns a new
328
217
  * (cached) Query.
329
218
  *
330
219
  * `Defs` is unchanged (the optional `T` is not a required component, like
331
- * `not` / `anyOf`); column types come from the accessor's own generics. */
220
+ * `not` and `or`). Column types come from the accessor's own generics. */
332
221
  optional(...defs: ComponentDef[]): Query<Defs>;
333
222
  /** One-id `optional` composition, cached on `(parent_id << 16) | cid` in the
334
- * resolver's shared single-term map (dense cid <= 128, same packing as the
335
- * `and` / `not` / `anyOf` caches). */
223
+ * resolver's shared single-term map (dense cid < 128, same packing as the
224
+ * `and`, `not` and `or` caches). */
336
225
  private _optionalOne;
337
226
  /** Build a derived query carrying new optional terms. Reuses this query's
338
227
  * dense state by reference (the matched set is unchanged) and carries the
339
- * existing sparse terms through unchanged same rationale as `_deriveSparse`. */
228
+ * existing sparse terms through unchanged, same rationale as `_deriveSparse`. */
340
229
  private _deriveOptional;
341
- /** Opt this query back in to disabled entities (#577). By default a query
230
+ /** Opt this query back in to disabled entities. By default a query
342
231
  * excludes disabled entities (the iteration bound `arch.entityCount` is the
343
232
  * enabled-row count). The returned (cached) query spans disabled rows too:
344
233
  * `forEach` publishes the all-rows flag so the SoA loop's `arch.entityCount`
345
- * reports `length`, and `count`/`forEachEntity` widen accordingly. Does NOT
234
+ * reports `length`, and `entityCount` and `forEachEntity` widen accordingly. Does not
346
235
  * touch the dense mask, so it reuses this query's live archetype list and is
347
- * carried through `and`/`not`/`anyOf` like the sparse/optional terms. */
236
+ * carried through `and`, `not` or `or` like the sparse or optional terms. */
348
237
  includeDisabled(): Query<Defs>;
349
238
  forEach(cb: (arch: ArchetypeView<Defs>) => void): void;
350
- /** @internal cold `includeDisabled` wrapper for `forEach` (#577), split out
351
- * (#649) so the all-rows flag dance (`_setIterAllRows` + try/finally) stays
239
+ /** @internal, cold `includeDisabled` wrapper for `forEach`, split out
240
+ * so the all-rows flag dance (`_setIterAllRows` inside a `finally`) stays
352
241
  * out of `forEach`'s inlined hot body. The default (enabled-only) query never
353
242
  * reaches here, so V8 leaves this uninlined and `forEach` shrinks accordingly. */
354
243
  private _forEachIncludeDisabled;
355
244
  /**
356
- * Per-archetype destructured column iteration (§eachChunk) — the flecs
357
- * `run()` / koota `useStores` model, and the recommended hot-path default for
245
+ * Per-archetype destructured column iteration, the flecs
246
+ * `run()` model and the koota `useStores` model, and the recommended hot-path default for
358
247
  * mutating systems:
359
248
  *
360
- * q.eachChunk((cols, count) => {
249
+ * q.forEachChunk((cols, count) => {
361
250
  * const { x, y } = cols.mut(Pos); // whole group, tick stamped inside
362
251
  * const { vx, vy } = cols.read(Vel); // read-only group
363
252
  * for (let i = 0; i < count; i++) { x[i] += vx[i] * dt; y[i] += vy[i] * dt; }
364
253
  * });
365
254
  *
366
- * vs the raw path it replaces (per-field `getColumn` + manual `ecsTick`
255
+ * vs the raw path it replaces (per-field `getColumnMut` + manual `ecsTick`
367
256
  * thread + `entityCount` loop). It folds away: per-field fetches (one call
368
- * per component), the `getColumn`/`getColumnRead` choice (→ `.mut`/`.read`),
257
+ * per component), the `getColumnMut` and `getColumnRead` choice (→ `.mut` and `.read`),
369
258
  * the manual tick arg (hidden in `.mut`), and the `.length`-vs-`entityCount`
370
259
  * corruption trap (`count` is `entityCount`). It is also the only mutable
371
- * column accessor reachable through the iteration path the read-only
372
- * `ArchetypeView` from `forEach` deliberately omits the mutable `getColumn`.
260
+ * column accessor reachable through the iteration path, the read-only
261
+ * `ArchetypeView` from `forEach` deliberately omits the mutable `getColumnMut`.
373
262
  * The SoA inner loop is byte-identical, and the per-archetype group objects
374
263
  * are cached (zero per-archetype allocation). One `ChunkColumns` cursor is
375
264
  * allocated per pass and reused across that pass's archetypes. Honours
376
265
  * `includeDisabled()` exactly like `forEach` (the bound widens to the
377
- * disabled tail); dense-only like `forEach` (sparse/relation/hierarchy terms
378
- * throw in `DEV` iterate those with `forEachEntity`).
266
+ * disabled tail). Dense-only like `forEach`, so a sparse, relation or
267
+ * hierarchy term throws in `DEV`. Iterate those with `forEachEntity`.
379
268
  */
380
- eachChunk(cb: (cols: ChunkColumns<Defs>, count: number) => void): void;
381
- /** @internal shared body for `eachChunk`'s default and `includeDisabled`
382
- * paths. The `ChunkColumns` cursor is allocated per call (a 2-field object whose
383
- * cost doesn't scale with the per-row work) rather than cached on the query, so
384
- * a nested `eachChunk` on the SAME query gets its own cursor instead of
385
- * re-pointing the outer pass's `_arch`/`_tick`. The per-(archetype, component)
269
+ forEachChunk(cb: (cols: ChunkColumns<Defs>, count: number) => void): void;
270
+ /** @internal, shared body for `forEachChunk`'s default and `includeDisabled`
271
+ * paths. The `ChunkColumns` cursor is allocated per call (a small object whose
272
+ * cost does not scale with the per-row work) rather than cached on the query, so
273
+ * a nested `forEachChunk` on the same query gets its own cursor instead of
274
+ * re-pointing the outer pass's `arch` and `tick`. The per-(archetype, component)
386
275
  * column-group caches that actually matter for allocation live on the
387
276
  * `Archetype`, untouched. */
388
- private _eachChunkInner;
277
+ private _forEachChunkInner;
389
278
  /**
390
279
  * Early-exit iteration: like `forEach`, but stops as soon as `cb` returns
391
280
  * `true`, and returns whether any callback did. The predicate analog for
392
- * "does any matching row satisfy X?" without it, callers hand-rolled a
393
- * `query.archetypes` walk (re-implementing the empty-archetype skip) just
281
+ * "does any matching row satisfy X?", without it, callers hand-rolled a
282
+ * `query.archetypes` walk (re-implementing the empty-archetype skip) only
394
283
  * to be able to `return` mid-scan. Deliberately a separate method:
395
284
  * honouring return values on `forEach`'s existing `=> void` callback
396
285
  * would silently change behaviour for arrow-expression bodies that happen
397
286
  * to return a truthy value.
398
287
  */
399
- forEachUntil(cb: (arch: ArchetypeView<Defs>) => boolean): boolean;
400
- /** @internal shared body for `forEachUntil`'s default and
288
+ some(cb: (arch: ArchetypeView<Defs>) => boolean): boolean;
289
+ /** @internal, shared body for `some`'s default and
401
290
  * `includeDisabled` paths. Same dev-mode optional-term scope as
402
- * `forEach` (#592). */
403
- private _forEachUntilInner;
404
- /** @internal the `includeDisabled` delegate for `forEach` (#577). The
291
+ * `forEach`. */
292
+ private _someInner;
293
+ /** @internal, the `includeDisabled` delegate for `forEach`. The
405
294
  * default (enabled-only) path inlines this body directly into `forEach`
406
- * (#608) to dodge a megamorphic delegate hop; this copy survives only for the
407
- * rare all-rows path, which needs the `_setIterAllRows` try/finally wrap. */
295
+ * to dodge a megamorphic delegate hop. This copy survives only for the
296
+ * rare all-rows path, which needs the `_setIterAllRows` `finally` wrap. */
408
297
  private _forEachInner;
409
298
  /** Iterate the entities this query matches, yielding each `EntityID`
410
- * (#469 — the sparse-membership match path). Use this whenever the query
411
- * carries a `withSparse` / `withoutSparse` term: members are scattered
412
- * across archetypes, so there is no SoA column span to hand back read
299
+ * (the sparse-membership match path). Use this whenever the query
300
+ * carries a `andSparse` or a `notSparse` term. Members are scattered
301
+ * across archetypes, so there is no SoA column span to hand back, read
413
302
  * fields via `ctx.getField` (dense) or `ctx.getSparseField` (sparse) on
414
303
  * the yielded entity. A dense-only query also works here (it walks its
415
304
  * archetypes' entity ids), but prefer `forEach` for the SoA hot loop.
@@ -419,316 +308,78 @@ export declare class Query<Defs extends readonly ComponentDef[]> {
419
308
  * key array, so **adding** the driving component (the store `push`es a new
420
309
  * key, which the `i < length` loop then visits) and **removing** it (the
421
310
  * store swap-pops, shifting the index list under the walk) both corrupt the
422
- * traversal. This is sharper than for dense `forEach`: `ctx.addSparse` /
423
- * `ctx.addRelation` apply *immediately* (no archetype transition to defer),
311
+ * traversal. This is sharper than for dense `forEach`. `ctx.addSparse` and
312
+ * `ctx.addRelation` apply immediately (no archetype transition to defer),
424
313
  * so unlike a deferred dense `addComponent` the mutation lands in the live
425
314
  * array at once. Buffer such edits and apply them after the walk. */
426
315
  forEachEntity(cb: (entityId: EntityID) => void): void;
427
- /** @internal used by ChangedQuery. Rebuild non-empty archetype list if the
316
+ /** @internal, used by ChangedQuery. Rebuild non-empty archetype list if the
428
317
  * Store has bumped its dirty epoch since our last rebuild, return cached result.
429
318
  *
430
319
  * Rebuild allocates a *fresh* array and swaps it in rather than truncating
431
- * the cached one in place (#431). `forEach`/`count`/`ChangedQuery.forEach`
432
- * bind the returned array once and walk it; an in-place `dst.length = 0` +
433
- * re-push would corrupt that walk if the query is re-entrantly iterated
320
+ * the cached one in place. `forEach`, `entityCount` and `ChangedQuery.forEach`
321
+ * bind the returned array once and walk it. An in-place `dst.length = 0` +
322
+ * re-push would corrupt that walk if the query is re-entrantly iterated,
434
323
  * i.e. the callback runs an immediate-mode mutation that crosses a
435
324
  * 0↔non-zero entity boundary on the *same* Query (bumping the epoch) and
436
- * then re-enters here via a nested `forEach`/`count`. Building fresh hands
325
+ * then re-enters here via a nested `forEach` or `entityCount`. Building fresh hands
437
326
  * the inner call its own array and leaves the outer iterator's snapshot
438
327
  * intact, so each archetype is visited exactly once. Cost is one array
439
- * allocation per epoch advance (rare only on boundary crossings); the
328
+ * allocation per epoch advance, and only on a boundary crossing. The
440
329
  * steady-state path returns the cached array with zero allocation. In-system
441
330
  * iteration never triggers a rebuild mid-loop: deferred mutations settle the
442
331
  * epoch during `flushStructural`, between systems. */
443
- _nonEmpty(): Archetype[];
444
- /** @internal cold rebuild path for `_nonEmpty`, split out (#649) so the
445
- * hot `_nonEmpty` body is just an epoch check + cached return. Keeping the
446
- * filter loops here shrinks `_nonEmpty`'s inlined bytecode footprint, which
332
+ nonEmptyArchs(): Archetype[];
333
+ /** @internal, cold rebuild path for `nonEmptyArchs`, split out so the
334
+ * hot `nonEmptyArchs` body is only an epoch check + cached return. Keeping the
335
+ * filter loops here shrinks `nonEmptyArchs`'s inlined bytecode footprint, which
447
336
  * matters when several composed queries iterate inside one hot function (the
448
- * `query_compose` shape): the leaner `_nonEmpty` keeps `forEach` under V8's
337
+ * `query_compose` shape): the leaner `nonEmptyArchs` keeps `forEach` under V8's
449
338
  * per-function cumulative inlining budget. */
450
339
  private _rebuildNonEmpty;
340
+ /** @internal, the rebuild of a query that carries plugin archetype terms.
341
+ * Same non-empty filter as `_rebuildNonEmpty`, with every term consulted
342
+ * for each surviving archetype. Separate body so a query with no term
343
+ * never loads a term list. */
344
+ private _rebuildFiltered;
451
345
  /** Require at least one of these components. */
452
- anyOf(...comps: ComponentDef[]): Query<Defs>;
453
- /** @internal cold cache-miss path for single-arg `anyOf` (#649); see `_andMiss`. */
454
- private _anyOfMiss;
346
+ or(...comps: ComponentDef[]): Query<Defs>;
347
+ /** @internal, cold cache-miss path for single-arg `or`. See `_andMiss`. */
348
+ private _orMiss;
455
349
  /** Create a ChangedQuery that filters archetypes by change tick.
456
350
  *
457
- * Granularity is **archetype**, not row: the `_changedTick[cid]` is
458
- * bumped per archetype on any write into that component's column
459
- * (`Archetype._changedTick` in archetype.ts). A 1-row write in a
460
- * 1000-row archetype trips `forEach` on the whole archetype next tick.
461
- * Use cases that need row-level granularity should compare per-row
462
- * state explicitly inside the callback.
351
+ * `forEach` works at archetype grain, not row grain: the store stamps
352
+ * `changedTick[cid]` per archetype on any write into that component's
353
+ * column (`Archetype.changedTick` in archetype.ts). One changed row trips
354
+ * `forEach` on the whole archetype next tick. For row grain, iterate with
355
+ * `forEachChunk` and read `cols.ticksRead(def)`, which needs
356
+ * `ecs.trackRows(def)`.
463
357
  *
464
- * The returned ChangedQuery is composable (M6): `and`/`without`/`anyOf`/
465
- * `optional` refine it further, so `q.changed(Pos).without(Dead)` works and
466
- * is the same set as `q.without(Dead).changed(Pos)`. */
358
+ * A stamp is reported once. The change tick advances before every
359
+ * system run, so a stamp made by an earlier system this frame is above
360
+ * the reader's last run, and a stamp the reader already saw is not.
361
+ *
362
+ * The returned ChangedQuery is composable. `and`, `not`, `or` and
363
+ * `optional` refine it further, so `q.changed(Pos).not(Dead)` works, and
364
+ * is the same set as `q.not(Dead).changed(Pos)`. */
467
365
  changed(...defs: ComponentDef[]): ChangedQuery<Defs>;
468
- /** @internal cold cache-miss path for single-arg `changed` (#649); see `_andMiss`. */
366
+ /** @internal, cold cache-miss path for single-arg `changed`. See `_andMiss`. */
469
367
  private _changedMiss;
470
- /** @internal reads lastRunTick from the resolver (ECS). */
471
- _ctxLastRunTick(): number;
368
+ /** @internal, reads lastRunTick from the resolver (ECS). */
369
+ lastRunTick(): number;
370
+ /** @internal, the change tick, for a `ChangedQuery` chunk pass. */
371
+ changeTick(): number;
372
+ /** @internal, the resolver, for a `ChangedQuery` chunk pass. */
373
+ resolver(): QueryResolver;
374
+ /** @internal, the dense-only guard, for a `ChangedQuery` chunk pass. */
375
+ assertDenseOnly(op: string): void;
472
376
  }
473
377
  export declare class QueryBuilder {
474
378
  private readonly _resolver;
475
379
  constructor(_resolver: QueryResolver);
476
- with<T extends ComponentDef[]>(...defs: T): Query<T>;
477
- }
478
- /**
479
- * A `BundleOrDef` whose def is constrained to the enclosing system's declared
480
- * add surface (§typestate). The bundle branch restates `Bundle`'s shape with
481
- * the def slot narrowed — intersecting `Bundle<any> & { def: … }` instead
482
- * would put two `ComponentDef` instantiations in one intersection, which TS
483
- * relates leniently (see system.ts §typestate notes).
484
- *
485
- * The outer conditional is a deliberate no-op (`[D] extends [unknown]` is
486
- * always true): it makes the variance of `D` — and therefore of the access
487
- * param `A` threaded through `Commands` / `SystemContext` — UNMEASURABLE to
488
- * the compiler. A measurable (plain-union) definition here gets `A` marked
489
- * reliably contravariant, variance-based comparison then rejects
490
- * `SystemContext<Narrow> → SystemContext` without the structural fallback,
491
- * and every helper taking a bare `SystemContext` stops accepting typed
492
- * contexts. Unmeasurable variance forces the structural path, where class
493
- * methods compare bivariantly and the conversion holds.
494
- *
495
- * The inner `D extends ComponentDef ? … : never` DISTRIBUTES over the declared
496
- * add-set union, so each raw-literal branch carries its OWN def's schema
497
- * (`Partial<FieldValues<SchemaOf<D>>>`) rather than the erased
498
- * `Partial<Record<string, number>>`. A hand-written `{ def: Vel, values: { x }}`
499
- * whose fields don't match its def is then rejected in a DECLARED-ACCESS system
500
- * — matching the `StrictBundles` guarantee on the `ecs.*` surface. A PERMISSIVE
501
- * context (`add: ComponentDef<any>`, i.e. an unnarrowed / `exclusive` system)
502
- * keeps the loose shape, which is the point of opting out of narrowing. The
503
- * outer no-op is preserved, so the variance invariant above still holds
504
- * (verified: the `permissiveHelper(ctx)` assertion still compiles).
505
- */
506
- export type DeclaredBundleOrDef<D> = [D] extends [unknown] ? D extends ComponentDef ? D | {
507
- readonly def: D;
508
- readonly values: Readonly<Partial<FieldValues<SchemaOf<D>>>>;
509
- } : never : never;
510
- /**
511
- * Deferred structural-command facade (§ctx.commands — Bevy `Commands`).
512
- * Namespaces the deferred structural ops so the call site is self-documenting:
513
- * `ctx.commands.add(e, …)` is *always* deferred (applied at the phase flush),
514
- * ending the collision where `ecs.addComponent` (immediate) and a bare
515
- * `ctx.addComponent` (deferred) would share a name with opposite timing. Takes
516
- * varargs callable bundles, so one shape — `commands.spawn(bundle(Pos,{x,y}), bundle(Vel,{vx:1}))`
517
- * — serves spawn and add. This is the ONLY deferred surface: the bare
518
- * `ctx.addComponent` / `ctx.removeComponent` / `ctx.disable` / `ctx.enable`
519
- * duplicates were removed in 0.5.0, completing the receiver-implies-timing
520
- * rule (`ecs.*` immediate, `ctx.commands.*` deferred) that 0.5.0 started for
521
- * spawn/despawn.
522
- *
523
- * `A` narrows the def-taking methods to the enclosing system's declared access
524
- * (§typestate, system.ts); the default is fully permissive.
525
- *
526
- * `out A` (declared covariance) is deliberate: every use of `A` sits inside a
527
- * declared-access conditional, whose variance the compiler cannot measure —
528
- * left unannotated, the measured verdict rejects `Commands<Narrow> →
529
- * Commands` (the direction every permissive consumer needs). Covariance is
530
- * the honest direction: a context with MORE declared access is usable where
531
- * one with less is expected. The checks themselves are per-instantiation, so
532
- * the annotation does not weaken them.
533
- */
534
- export declare class Commands<out A extends SystemAccess = SystemAccess> {
535
- private readonly store;
536
- constructor(store: Store);
537
- /** Spawn from bundles. Create is immediate (the id is returned now); the
538
- * component attaches are deferred to the phase flush — so until that flush the
539
- * entity exists in its empty/partial archetype and a query running later in
540
- * the same phase can observe it half-built. (Same semantics as
541
- * `ctx.commands.spawn()` + `ctx.addComponent`; fully-deferred id-reservation
542
- * spawn, à la Bevy, is a separate follow-up.) */
543
- spawn(...items: DeclaredBundleOrDef<A["add"]>[]): EntityID;
544
- /** Attach bundles to an existing entity (deferred). Bundles zero-fill
545
- * omitted fields. */
546
- add(entityId: EntityID, ...items: DeclaredBundleOrDef<A["add"]>[]): this;
547
- /** Explicit complete-values attach (deferred) — the compile-checked shape
548
- * where a typo'd or missing field is a compile error, mirroring the
549
- * immediate `ecs.addComponent(e, def, values)`. Tags take no values
550
- * argument (`AttachValuesArg`). */
551
- add<D extends ComponentDef<any>>(entityId: EntityID, def: D & DeclaredAdd<A, D>, ...values: AttachValuesArg<SchemaOf<D>>): this;
552
- /** Remove a component (deferred). */
553
- remove<D extends ComponentDef<any>>(entityId: EntityID, def: D & DeclaredRemove<A, D>): this;
554
- /** Destroy an entity (deferred). */
555
- despawn(entityId: DespawnArg<A>): this;
556
- /** Buffer `entityId` to be disabled at the phase flush (idempotent, #577).
557
- * Deferred because a toggle is an in-archetype row swap, which would corrupt
558
- * a `forEach` SoA loop iterating that archetype if applied mid-system (it
559
- * reorders the dense columns being read). A disabled entity is excluded from
560
- * default queries; opt back in per query with `.includeDisabled()`. The
561
- * immediate read is `ctx.isDisabled`. */
562
- disable(entityId: EntityID): this;
563
- /** Buffer `entityId` to be re-enabled at the phase flush (idempotent).
564
- * Deferred for the same row-swap reason as `disable`. */
565
- enable(entityId: EntityID): this;
566
- }
567
- /**
568
- * The per-system world facade. `A` is the system's declared access surface
569
- * (§typestate, system.ts): the config-form `registerSystem` computes it from
570
- * the literal `reads`/`writes`/… declarations and every guarded method below
571
- * checks its handle argument against the matching union at compile time —
572
- * the same rules `accessCheck` enforces at runtime in `DEV`. The default
573
- * `A = SystemAccess` is fully permissive, so a bare `SystemContext` (helper
574
- * functions, host-side code, explicitly-annotated escape hatches) behaves
575
- * exactly as before, and every narrowed `SystemContext<…>` is assignable to
576
- * it.
577
- *
578
- * `out A` (declared covariance) is deliberate — see `Commands` above: the
579
- * declared-access conditionals are unmeasurable to the compiler, and the
580
- * unannotated verdict rejects exactly the `SystemContext<Narrow> →
581
- * SystemContext` conversion the whole design depends on.
582
- */
583
- export declare class SystemContext<out A extends SystemAccess = SystemAccess> {
584
- private readonly store;
585
- lastRunTick: number;
586
- /** Deferred structural-command facade (§ctx.commands). */
587
- readonly commands: Commands<A>;
588
- /** Current ECS tick. Use this for write ticks in getColumn. */
589
- get ecsTick(): number;
590
- /** The world's frame-trace sink (ADR-0030), or `null`. Lets the schedule
591
- * fire `systemStart`/`flush*` without reaching into the private store.
592
- * Read only under `if (DEV)`; the seam is dead-code-eliminated in prod. */
593
- get _trace(): FrameTraceSink | null;
594
- constructor(store: Store);
595
- isAlive(entityId: EntityID): boolean;
596
- hasComponent(entityId: EntityID, def: ComponentDef): boolean;
597
- getField<D extends ComponentDef<any>>(entityId: EntityID, def: D & DeclaredRead<A, D>, field: string & keyof SchemaOf<D>): number;
598
- /** Total sibling of {@link getField}, mirroring `ecs.tryGetField`
599
- * (POLISH_AUDIT #9): `undefined` when the entity is dead or doesn't hold
600
- * the component, instead of a dev throw / prod garbage read. The safe way
601
- * to probe-and-read in one call: `ctx.tryGetField(e, Health, "current") ?? 0`. */
602
- tryGetField<D extends ComponentDef<any>>(entityId: EntityID, def: D & DeclaredRead<A, D>, field: string & keyof SchemaOf<D>): number | undefined;
603
- setField<D extends ComponentDef<any>>(entityId: EntityID, def: D & DeclaredWrite<A, D>, field: string & keyof SchemaOf<D>, value: number): void;
604
- /** Read-modify-write one field: `updateField(e, Gold, "value", v => v - cost)`
605
- * is the one-line form of the `getField` → compute → `setField` round trip.
606
- * Returns the written value. Same access-check and observer semantics as the
607
- * two calls it composes (inlined here: the declared-access conditionals on
608
- * those methods only resolve per `A` instantiation, so a body where `A` is
609
- * still generic cannot call them without casts). */
610
- updateField<D extends ComponentDef<any>>(entityId: EntityID, def: D & DeclaredWrite<A, D>, field: string & keyof SchemaOf<D>, fn: (current: number) => number): number;
611
- /**
612
- * Record an entity as changed for a component's per-entity `onSet` observer
613
- * (#517 §1 / ADR-0013). The SoA write idiom — `const col = arch.getColumn(D,
614
- * f, tick); col[i] = v` in a tight loop — bypasses the deferred buffer and the
615
- * engine never sees the per-element writes, so a per-entity `onSet` consumer
616
- * pushes the row here (the bench's winning `tick+list`: raw write + an int
617
- * push, fired batched at the post-update detection point — never a per-element
618
- * observable setter). No-op for components without a per-entity onSet observer.
619
- * `setField` records automatically; this is for the hot `getColumn` loop.
620
- */
621
- markChanged(entityId: EntityID, def: ComponentDef): void;
622
- /**
623
- * Create a cached component reference for a single entity. Marks the
624
- * component as changed (the mutable default — see `refRead` for the
625
- * read-only variant to reach for when you are not mutating). See ref.ts.
626
- */
627
- ref<D extends ComponentDef<any>>(def: D & DeclaredWrite<A, D>, entityId: EntityID): ComponentRef<SchemaOf<D>>;
628
- /**
629
- * Create a cached read-only component reference for a single entity. Use
630
- * this when you are not mutating. The returned `ReadonlyComponentRef<S>`
631
- * is an *advisory* compile-time barrier (no `_changedTick` bump): the
632
- * `readonly` typing blocks field writes at the type layer, but the
633
- * underlying accessor shares its prototype with `ref()` and can still be
634
- * written through a §10c-policed cast. See ref.ts.
635
- */
636
- refRead<D extends ComponentDef<any>>(def: D & DeclaredRead<A, D>, entityId: EntityID): ReadonlyComponentRef<SchemaOf<D>>;
637
- /** Whether `entityId` is currently disabled (immediate read). Toggling is
638
- * deferred — `ctx.commands.disable` / `ctx.commands.enable` (#577). */
639
- isDisabled(entityId: EntityID): boolean;
640
- /** Tags take no values argument; valued schemas require a complete one. */
641
- addSparse<D extends SparseComponentDef<any>>(entityId: EntityID, def: D & DeclaredSparseWrite<A, D>, ...values: AttachValuesArg<SparseSchemaOf<D>>): this;
642
- removeSparse<D extends SparseComponentDef<any>>(entityId: EntityID, def: D & DeclaredSparseWrite<A, D>): this;
643
- hasSparse(entityId: EntityID, def: SparseComponentDef): boolean;
644
- getSparseField<D extends SparseComponentDef<any>>(entityId: EntityID, def: D & DeclaredSparseRead<A, D>, field: string & keyof SparseSchemaOf<D>): number;
645
- setSparseField<D extends SparseComponentDef<any>>(entityId: EntityID, def: D & DeclaredSparseWrite<A, D>, field: string & keyof SparseSchemaOf<D>, value: number): void;
646
- /** Add a `(R, tgt)` pair to `src` (exclusive replaces, multi adds). */
647
- addRelation<D extends RelationDef>(src: EntityID, def: D & DeclaredRelationWrite<A, D>, tgt: EntityID): this;
648
- /** Remove a `(R, tgt)` pair from `src`; for multi, omitting `tgt` removes all. */
649
- removeRelation<D extends RelationDef>(src: EntityID, def: D & DeclaredRelationWrite<A, D>, tgt?: EntityID): this;
650
- /** The single target of `src` under an exclusive relation, or `undefined`. */
651
- targetOf<D extends RelationDef<"exclusive">>(src: EntityID, def: D & DeclaredRelationRead<A, D>): EntityID | undefined;
652
- /** All targets of `src` under `R`, ascending by id. */
653
- targetsOf<D extends RelationDef>(src: EntityID, def: D & DeclaredRelationRead<A, D>): EntityID[];
654
- /** Sources pointing at `tgt` under `R` (the reverse index), ascending by id.
655
- * `(entity, def)` order, matching `targetOf` / `targetsOf`. */
656
- sourcesOf<D extends RelationDef>(tgt: EntityID, def: D & DeclaredRelationRead<A, D>): EntityID[];
657
- /** Whether `src` holds any pair under `R`. */
658
- hasRelation(src: EntityID, def: RelationDef): boolean;
659
- /** Flush all deferred changes: structural (add/remove) first, then
660
- * destructions. Republishes archetype row counts into the SAB
661
- * descriptor at the end so any WASM scan running in the next phase
662
- * sees fresh `row_count` fields. This is one of two publish sites —
663
- * `ECS.update()` also republishes once at tick start (see PATTERNS.md
664
- * §60), covering host-side mutations between updates. The publish walks
665
- * descriptors only — it doesn't touch column data — and benches at
666
- * sub-microsecond per archetype, so paying it once per phase boundary
667
- * is materially cheaper than the pre-#306 pattern of paying it per
668
- * WASM-using system per tick. After #336 the descriptor walk is gated
669
- * on a dirty flag, so read-only phases skip the walk entirely. */
670
- flush(): void;
671
- /**
672
- * Emit an event (or a payload-less signal) onto its channel. The event is
673
- * visible to every system that runs *later* in the same `update()` and is
674
- * cleared at the tick's tail — events live exactly one tick, there is no
675
- * ack/consume. The channel must have been registered at world setup via
676
- * `ecs.events.register(key, fields)` / `registerSignal(key)`.
677
- *
678
- * @example
679
- * const Damaged = eventKey<{ target: EntityID; amount: number }>("Damaged");
680
- * ecs.events.register(Damaged, ["target", "amount"]);
681
- * // inside a system:
682
- * ctx.emit(Damaged, { target: e, amount: 10 });
683
- */
684
- emit(key: SignalKey): void;
685
- emit<S extends EventShape<S>>(key: EventKey<S>, values: NoInfer<S>): void;
686
- /**
687
- * Read this tick's events on a channel. Returns an SoA reader over
688
- * everything emitted *earlier in the same `update()`* — order systems so
689
- * readers run after emitters, or they see an empty reader.
690
- *
691
- * @example
692
- * const dmg = ctx.read(Damaged); // SoA columns, one per field
693
- * for (let i = 0; i < dmg.length; i++) {
694
- * applyDamage(dmg.target[i], dmg.amount[i]);
695
- * }
696
- */
697
- read<S extends EventShape<S>>(key: EventKey<S>): EventReader<S>;
698
- /** Read a resource (declared in `resourceReads`). The flat `ctx` surface verbs
699
- * its accessors — `getResource`/`setResource`/`removeResource`/`hasResource`,
700
- * matching `getField`/`setField`/`hasComponent`. The grouped `ecs.resources`
701
- * facade drops the noun (`get`/`set`/`remove`/`has`) because its receiver
702
- * already names it. */
703
- getResource<K extends ResourceKey<any>>(key: K & DeclaredResourceRead<A, K>): ResourceValueOf<K>;
704
- setResource<K extends ResourceKey<any>>(key: K & DeclaredResourceWrite<A, K>, value: ResourceValueOf<NoInfer<K>>): void;
705
- /** Drop a resource mid-tick (#798). A lifecycle mutation, so it is access-
706
- * checked as a *write* — the system must declare the key in `resourceWrites`,
707
- * which serialises it against readers/writers of the same resource. Fails
708
- * closed on a missing key. */
709
- removeResource<K extends ResourceKey<any>>(key: K & DeclaredResourceWrite<A, K>): void;
710
- hasResource<T>(key: ResourceKey<T>): boolean;
711
- }
712
- export declare class ChangedQuery<Defs extends readonly ComponentDef[]> {
713
- private readonly _query;
714
- private readonly _changedIds;
715
- constructor(query: Query<Defs>, changedIds: number[]);
716
- /** Also require these components (mirrors `Query.and`). */
717
- and<D extends ComponentDef[]>(...comps: D): ChangedQuery<[...Defs, ...D]>;
718
- /** Exclude archetypes holding any of these (mirrors `Query.without`). */
719
- without(...comps: ComponentDef[]): ChangedQuery<Defs>;
720
- /** Require at least one of these (mirrors `Query.anyOf`). */
721
- anyOf(...comps: ComponentDef[]): ChangedQuery<Defs>;
722
- /** Permit optional-component data access in the loop (mirrors `Query.optional`). */
723
- optional(...defs: ComponentDef[]): ChangedQuery<Defs>;
724
- forEach(cb: (arch: ArchetypeView<Defs>) => void): void;
725
- /** @internal — cold `includeDisabled` wrapper (#577), split out of `forEach`
726
- * (#649) so the all-rows flag dance stays out of the inlined hot body. */
727
- private _forEachIncludeDisabled;
728
- /** @internal — the `includeDisabled` delegate for `forEach` (#577). The
729
- * default path inlines this body directly into `forEach` (#608) to dodge a
730
- * megamorphic delegate hop; this copy survives only for the rare all-rows
731
- * path, which needs the `_setIterAllRows` try/finally wrap. */
732
- private _forEachInner;
380
+ /** Require these components. The first link of the chain takes the same
381
+ * word as every later link, so `qb.and(Pos).and(Vel)` and `qb.and(Pos, Vel)`
382
+ * read alike and mean one thing. */
383
+ and<T extends ComponentDef[]>(...defs: T): Query<T>;
733
384
  }
734
385
  //# sourceMappingURL=query.d.ts.map