murow 0.0.70 → 0.0.71

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 (439) hide show
  1. package/README.md +52 -37
  2. package/dist/cjs/core/binary-codec/binary-codec.js +1 -0
  3. package/dist/cjs/core/binary-codec/index.js +1 -0
  4. package/dist/cjs/core/driver/driver.js +1 -0
  5. package/dist/cjs/core/driver/drivers/immediate.js +1 -0
  6. package/dist/cjs/core/driver/drivers/index.js +1 -0
  7. package/dist/cjs/core/driver/drivers/raf.js +1 -0
  8. package/dist/cjs/core/driver/drivers/timeout.js +1 -0
  9. package/dist/cjs/core/driver/index.js +1 -0
  10. package/dist/cjs/core/events/event-system.js +1 -0
  11. package/dist/cjs/core/events/index.js +1 -0
  12. package/dist/cjs/core/fixed-ticker/fixed-ticker.js +1 -0
  13. package/dist/cjs/core/fixed-ticker/index.js +1 -0
  14. package/dist/cjs/core/free-list/free-list.js +1 -0
  15. package/dist/cjs/core/free-list/index.js +1 -0
  16. package/dist/cjs/core/generate-id/generate-id.js +1 -0
  17. package/dist/cjs/core/generate-id/index.js +1 -0
  18. package/dist/cjs/core/index.js +1 -0
  19. package/dist/cjs/core/input/index.js +1 -0
  20. package/dist/cjs/core/input/manager.js +1 -0
  21. package/dist/cjs/core/input/sources/browser.js +1 -0
  22. package/dist/cjs/core/input/sources/index.js +1 -0
  23. package/dist/cjs/core/input/types.js +1 -0
  24. package/dist/cjs/core/lerp/index.js +1 -0
  25. package/dist/cjs/core/lerp/lerp.js +1 -0
  26. package/dist/cjs/core/navmesh/index.js +1 -0
  27. package/dist/cjs/core/navmesh/navmesh-worker-pool.js +1 -0
  28. package/dist/cjs/core/navmesh/navmesh.js +1 -0
  29. package/dist/cjs/core/navmesh/navmesh.worker.js +1 -0
  30. package/dist/cjs/core/pooled-codec/index.js +1 -0
  31. package/dist/cjs/core/pooled-codec/pooled-codec.js +1 -0
  32. package/dist/cjs/core/prediction/index.js +1 -0
  33. package/dist/cjs/core/prediction/prediction.js +1 -0
  34. package/dist/cjs/core/ray/index.js +1 -0
  35. package/dist/cjs/core/ray/ray-2d.js +1 -0
  36. package/dist/cjs/core/ray/ray-3d.js +1 -0
  37. package/dist/cjs/core/simple-rng/index.js +1 -0
  38. package/dist/cjs/core/simple-rng/simple-rng.js +1 -0
  39. package/dist/cjs/core/sparse-batcher/index.js +1 -0
  40. package/dist/cjs/core/sparse-batcher/sparse-batcher.js +1 -0
  41. package/dist/cjs/ecs/component-store.js +1 -0
  42. package/dist/cjs/ecs/component.js +1 -0
  43. package/dist/cjs/ecs/entity-handle.js +1 -0
  44. package/dist/cjs/ecs/index.js +1 -0
  45. package/dist/cjs/ecs/system-builder.js +1 -0
  46. package/dist/cjs/ecs/world-systems.js +1 -0
  47. package/dist/cjs/ecs/world.js +1 -0
  48. package/dist/cjs/game/index.js +1 -0
  49. package/dist/cjs/game/loop/index.js +1 -0
  50. package/dist/cjs/game/loop/loop.js +1 -0
  51. package/dist/cjs/index.js +1 -0
  52. package/dist/cjs/net/adapters/browser-websocket.js +1 -0
  53. package/dist/cjs/net/adapters/bun-websocket.js +1 -0
  54. package/dist/cjs/net/buffer-pool.js +1 -0
  55. package/dist/cjs/net/client.js +1 -0
  56. package/dist/cjs/net/index.js +1 -0
  57. package/dist/cjs/net/server.js +1 -0
  58. package/dist/cjs/net/types.js +1 -0
  59. package/dist/cjs/net/validators.js +1 -0
  60. package/dist/cjs/protocol/index.js +1 -0
  61. package/dist/cjs/protocol/intent/define-intent.js +1 -0
  62. package/dist/cjs/protocol/intent/index.js +1 -0
  63. package/dist/cjs/protocol/intent/intent-registry.js +1 -0
  64. package/dist/cjs/protocol/intent/intent.js +1 -0
  65. package/dist/cjs/protocol/rpc/define-rpc.js +1 -0
  66. package/dist/cjs/protocol/rpc/index.js +1 -0
  67. package/dist/cjs/protocol/rpc/rpc-registry.js +1 -0
  68. package/dist/cjs/protocol/rpc/rpc.js +1 -0
  69. package/dist/cjs/protocol/snapshot/index.js +1 -0
  70. package/dist/cjs/protocol/snapshot/snapshot-codec.js +1 -0
  71. package/dist/cjs/protocol/snapshot/snapshot-registry.js +1 -0
  72. package/dist/cjs/protocol/snapshot/snapshot.js +1 -0
  73. package/dist/cjs/renderer/base-2d-renderer.js +1 -0
  74. package/dist/cjs/renderer/base-3d-renderer.js +1 -0
  75. package/dist/cjs/renderer/base-renderer.js +1 -0
  76. package/dist/cjs/renderer/index.js +1 -0
  77. package/dist/cjs/renderer/types.js +1 -0
  78. package/dist/esm/core/binary-codec/binary-codec.js +1 -0
  79. package/dist/esm/core/binary-codec/index.js +1 -0
  80. package/dist/esm/core/driver/driver.js +1 -0
  81. package/dist/esm/core/driver/drivers/immediate.js +1 -0
  82. package/dist/esm/core/driver/drivers/index.js +1 -0
  83. package/dist/esm/core/driver/drivers/raf.js +1 -0
  84. package/dist/esm/core/driver/drivers/timeout.js +1 -0
  85. package/dist/esm/core/driver/index.js +1 -0
  86. package/dist/esm/core/events/event-system.js +1 -0
  87. package/dist/esm/core/events/index.js +1 -0
  88. package/dist/esm/core/fixed-ticker/fixed-ticker.js +1 -0
  89. package/dist/esm/core/fixed-ticker/index.js +1 -0
  90. package/dist/esm/core/free-list/free-list.js +1 -0
  91. package/dist/esm/core/free-list/index.js +1 -0
  92. package/dist/esm/core/generate-id/generate-id.js +1 -0
  93. package/dist/esm/core/generate-id/index.js +1 -0
  94. package/dist/esm/core/index.js +1 -0
  95. package/dist/esm/core/input/index.js +1 -0
  96. package/dist/esm/core/input/manager.js +1 -0
  97. package/dist/esm/core/input/sources/browser.js +1 -0
  98. package/dist/esm/core/input/sources/index.js +1 -0
  99. package/dist/esm/core/input/types.js +0 -0
  100. package/dist/esm/core/lerp/index.js +1 -0
  101. package/dist/esm/core/lerp/lerp.js +1 -0
  102. package/dist/esm/core/navmesh/index.js +1 -0
  103. package/dist/esm/core/navmesh/navmesh-worker-pool.js +1 -0
  104. package/dist/esm/core/navmesh/navmesh.js +1 -0
  105. package/dist/esm/core/navmesh/navmesh.worker.js +1 -0
  106. package/dist/esm/core/pooled-codec/index.js +1 -0
  107. package/dist/esm/core/pooled-codec/pooled-codec.js +1 -0
  108. package/dist/esm/core/prediction/index.js +1 -0
  109. package/dist/esm/core/prediction/prediction.js +1 -0
  110. package/dist/esm/core/ray/index.js +1 -0
  111. package/dist/esm/core/ray/ray-2d.js +1 -0
  112. package/dist/esm/core/ray/ray-3d.js +1 -0
  113. package/dist/esm/core/simple-rng/index.js +1 -0
  114. package/dist/esm/core/simple-rng/simple-rng.js +1 -0
  115. package/dist/esm/core/sparse-batcher/index.js +1 -0
  116. package/dist/esm/core/sparse-batcher/sparse-batcher.js +1 -0
  117. package/dist/esm/ecs/component-store.js +1 -0
  118. package/dist/esm/ecs/component.js +1 -0
  119. package/dist/esm/ecs/entity-handle.js +1 -0
  120. package/dist/esm/ecs/index.js +1 -0
  121. package/dist/esm/ecs/system-builder.js +1 -0
  122. package/dist/esm/ecs/world-systems.js +1 -0
  123. package/dist/esm/ecs/world.js +1 -0
  124. package/dist/esm/game/index.js +1 -0
  125. package/dist/esm/game/loop/index.js +1 -0
  126. package/dist/esm/game/loop/loop.js +1 -0
  127. package/dist/esm/index.js +1 -0
  128. package/dist/esm/net/adapters/browser-websocket.js +1 -0
  129. package/dist/esm/net/adapters/bun-websocket.js +1 -0
  130. package/dist/esm/net/buffer-pool.js +1 -0
  131. package/dist/esm/net/client.js +1 -0
  132. package/dist/esm/net/index.js +1 -0
  133. package/dist/esm/net/server.js +1 -0
  134. package/dist/esm/net/types.js +1 -0
  135. package/dist/esm/net/validators.js +1 -0
  136. package/dist/esm/protocol/index.js +1 -0
  137. package/dist/esm/protocol/intent/define-intent.js +1 -0
  138. package/dist/esm/protocol/intent/index.js +1 -0
  139. package/dist/esm/protocol/intent/intent-registry.js +1 -0
  140. package/dist/esm/protocol/intent/intent.js +0 -0
  141. package/dist/esm/protocol/rpc/define-rpc.js +1 -0
  142. package/dist/esm/protocol/rpc/index.js +1 -0
  143. package/dist/esm/protocol/rpc/rpc-registry.js +1 -0
  144. package/dist/esm/protocol/rpc/rpc.js +0 -0
  145. package/dist/esm/protocol/snapshot/index.js +1 -0
  146. package/dist/esm/protocol/snapshot/snapshot-codec.js +1 -0
  147. package/dist/esm/protocol/snapshot/snapshot-registry.js +1 -0
  148. package/dist/esm/protocol/snapshot/snapshot.js +1 -0
  149. package/dist/esm/renderer/base-2d-renderer.js +1 -0
  150. package/dist/esm/renderer/base-3d-renderer.js +1 -0
  151. package/dist/esm/renderer/base-renderer.js +1 -0
  152. package/dist/esm/renderer/index.js +1 -0
  153. package/dist/esm/renderer/types.js +0 -0
  154. package/dist/{core → types/core}/binary-codec/binary-codec.d.ts +4 -0
  155. package/dist/{core → types/core}/events/event-system.d.ts +14 -33
  156. package/dist/types/core/free-list/free-list.d.ts +31 -0
  157. package/dist/types/core/free-list/index.d.ts +1 -0
  158. package/dist/{core → types/core}/index.d.ts +5 -0
  159. package/dist/{core → types/core}/input/index.d.ts +1 -0
  160. package/dist/{core → types/core}/input/manager.d.ts +2 -0
  161. package/dist/{core → types/core}/navmesh/navmesh.d.ts +1 -21
  162. package/dist/types/core/ray/index.d.ts +2 -0
  163. package/dist/types/core/ray/ray-2d.d.ts +37 -0
  164. package/dist/types/core/ray/ray-3d.d.ts +42 -0
  165. package/dist/types/core/simple-rng/index.d.ts +1 -0
  166. package/dist/types/core/simple-rng/simple-rng.d.ts +36 -0
  167. package/dist/types/core/sparse-batcher/index.d.ts +1 -0
  168. package/dist/types/core/sparse-batcher/sparse-batcher.d.ts +55 -0
  169. package/dist/{ecs → types/ecs}/world.d.ts +11 -0
  170. package/dist/{game → types/game}/loop/loop.d.ts +33 -29
  171. package/dist/{index.d.ts → types/index.d.ts} +1 -0
  172. package/dist/{net → types/net}/index.d.ts +2 -2
  173. package/dist/types/renderer/base-2d-renderer.d.ts +13 -0
  174. package/dist/types/renderer/base-3d-renderer.d.ts +10 -0
  175. package/dist/types/renderer/base-renderer.d.ts +21 -0
  176. package/dist/types/renderer/index.d.ts +4 -0
  177. package/dist/types/renderer/types.d.ts +79 -0
  178. package/dist/webgpu/cjs/index.js +6004 -0
  179. package/dist/webgpu/esm/index.js +5972 -0
  180. package/dist/webgpu/types/2d/animation.d.ts +97 -0
  181. package/dist/webgpu/types/2d/renderer.d.ts +55 -0
  182. package/dist/webgpu/types/2d/shader.d.ts +61 -0
  183. package/dist/webgpu/types/2d/sprite-accessor.d.ts +47 -0
  184. package/dist/webgpu/types/3d/gltf-skin-parser.d.ts +101 -0
  185. package/dist/webgpu/types/3d/morph-animation.d.ts +69 -0
  186. package/dist/webgpu/types/3d/morph-animation.test.d.ts +1 -0
  187. package/dist/webgpu/types/3d/renderer.d.ts +216 -0
  188. package/dist/webgpu/types/3d/shader.d.ts +136 -0
  189. package/dist/webgpu/types/3d/skeletal-animation-compute/index.d.ts +2 -0
  190. package/dist/webgpu/types/3d/skeletal-animation-compute/kernel.d.ts +8 -0
  191. package/dist/webgpu/types/3d/skeletal-animation-compute/packer.d.ts +32 -0
  192. package/dist/webgpu/types/3d/skeletal-animation.d.ts +90 -0
  193. package/dist/webgpu/types/camera/camera-2d.d.ts +53 -0
  194. package/dist/webgpu/types/camera/camera-2d.test.d.ts +1 -0
  195. package/dist/webgpu/types/camera/camera-3d.d.ts +81 -0
  196. package/dist/webgpu/types/camera/camera-3d.test.d.ts +1 -0
  197. package/dist/webgpu/types/camera/index.d.ts +2 -0
  198. package/dist/webgpu/types/compute/compute-builder.d.ts +123 -0
  199. package/dist/webgpu/types/compute/compute-builder.test.d.ts +1 -0
  200. package/dist/webgpu/types/core/constants.d.ts +59 -0
  201. package/dist/webgpu/types/core/constants.test.d.ts +1 -0
  202. package/dist/webgpu/types/core/index.d.ts +2 -0
  203. package/dist/webgpu/types/core/math.d.ts +37 -0
  204. package/dist/webgpu/types/core/types.d.ts +125 -0
  205. package/dist/webgpu/types/core/types.test.d.ts +1 -0
  206. package/dist/webgpu/types/geometry/built-in.d.ts +58 -0
  207. package/dist/webgpu/types/geometry/built-in.test.d.ts +1 -0
  208. package/dist/webgpu/types/geometry/geometry-builder.d.ts +281 -0
  209. package/dist/webgpu/types/geometry/geometry-builder.test.d.ts +1 -0
  210. package/dist/webgpu/types/geometry/index.d.ts +2 -0
  211. package/dist/webgpu/types/index.d.ts +32 -0
  212. package/dist/webgpu/types/particle/emitter.d.ts +36 -0
  213. package/dist/webgpu/types/shaders/index.d.ts +2 -0
  214. package/dist/webgpu/types/shaders/runtime-transpile.d.ts +18 -0
  215. package/dist/webgpu/types/shaders/sprite-2d.wgsl.d.ts +10 -0
  216. package/dist/webgpu/types/shaders/typegpu.d.ts +9 -0
  217. package/dist/webgpu/types/shaders/utils.d.ts +28 -0
  218. package/dist/webgpu/types/shaders/utils.test.d.ts +1 -0
  219. package/dist/webgpu/types/spritesheet/index.d.ts +1 -0
  220. package/dist/webgpu/types/spritesheet/spritesheet.d.ts +57 -0
  221. package/dist/webgpu/types/spritesheet/spritesheet.test.d.ts +1 -0
  222. package/package.json +96 -26
  223. package/dist/core/binary-codec/binary-codec.js +0 -354
  224. package/dist/core/binary-codec/index.js +0 -1
  225. package/dist/core/driver/driver.js +0 -47
  226. package/dist/core/driver/drivers/immediate.js +0 -61
  227. package/dist/core/driver/drivers/index.js +0 -3
  228. package/dist/core/driver/drivers/raf.js +0 -62
  229. package/dist/core/driver/drivers/timeout.js +0 -71
  230. package/dist/core/driver/index.js +0 -2
  231. package/dist/core/events/event-system.js +0 -88
  232. package/dist/core/events/index.js +0 -1
  233. package/dist/core/fixed-ticker/fixed-ticker.js +0 -105
  234. package/dist/core/fixed-ticker/index.js +0 -1
  235. package/dist/core/generate-id/generate-id.js +0 -25
  236. package/dist/core/generate-id/index.js +0 -1
  237. package/dist/core/index.js +0 -10
  238. package/dist/core/input/index.js +0 -2
  239. package/dist/core/input/manager.js +0 -211
  240. package/dist/core/input/sources/browser.js +0 -29
  241. package/dist/core/input/sources/index.js +0 -1
  242. package/dist/core/lerp/index.js +0 -1
  243. package/dist/core/lerp/lerp.js +0 -42
  244. package/dist/core/navmesh/index.js +0 -1
  245. package/dist/core/navmesh/navmesh-worker-pool.js +0 -180
  246. package/dist/core/navmesh/navmesh.js +0 -799
  247. package/dist/core/navmesh/navmesh.worker.js +0 -79
  248. package/dist/core/pooled-codec/index.js +0 -1
  249. package/dist/core/pooled-codec/pooled-codec.js +0 -410
  250. package/dist/core/prediction/index.js +0 -1
  251. package/dist/core/prediction/prediction.js +0 -99
  252. package/dist/core.esm.js +0 -1
  253. package/dist/core.js +0 -1
  254. package/dist/ecs/component-store.js +0 -175
  255. package/dist/ecs/component.js +0 -43
  256. package/dist/ecs/entity-handle.js +0 -515
  257. package/dist/ecs/example.js +0 -125
  258. package/dist/ecs/index.js +0 -4
  259. package/dist/ecs/system-builder.js +0 -249
  260. package/dist/ecs/world-systems.js +0 -79
  261. package/dist/ecs/world.js +0 -767
  262. package/dist/game/index.js +0 -1
  263. package/dist/game/loop/index.js +0 -1
  264. package/dist/game/loop/loop.js +0 -108
  265. package/dist/index.js +0 -26
  266. package/dist/net/adapters/browser-websocket.js +0 -74
  267. package/dist/net/adapters/bun-websocket.js +0 -245
  268. package/dist/net/buffer-pool.js +0 -89
  269. package/dist/net/client.js +0 -586
  270. package/dist/net/index.js +0 -58
  271. package/dist/net/server.js +0 -974
  272. package/dist/net/types.js +0 -31
  273. package/dist/net/validators.js +0 -88
  274. package/dist/protocol/index.js +0 -92
  275. package/dist/protocol/intent/define-intent.js +0 -125
  276. package/dist/protocol/intent/index.js +0 -91
  277. package/dist/protocol/intent/intent-registry.js +0 -91
  278. package/dist/protocol/rpc/define-rpc.js +0 -84
  279. package/dist/protocol/rpc/index.js +0 -3
  280. package/dist/protocol/rpc/rpc-registry.js +0 -159
  281. package/dist/protocol/rpc/rpc.js +0 -12
  282. package/dist/protocol/snapshot/index.js +0 -43
  283. package/dist/protocol/snapshot/snapshot-codec.js +0 -67
  284. package/dist/protocol/snapshot/snapshot-registry.js +0 -168
  285. package/dist/protocol/snapshot/snapshot.js +0 -30
  286. package/src/core/binary-codec/README.md +0 -60
  287. package/src/core/binary-codec/binary-codec.test.ts +0 -300
  288. package/src/core/binary-codec/binary-codec.ts +0 -448
  289. package/src/core/binary-codec/index.ts +0 -1
  290. package/src/core/driver/README.md +0 -97
  291. package/src/core/driver/driver.test.ts +0 -414
  292. package/src/core/driver/driver.ts +0 -71
  293. package/src/core/driver/drivers/immediate.ts +0 -66
  294. package/src/core/driver/drivers/index.ts +0 -3
  295. package/src/core/driver/drivers/raf.ts +0 -67
  296. package/src/core/driver/drivers/timeout.ts +0 -77
  297. package/src/core/driver/index.ts +0 -2
  298. package/src/core/events/README.md +0 -47
  299. package/src/core/events/event-system.test.ts +0 -243
  300. package/src/core/events/event-system.ts +0 -140
  301. package/src/core/events/index.ts +0 -1
  302. package/src/core/fixed-ticker/README.md +0 -77
  303. package/src/core/fixed-ticker/fixed-ticker.test.ts +0 -151
  304. package/src/core/fixed-ticker/fixed-ticker.ts +0 -174
  305. package/src/core/fixed-ticker/index.ts +0 -1
  306. package/src/core/generate-id/README.md +0 -18
  307. package/src/core/generate-id/generate-id.test.ts +0 -79
  308. package/src/core/generate-id/generate-id.ts +0 -37
  309. package/src/core/generate-id/index.ts +0 -1
  310. package/src/core/index.ts +0 -10
  311. package/src/core/input/README.md +0 -24
  312. package/src/core/input/index.ts +0 -2
  313. package/src/core/input/manager.ts +0 -259
  314. package/src/core/input/sources/browser.ts +0 -39
  315. package/src/core/input/sources/index.ts +0 -1
  316. package/src/core/input/types.ts +0 -40
  317. package/src/core/lerp/README.md +0 -79
  318. package/src/core/lerp/index.ts +0 -1
  319. package/src/core/lerp/lerp.test.ts +0 -90
  320. package/src/core/lerp/lerp.ts +0 -42
  321. package/src/core/navmesh/README.md +0 -164
  322. package/src/core/navmesh/index.ts +0 -1
  323. package/src/core/navmesh/navmesh-worker-pool.ts +0 -236
  324. package/src/core/navmesh/navmesh-workers.test.ts +0 -356
  325. package/src/core/navmesh/navmesh.test.ts +0 -344
  326. package/src/core/navmesh/navmesh.ts +0 -1047
  327. package/src/core/navmesh/navmesh.worker.ts +0 -147
  328. package/src/core/pooled-codec/README.md +0 -70
  329. package/src/core/pooled-codec/index.ts +0 -1
  330. package/src/core/pooled-codec/pooled-codec.test.ts +0 -862
  331. package/src/core/pooled-codec/pooled-codec.ts +0 -504
  332. package/src/core/prediction/README.md +0 -64
  333. package/src/core/prediction/index.ts +0 -1
  334. package/src/core/prediction/prediction.test.ts +0 -423
  335. package/src/core/prediction/prediction.ts +0 -112
  336. package/src/ecs/README.md +0 -427
  337. package/src/ecs/benchmark.test.ts +0 -1645
  338. package/src/ecs/component-store.ts +0 -198
  339. package/src/ecs/component.ts +0 -90
  340. package/src/ecs/entity-handle.test.ts +0 -393
  341. package/src/ecs/entity-handle.ts +0 -563
  342. package/src/ecs/example.ts +0 -152
  343. package/src/ecs/index.ts +0 -4
  344. package/src/ecs/system-builder.ts +0 -404
  345. package/src/ecs/world-systems.ts +0 -83
  346. package/src/ecs/world.test.ts +0 -310
  347. package/src/ecs/world.ts +0 -904
  348. package/src/game/index.ts +0 -1
  349. package/src/game/loop/README.md +0 -32
  350. package/src/game/loop/index.ts +0 -1
  351. package/src/game/loop/loop.ts +0 -236
  352. package/src/index.ts +0 -32
  353. package/src/net/README.md +0 -474
  354. package/src/net/adapters/browser-websocket.ts +0 -86
  355. package/src/net/adapters/bun-websocket.ts +0 -292
  356. package/src/net/buffer-pool.ts +0 -106
  357. package/src/net/client.test.ts +0 -807
  358. package/src/net/client.ts +0 -695
  359. package/src/net/index.ts +0 -60
  360. package/src/net/server.test.ts +0 -799
  361. package/src/net/server.ts +0 -1152
  362. package/src/net/types.ts +0 -228
  363. package/src/net/validators.ts +0 -104
  364. package/src/protocol/README.md +0 -469
  365. package/src/protocol/index.ts +0 -93
  366. package/src/protocol/intent/define-intent.test.ts +0 -397
  367. package/src/protocol/intent/define-intent.ts +0 -201
  368. package/src/protocol/intent/index.ts +0 -94
  369. package/src/protocol/intent/intent-registry.test.ts +0 -198
  370. package/src/protocol/intent/intent-registry.ts +0 -112
  371. package/src/protocol/intent/intent.ts +0 -12
  372. package/src/protocol/rpc/define-rpc.test.ts +0 -141
  373. package/src/protocol/rpc/define-rpc.ts +0 -113
  374. package/src/protocol/rpc/index.ts +0 -3
  375. package/src/protocol/rpc/rpc-registry.test.ts +0 -168
  376. package/src/protocol/rpc/rpc-registry.ts +0 -176
  377. package/src/protocol/rpc/rpc.ts +0 -37
  378. package/src/protocol/snapshot/index.ts +0 -45
  379. package/src/protocol/snapshot/snapshot-codec.test.ts +0 -138
  380. package/src/protocol/snapshot/snapshot-codec.ts +0 -87
  381. package/src/protocol/snapshot/snapshot-registry.test.ts +0 -310
  382. package/src/protocol/snapshot/snapshot-registry.ts +0 -201
  383. package/src/protocol/snapshot/snapshot.test.ts +0 -76
  384. package/src/protocol/snapshot/snapshot.ts +0 -41
  385. /package/dist/{core → types/core}/binary-codec/index.d.ts +0 -0
  386. /package/dist/{core → types/core}/driver/driver.d.ts +0 -0
  387. /package/dist/{core → types/core}/driver/drivers/immediate.d.ts +0 -0
  388. /package/dist/{core → types/core}/driver/drivers/index.d.ts +0 -0
  389. /package/dist/{core → types/core}/driver/drivers/raf.d.ts +0 -0
  390. /package/dist/{core → types/core}/driver/drivers/timeout.d.ts +0 -0
  391. /package/dist/{core → types/core}/driver/index.d.ts +0 -0
  392. /package/dist/{core → types/core}/events/index.d.ts +0 -0
  393. /package/dist/{core → types/core}/fixed-ticker/fixed-ticker.d.ts +0 -0
  394. /package/dist/{core → types/core}/fixed-ticker/index.d.ts +0 -0
  395. /package/dist/{core → types/core}/generate-id/generate-id.d.ts +0 -0
  396. /package/dist/{core → types/core}/generate-id/index.d.ts +0 -0
  397. /package/dist/{core → types/core}/input/sources/browser.d.ts +0 -0
  398. /package/dist/{core → types/core}/input/sources/index.d.ts +0 -0
  399. /package/dist/{core → types/core}/input/types.d.ts +0 -0
  400. /package/dist/{core → types/core}/lerp/index.d.ts +0 -0
  401. /package/dist/{core → types/core}/lerp/lerp.d.ts +0 -0
  402. /package/dist/{core → types/core}/navmesh/index.d.ts +0 -0
  403. /package/dist/{core → types/core}/navmesh/navmesh-worker-pool.d.ts +0 -0
  404. /package/dist/{core → types/core}/navmesh/navmesh.worker.d.ts +0 -0
  405. /package/dist/{core → types/core}/pooled-codec/index.d.ts +0 -0
  406. /package/dist/{core → types/core}/pooled-codec/pooled-codec.d.ts +0 -0
  407. /package/dist/{core → types/core}/prediction/index.d.ts +0 -0
  408. /package/dist/{core → types/core}/prediction/prediction.d.ts +0 -0
  409. /package/dist/{ecs → types/ecs}/component-store.d.ts +0 -0
  410. /package/dist/{ecs → types/ecs}/component.d.ts +0 -0
  411. /package/dist/{ecs → types/ecs}/entity-handle.d.ts +0 -0
  412. /package/dist/{ecs → types/ecs}/example.d.ts +0 -0
  413. /package/dist/{ecs → types/ecs}/index.d.ts +0 -0
  414. /package/dist/{ecs → types/ecs}/system-builder.d.ts +0 -0
  415. /package/dist/{ecs → types/ecs}/world-systems.d.ts +0 -0
  416. /package/dist/{game → types/game}/index.d.ts +0 -0
  417. /package/dist/{game → types/game}/loop/index.d.ts +0 -0
  418. /package/dist/{net → types/net}/adapters/browser-websocket.d.ts +0 -0
  419. /package/dist/{net → types/net}/adapters/bun-websocket.d.ts +0 -0
  420. /package/dist/{net → types/net}/buffer-pool.d.ts +0 -0
  421. /package/dist/{net → types/net}/client.d.ts +0 -0
  422. /package/dist/{net → types/net}/server.d.ts +0 -0
  423. /package/dist/{net → types/net}/types.d.ts +0 -0
  424. /package/dist/{net → types/net}/validators.d.ts +0 -0
  425. /package/dist/{protocol → types/protocol}/index.d.ts +0 -0
  426. /package/dist/{protocol → types/protocol}/intent/define-intent.d.ts +0 -0
  427. /package/dist/{protocol → types/protocol}/intent/index.d.ts +0 -0
  428. /package/dist/{protocol → types/protocol}/intent/intent-registry.d.ts +0 -0
  429. /package/dist/{protocol → types/protocol}/intent/intent.d.ts +0 -0
  430. /package/dist/{protocol → types/protocol}/rpc/define-rpc.d.ts +0 -0
  431. /package/dist/{protocol → types/protocol}/rpc/index.d.ts +0 -0
  432. /package/dist/{protocol → types/protocol}/rpc/rpc-registry.d.ts +0 -0
  433. /package/dist/{protocol → types/protocol}/rpc/rpc.d.ts +0 -0
  434. /package/dist/{protocol → types/protocol}/snapshot/index.d.ts +0 -0
  435. /package/dist/{protocol → types/protocol}/snapshot/snapshot-codec.d.ts +0 -0
  436. /package/dist/{protocol → types/protocol}/snapshot/snapshot-registry.d.ts +0 -0
  437. /package/dist/{protocol → types/protocol}/snapshot/snapshot.d.ts +0 -0
  438. /package/dist/{core/input/types.js → webgpu/types/2d/animation.test.d.ts} +0 -0
  439. /package/dist/{protocol/intent/intent.js → webgpu/types/2d/sprite-accessor.test.d.ts} +0 -0
package/dist/ecs/world.js DELETED
@@ -1,767 +0,0 @@
1
- import { generateId } from "../core/generate-id";
2
- import { ComponentStore } from "./component-store";
3
- import { EntityHandle } from "./entity-handle";
4
- import { WorldSystems } from "./world-systems";
5
- /**
6
- * World manages entities and their components.
7
- * Provides efficient ECS storage using typed arrays.
8
- *
9
- * Performance optimizations:
10
- * - Array iteration instead of Set for 2-5x faster queries
11
- * - Query bitmask caching for repeated queries
12
- * - Array-indexed component stores for O(1) access
13
- * - Pre-allocated ring buffer for entity ID reuse
14
- *
15
- * @example
16
- * ```typescript
17
- * const world = new World({
18
- * maxEntities: 10000,
19
- * components: [Transform, Health, Velocity]
20
- * });
21
- *
22
- * const entity = world.spawn();
23
- * world.add(entity, Transform, { x: 100, y: 200, rotation: 0 });
24
- * world.add(entity, Health, { current: 100, max: 100 });
25
- *
26
- * // Query entities
27
- * for (const entity of world.query(Transform, Velocity)) {
28
- * const transform = world.get(entity, Transform);
29
- * const velocity = world.get(entity, Velocity);
30
- * // transform is readonly, use update() to modify
31
- * world.update(entity, Transform, {
32
- * x: transform.x + velocity.vx,
33
- * y: transform.y + velocity.vy
34
- * });
35
- * }
36
- * ```
37
- */
38
- export class World extends WorldSystems {
39
- constructor(config) {
40
- super();
41
- this.nextEntityId = 0;
42
- this.freeEntityHead = 0;
43
- this.freeEntityTail = 0;
44
- this.freeEntityCount = 0;
45
- this.freeEntityMask = 0; // Bitwise AND mask for power-of-2 modulo
46
- // Entity storage: Array for fast iteration, bitmask for O(1) alive checks
47
- this.aliveEntitiesArray = [];
48
- this.numMaskWords = 0; // Number of allocated mask words
49
- // Component registry (direct index stored on component - zero lookup cost!)
50
- this.components = [];
51
- // Query result cache (reusable buffers for zero allocations)
52
- this.queryResultBuffers = {}; // Now keyed by string hash
53
- // Persistent query cache (invalidated only on archetype changes)
54
- this.archetypeVersion = 0; // Increments on spawn/despawn/add/remove
55
- this.queryCacheVersions = {}; // Keyed by mask hash
56
- // Query mask cache (avoid recomputing masks for same component combinations)
57
- this.queryMaskCache = {};
58
- // Debug ID
59
- this.worldId = generateId({ prefix: "world_" });
60
- this.maxEntities = config.maxEntities ?? 10000;
61
- // Calculate number of mask words needed (1 word per 32 components)
62
- this.numMaskWords = Math.ceil(config.components.length / 32);
63
- // Allocate separate Uint32Array for each mask word
64
- this.componentMasks = [];
65
- for (let i = 0; i < this.numMaskWords; i++) {
66
- this.componentMasks.push(new Uint32Array(this.maxEntities));
67
- }
68
- // Cache first word for fast path (most games use <32 components)
69
- if (this.numMaskWords > 0) {
70
- this.componentMasks0 = this.componentMasks[0];
71
- }
72
- // Round up to next power of 2 for ring buffer (enables bitwise modulo)
73
- const ringBufferSize = Math.pow(2, Math.ceil(Math.log2(this.maxEntities)));
74
- this.freeEntityIds = new Uint32Array(ringBufferSize);
75
- this.freeEntityMask = ringBufferSize - 1; // For x % size → x & mask
76
- // Pre-allocate index lookup for O(1) despawn
77
- this.aliveEntitiesIndices = new Uint32Array(this.maxEntities);
78
- // Pre-allocate alive flags for O(1) alive checks
79
- this.aliveEntityFlags = new Uint8Array(this.maxEntities);
80
- // Pre-allocate arrays for component stores
81
- this.componentStoresArray = new Array(config.components.length);
82
- // Register components
83
- config.components.forEach((component, index) => {
84
- this.components.push(component);
85
- // Store index directly on component for O(1) access (no Map lookup!)
86
- component.__worldIndex = index;
87
- // Create component store with selected backend
88
- const store = new ComponentStore(component, this.maxEntities);
89
- this.componentStoresArray[index] = store;
90
- });
91
- }
92
- /**
93
- * Get component index (O(1) - stored directly on component)
94
- */
95
- getComponentIndex(component) {
96
- const index = component.__worldIndex;
97
- if (index === undefined) {
98
- const registered = this.components.map((c) => c.name).join(", ");
99
- throw new Error(`Component ${component.name} not registered in World[${this.worldId}]. ` +
100
- `Registered components: [${registered}]. ` +
101
- `Did you forget to include it in the WorldConfig?`);
102
- }
103
- return index;
104
- }
105
- /**
106
- * Set a bit in the bitmask for an entity
107
- */
108
- setComponentBit(entity, componentIndex) {
109
- const wordIndex = componentIndex >>> 5; // Which word (div 32)
110
- const bitIndex = componentIndex & 31; // Which bit in word (mod 32)
111
- this.componentMasks[wordIndex][entity] |= 1 << bitIndex;
112
- }
113
- /**
114
- * Clear a bit in the bitmask for an entity
115
- */
116
- clearComponentBit(entity, componentIndex) {
117
- const wordIndex = componentIndex >>> 5; // Which word (div 32)
118
- const bitIndex = componentIndex & 31; // Which bit in word (mod 32)
119
- this.componentMasks[wordIndex][entity] &= ~(1 << bitIndex);
120
- }
121
- /**
122
- * Check if a bit is set in the bitmask for an entity
123
- */
124
- hasComponentBit(entity, componentIndex) {
125
- const wordIndex = componentIndex >>> 5; // Which word (div 32)
126
- const bitIndex = componentIndex & 31; // Which bit in word (mod 32)
127
- return (this.componentMasks[wordIndex][entity] & (1 << bitIndex)) !== 0;
128
- }
129
- /**
130
- * Clear all component bits for an entity
131
- */
132
- clearAllComponentBits(entity) {
133
- // Fast paths for common cases (avoids loop overhead)
134
- if (this.numMaskWords === 1) {
135
- this.componentMasks0[entity] = 0;
136
- }
137
- else if (this.numMaskWords === 2) {
138
- this.componentMasks0[entity] = 0;
139
- this.componentMasks[1][entity] = 0;
140
- }
141
- else if (this.numMaskWords === 3) {
142
- this.componentMasks0[entity] = 0;
143
- this.componentMasks[1][entity] = 0;
144
- this.componentMasks[2][entity] = 0;
145
- }
146
- else {
147
- // General case for 4+ words
148
- for (let i = 0; i < this.numMaskWords; i++) {
149
- this.componentMasks[i][entity] = 0;
150
- }
151
- }
152
- }
153
- /**
154
- * Check if entity matches the required component mask
155
- * Returns true if entity has all required components
156
- *
157
- * Optimized for common case: most games use <32 components,
158
- * so we only need to check the first word
159
- */
160
- matchesComponentMask(entity, mask) {
161
- const len = mask.length;
162
- // Fast path: single word (most common - <32 components)
163
- if (len === 1) {
164
- return (this.componentMasks0[entity] & mask[0]) === mask[0];
165
- }
166
- // Unrolled for 2 words (32-63 components)
167
- if (len === 2) {
168
- return (this.componentMasks0[entity] & mask[0]) === mask[0] &&
169
- (this.componentMasks[1][entity] & mask[1]) === mask[1];
170
- }
171
- // Unrolled for 3 words (64-95 components)
172
- if (len === 3) {
173
- return (this.componentMasks0[entity] & mask[0]) === mask[0] &&
174
- (this.componentMasks[1][entity] & mask[1]) === mask[1] &&
175
- (this.componentMasks[2][entity] & mask[2]) === mask[2];
176
- }
177
- // Unrolled for 4 words (96-127 components)
178
- if (len === 4) {
179
- return (this.componentMasks0[entity] & mask[0]) === mask[0] &&
180
- (this.componentMasks[1][entity] & mask[1]) === mask[1] &&
181
- (this.componentMasks[2][entity] & mask[2]) === mask[2] &&
182
- (this.componentMasks[3][entity] & mask[3]) === mask[3];
183
- }
184
- // General case for 5+ words (rare)
185
- for (let i = 0; i < len; i++) {
186
- if ((this.componentMasks[i][entity] & mask[i]) !== mask[i]) {
187
- return false;
188
- }
189
- }
190
- return true;
191
- }
192
- /**
193
- * Get or compute query bitmask
194
- * Returns array of numbers (one 32-bit mask per word)
195
- *
196
- * Caches masks to avoid recomputation for frequently used component combinations
197
- */
198
- getQueryMask(components) {
199
- // Create cache key from component names (sorted for consistency)
200
- const cacheKey = components.map(c => c.name).sort().join(',');
201
- // Check cache first
202
- const cached = this.queryMaskCache[cacheKey];
203
- if (cached)
204
- return cached;
205
- // Find max component index to determine how many words we need
206
- let maxIndex = -1;
207
- const indices = [];
208
- for (const component of components) {
209
- const index = component.__worldIndex;
210
- if (index === undefined)
211
- return null; // Invalid mask sentinel
212
- indices.push(index);
213
- if (index > maxIndex)
214
- maxIndex = index;
215
- }
216
- // Calculate number of words needed
217
- const numWords = Math.floor(maxIndex / 32) + 1;
218
- const requiredMask = new Array(numWords).fill(0);
219
- // Set bits for each component (direct index access - no lookups!)
220
- for (const index of indices) {
221
- const wordIndex = index >>> 5; // div 32
222
- const bitIndex = index & 31; // mod 32
223
- requiredMask[wordIndex] |= 1 << bitIndex;
224
- }
225
- // Cache the mask for future queries
226
- this.queryMaskCache[cacheKey] = requiredMask;
227
- return requiredMask;
228
- }
229
- /**
230
- * Convert mask array to a hash key for caching
231
- */
232
- maskToKey(mask) {
233
- let key = '';
234
- for (let i = 0; i < mask.length; i++) {
235
- if (mask[i] !== 0) {
236
- key += `${i}:${mask[i].toString(36)},`;
237
- }
238
- }
239
- return key;
240
- }
241
- /**
242
- * Internal: Get query mask key for a set of components.
243
- * Used by SystemBuilder for precomputing query keys.
244
- * @internal
245
- */
246
- _getQueryMaskKey(components) {
247
- const mask = this.getQueryMask(components);
248
- return mask ? this.maskToKey(mask) : '';
249
- }
250
- /**
251
- * Internal: Query entities by precomputed mask key and mask.
252
- * Used by ExecutableSystem for fast queries without mask recomputation.
253
- * @internal
254
- */
255
- _queryByMaskKey(maskKey, requiredMask) {
256
- // Get or create reusable buffer for this query mask
257
- let buffer = this.queryResultBuffers[maskKey];
258
- if (!buffer) {
259
- buffer = [];
260
- this.queryResultBuffers[maskKey] = buffer;
261
- }
262
- // Check if cache is valid (persistent query caching)
263
- if (this.queryCacheVersions[maskKey] === this.archetypeVersion) {
264
- // Cache is valid! Return cached result (FAST PATH - no iteration!)
265
- return buffer;
266
- }
267
- // Cache is stale - rebuild by iterating alive entities
268
- const aliveEntities = this.aliveEntitiesArray;
269
- const length = aliveEntities.length;
270
- const numWords = requiredMask.length;
271
- let writeIdx = 0;
272
- // Fast path for single-word masks (most common case, <32 components)
273
- if (numWords === 1) {
274
- const mask0 = requiredMask[0];
275
- const componentMasks0 = this.componentMasks0;
276
- for (let i = 0; i < length; i++) {
277
- const entity = aliveEntities[i];
278
- if ((componentMasks0[entity] & mask0) === mask0) {
279
- buffer[writeIdx++] = entity;
280
- }
281
- }
282
- }
283
- else if (numWords === 2) {
284
- // Unrolled for 2 words (32-63 components)
285
- const mask0 = requiredMask[0];
286
- const mask1 = requiredMask[1];
287
- const masks0 = this.componentMasks0;
288
- const masks1 = this.componentMasks[1];
289
- for (let i = 0; i < length; i++) {
290
- const entity = aliveEntities[i];
291
- if ((masks0[entity] & mask0) === mask0 &&
292
- (masks1[entity] & mask1) === mask1) {
293
- buffer[writeIdx++] = entity;
294
- }
295
- }
296
- }
297
- else if (numWords === 3) {
298
- // Unrolled for 3 words (64-95 components)
299
- const mask0 = requiredMask[0];
300
- const mask1 = requiredMask[1];
301
- const mask2 = requiredMask[2];
302
- const masks0 = this.componentMasks0;
303
- const masks1 = this.componentMasks[1];
304
- const masks2 = this.componentMasks[2];
305
- for (let i = 0; i < length; i++) {
306
- const entity = aliveEntities[i];
307
- if ((masks0[entity] & mask0) === mask0 &&
308
- (masks1[entity] & mask1) === mask1 &&
309
- (masks2[entity] & mask2) === mask2) {
310
- buffer[writeIdx++] = entity;
311
- }
312
- }
313
- }
314
- else if (numWords === 4) {
315
- // Unrolled for 4 words (96-127 components)
316
- const mask0 = requiredMask[0];
317
- const mask1 = requiredMask[1];
318
- const mask2 = requiredMask[2];
319
- const mask3 = requiredMask[3];
320
- const masks0 = this.componentMasks0;
321
- const masks1 = this.componentMasks[1];
322
- const masks2 = this.componentMasks[2];
323
- const masks3 = this.componentMasks[3];
324
- for (let i = 0; i < length; i++) {
325
- const entity = aliveEntities[i];
326
- if ((masks0[entity] & mask0) === mask0 &&
327
- (masks1[entity] & mask1) === mask1 &&
328
- (masks2[entity] & mask2) === mask2 &&
329
- (masks3[entity] & mask3) === mask3) {
330
- buffer[writeIdx++] = entity;
331
- }
332
- }
333
- }
334
- else {
335
- // General case for 5+ words (rare)
336
- const componentMasks = this.componentMasks;
337
- outer: for (let i = 0; i < length; i++) {
338
- const entity = aliveEntities[i];
339
- for (let w = 0; w < numWords; w++) {
340
- if ((componentMasks[w][entity] & requiredMask[w]) !== requiredMask[w]) {
341
- continue outer;
342
- }
343
- }
344
- buffer[writeIdx++] = entity;
345
- }
346
- }
347
- // Truncate buffer to actual size (zero allocations)
348
- buffer.length = writeIdx;
349
- // Mark cache as valid for this archetype version
350
- this.queryCacheVersions[maskKey] = this.archetypeVersion;
351
- return buffer;
352
- }
353
- /**
354
- * Spawn a new entity.
355
- * Returns the entity ID.
356
- */
357
- spawn() {
358
- // Hot path: allocate new ID (most common case, no branching)
359
- let id = this.nextEntityId;
360
- // Cold path: reuse freed ID if available
361
- if (this.freeEntityCount > 0) {
362
- id = this.freeEntityIds[this.freeEntityTail];
363
- this.freeEntityTail = (this.freeEntityTail + 1) & this.freeEntityMask;
364
- this.freeEntityCount--;
365
- }
366
- else {
367
- this.nextEntityId++;
368
- }
369
- // Bounds check (unlikely to fail in normal operation)
370
- if (id >= this.maxEntities) {
371
- throw new Error(`Maximum entities (${this.maxEntities}) reached. ` +
372
- `Current alive: ${this.aliveEntitiesArray.length}, ` +
373
- `Free list: ${this.freeEntityCount}`);
374
- }
375
- // Fast path: setup entity (no branches)
376
- this.aliveEntityFlags[id] = 1;
377
- this.aliveEntitiesIndices[id] = this.aliveEntitiesArray.length;
378
- this.aliveEntitiesArray.push(id);
379
- this.clearAllComponentBits(id);
380
- // Invalidate query cache since entity count changed
381
- this.invalidateQueryCache();
382
- return id;
383
- }
384
- /**
385
- * Despawn an entity, removing all its components.
386
- * The entity ID will be reused.
387
- */
388
- despawn(entity) {
389
- if (this.aliveEntityFlags[entity] === 0) {
390
- return; // Already despawned
391
- }
392
- this.aliveEntityFlags[entity] = 0;
393
- // Remove from array (swap with last for O(1) removal)
394
- const idx = this.aliveEntitiesIndices[entity];
395
- const last = this.aliveEntitiesArray.length - 1;
396
- if (idx !== last) {
397
- // Swap with last element
398
- const lastEntity = this.aliveEntitiesArray[last];
399
- this.aliveEntitiesArray[idx] = lastEntity;
400
- this.aliveEntitiesIndices[lastEntity] = idx;
401
- }
402
- this.aliveEntitiesArray.pop();
403
- // Clear all components for this entity
404
- const stores = this.componentStoresArray;
405
- const componentCount = this.components.length;
406
- for (let i = 0; i < componentCount; i++) {
407
- if (this.hasComponentBit(entity, i)) {
408
- stores[i].clear(entity);
409
- }
410
- }
411
- this.clearAllComponentBits(entity);
412
- // Push to free list
413
- this.freeEntityIds[this.freeEntityHead] = entity;
414
- this.freeEntityHead = (this.freeEntityHead + 1) & this.freeEntityMask; // Bitwise AND instead of modulo
415
- this.freeEntityCount++;
416
- // Invalidate query cache since entity count changed
417
- this.invalidateQueryCache();
418
- }
419
- /**
420
- * Check if an entity is alive
421
- */
422
- isAlive(entity) {
423
- return this.aliveEntityFlags[entity] === 1;
424
- }
425
- /**
426
- * Invalidate all query caches (called on archetype changes).
427
- */
428
- invalidateQueryCache() {
429
- this.archetypeVersion++;
430
- }
431
- /**
432
- * Add a component to an entity with initial data.
433
- */
434
- add(entity, component, data) {
435
- if (this.aliveEntityFlags[entity] === 0) {
436
- throw new Error(`Cannot add component ${component.name} to entity ${entity}: ` +
437
- `entity is not alive (was it despawned?). ` +
438
- `Current alive entities: ${this.aliveEntitiesArray.length}`);
439
- }
440
- const index = this.getComponentIndex(component);
441
- const store = this.componentStoresArray[index];
442
- this.setComponentBit(entity, index);
443
- store.set(entity, data);
444
- // Invalidate query cache since archetype changed
445
- this.invalidateQueryCache();
446
- }
447
- /**
448
- * Remove a component from an entity.
449
- */
450
- remove(entity, component) {
451
- const index = component.__worldIndex;
452
- if (index === undefined)
453
- return;
454
- this.clearComponentBit(entity, index);
455
- const store = this.componentStoresArray[index];
456
- if (store) {
457
- store.clear(entity);
458
- }
459
- // Invalidate query cache since archetype changed
460
- this.invalidateQueryCache();
461
- }
462
- /**
463
- * Check if an entity has a component.
464
- */
465
- has(entity, component) {
466
- const index = component.__worldIndex;
467
- if (index === undefined)
468
- return false;
469
- return this.hasComponentBit(entity, index);
470
- }
471
- /**
472
- * Get a component's data for an entity.
473
- * Returns a READONLY reusable object (zero allocations).
474
- *
475
- * ⚠️ IMPORTANT: The returned object is reused and will be overwritten on the next get().
476
- * To modify, use set() or update() instead.
477
- * To keep multiple components, use getMutable() or spread operator.
478
- *
479
- * @example
480
- * // ✅ CORRECT: Use immediately
481
- * const t = world.get(entity, Transform);
482
- * console.log(t.x, t.y);
483
- *
484
- * // ❌ WRONG: Storing reference
485
- * const t1 = world.get(entity1, Transform);
486
- * const t2 = world.get(entity2, Transform); // t1 is now corrupted!
487
- *
488
- * // ✅ CORRECT: Copy if you need to keep
489
- * const t1 = { ...world.get(entity1, Transform) };
490
- * const t2 = { ...world.get(entity2, Transform) };
491
- */
492
- get(entity, component) {
493
- const index = this.getComponentIndex(component);
494
- if (!this.hasComponentBit(entity, index)) {
495
- const entityComponents = this.getEntityComponentNames(entity);
496
- throw new Error(`Cannot get component ${component.name} from entity ${entity}: ` +
497
- `entity does not have this component. ` +
498
- `Entity has: [${entityComponents.join(", ")}]. ` +
499
- `Did you forget to call world.add()?`);
500
- }
501
- return this.componentStoresArray[index].get(entity);
502
- }
503
- /**
504
- * Get a mutable copy of component data.
505
- * Use this when you need to modify and keep the data.
506
- *
507
- * Note: This allocates a new object. Use sparingly in hot paths.
508
- */
509
- getMutable(entity, component) {
510
- const index = this.getComponentIndex(component);
511
- if (!this.hasComponentBit(entity, index)) {
512
- throw new Error(`Entity ${entity} does not have component ${component.name}`);
513
- }
514
- return this.componentStoresArray[index].getMutable(entity);
515
- }
516
- /**
517
- * Set a component's data for an entity.
518
- * Overwrites all fields.
519
- */
520
- set(entity, component, data) {
521
- const index = this.getComponentIndex(component);
522
- if (!this.hasComponentBit(entity, index)) {
523
- throw new Error(`Cannot set component ${component.name} on entity ${entity}: ` +
524
- `entity does not have this component. Use add() first.`);
525
- }
526
- this.componentStoresArray[index].set(entity, data);
527
- }
528
- /**
529
- * Update specific fields of a component.
530
- * More efficient than get + modify + set.
531
- *
532
- * @example
533
- * // ✅ GOOD: Partial update
534
- * world.update(entity, Transform, { x: 150 });
535
- *
536
- * // ❌ BAD: Full get/set for single field
537
- * const t = world.getMutable(entity, Transform);
538
- * t.x = 150;
539
- * world.set(entity, Transform, t);
540
- */
541
- update(entity, component, partial) {
542
- const index = this.getComponentIndex(component);
543
- if (!this.hasComponentBit(entity, index)) {
544
- throw new Error(`Entity ${entity} does not have component ${component.name}`);
545
- }
546
- this.componentStoresArray[index].update(entity, partial);
547
- }
548
- /**
549
- * Query entities that have all specified components.
550
- * Returns a readonly array for zero-allocation iteration.
551
- *
552
- * Uses reusable buffers and direct bitmask checks for maximum performance.
553
- * The returned array is reused on subsequent queries with the same mask.
554
- *
555
- * @example
556
- * ```typescript
557
- * for (const entity of world.query(Transform, Velocity)) {
558
- * const t = world.get(entity, Transform);
559
- * const v = world.get(entity, Velocity);
560
- * world.update(entity, Transform, {
561
- * x: t.x + v.vx * dt,
562
- * y: t.y + v.vy * dt
563
- * });
564
- * }
565
- * ```
566
- */
567
- query(...components) {
568
- const requiredMask = this.getQueryMask(components);
569
- if (requiredMask === null)
570
- return []; // Component not registered
571
- const maskKey = this.maskToKey(requiredMask);
572
- // Get or create reusable buffer for this query mask
573
- let buffer = this.queryResultBuffers[maskKey];
574
- if (!buffer) {
575
- buffer = [];
576
- this.queryResultBuffers[maskKey] = buffer;
577
- }
578
- // Check if cache is valid (persistent query caching)
579
- if (this.queryCacheVersions[maskKey] === this.archetypeVersion) {
580
- // Cache is valid! Return cached result (FAST PATH - no iteration!)
581
- return buffer;
582
- }
583
- // Cache miss or stale - recompute query results
584
- const entities = this.aliveEntitiesArray;
585
- const length = entities.length;
586
- const numWords = requiredMask.length;
587
- // Use write cursor pattern instead of buffer.length = 0 + push
588
- let writeIdx = 0;
589
- // Inline fast path for single-word masks (avoids function call overhead)
590
- if (numWords === 1) {
591
- const mask0 = requiredMask[0];
592
- const masks0 = this.componentMasks0;
593
- for (let i = 0; i < length; i++) {
594
- const entity = entities[i];
595
- if ((masks0[entity] & mask0) === mask0) {
596
- buffer[writeIdx++] = entity;
597
- }
598
- }
599
- }
600
- else {
601
- // Fall back to matchesComponentMask for multi-word
602
- for (let i = 0; i < length; i++) {
603
- const entity = entities[i];
604
- if (this.matchesComponentMask(entity, requiredMask)) {
605
- buffer[writeIdx++] = entity;
606
- }
607
- }
608
- }
609
- // Truncate buffer to actual size
610
- buffer.length = writeIdx;
611
- // Mark cache as valid for this archetype version
612
- this.queryCacheVersions[maskKey] = this.archetypeVersion;
613
- return buffer;
614
- }
615
- /**
616
- * Get all alive entity IDs.
617
- *
618
- * ⚠️ WARNING: The returned array is a direct reference and should not be modified.
619
- * For a safe copy, use [...world.getEntities()].
620
- */
621
- getEntities() {
622
- return this.aliveEntitiesArray;
623
- }
624
- /**
625
- * Get the number of alive entities.
626
- */
627
- getEntityCount() {
628
- return this.aliveEntitiesArray.length;
629
- }
630
- /**
631
- * Get the maximum number of entities.
632
- */
633
- getMaxEntities() {
634
- return this.maxEntities;
635
- }
636
- /**
637
- * Get all registered components.
638
- */
639
- getComponents() {
640
- return this.components;
641
- }
642
- /**
643
- * Get component names for an entity (for debugging)
644
- */
645
- getEntityComponentNames(entity) {
646
- const result = [];
647
- for (let i = 0; i < this.components.length; i++) {
648
- if (this.hasComponentBit(entity, i)) {
649
- result.push(this.components[i].name);
650
- }
651
- }
652
- return result;
653
- }
654
- /**
655
- * Serialize entities with specific components to binary.
656
- * Uses PooledCodec internally for efficient encoding.
657
- *
658
- * @param components Components to include in the snapshot
659
- * @param entities Optional list of entities to serialize (defaults to all)
660
- * @returns Binary buffer with serialized data
661
- */
662
- serialize(components, entities) {
663
- const entityList = entities ?? Array.from(this.aliveEntitiesArray);
664
- // Build data structure for each component
665
- const componentArrays = [];
666
- for (const component of components) {
667
- const index = component.__worldIndex;
668
- if (index === undefined)
669
- continue;
670
- const store = this.componentStoresArray[index];
671
- if (!store)
672
- continue;
673
- const items = [];
674
- for (const entity of entityList) {
675
- if (this.has(entity, component)) {
676
- items.push({
677
- entity,
678
- ...store.getMutable(entity),
679
- });
680
- }
681
- }
682
- if (items.length > 0) {
683
- // Use the component's arrayCodec (PooledCodec.array) to encode
684
- const encoded = component.arrayCodec.encode(items);
685
- componentArrays.push(encoded);
686
- }
687
- }
688
- // Combine all buffers
689
- // TODO: Could optimize this with a proper multi-buffer format
690
- const totalSize = componentArrays.reduce((sum, buf) => sum + buf.length, 0);
691
- const result = new Uint8Array(totalSize);
692
- let offset = 0;
693
- for (const buf of componentArrays) {
694
- result.set(buf, offset);
695
- offset += buf.length;
696
- }
697
- return result;
698
- }
699
- /**
700
- * Deserialize binary data into entities.
701
- * Uses PooledCodec internally for efficient decoding.
702
- *
703
- * Note: This is a basic implementation. For production use,
704
- * you'd want a more sophisticated format with component IDs, etc.
705
- */
706
- deserialize(components, buffer) {
707
- // TODO: Implement proper deserialization with component IDs
708
- // For now, this is a placeholder
709
- throw new Error("Deserialization not yet implemented");
710
- }
711
- /**
712
- * Get direct access to a component field's TypedArray for maximum performance.
713
- * This bypasses the get/update API for ~3-4x faster access in hot paths.
714
- *
715
- * ⚠️ ADVANCED API: Use with caution!
716
- * - No bounds checking
717
- * - No type safety
718
- * - You must ensure entities have the component
719
- * - Direct array mutation bypasses any safety mechanisms
720
- *
721
- * @example
722
- * ```typescript
723
- * // High-performance system (bitECS-style)
724
- * const transformX = world.getFieldArray(Transform, 'x');
725
- * const transformY = world.getFieldArray(Transform, 'y');
726
- * const velocityVx = world.getFieldArray(Velocity, 'vx');
727
- * const velocityVy = world.getFieldArray(Velocity, 'vy');
728
- *
729
- * for (const entity of world.query(Transform, Velocity)) {
730
- * transformX[entity] += velocityVx[entity] * dt;
731
- * transformY[entity] += velocityVy[entity] * dt;
732
- * }
733
- * ```
734
- */
735
- getFieldArray(component, fieldName) {
736
- const index = this.getComponentIndex(component);
737
- return this.componentStoresArray[index].getFieldArray(fieldName);
738
- }
739
- /**
740
- * Create an EntityHandle wrapper for fluent API usage.
741
- *
742
- * EntityHandle provides a chainable interface for entity operations with zero runtime overhead.
743
- * Modern JIT compilers inline these simple method calls, making them identical to raw World API.
744
- *
745
- * @param entityId - Entity ID to wrap
746
- * @returns EntityHandle for fluent operations
747
- *
748
- * @example
749
- * ```typescript
750
- * // Fluent API with chaining
751
- * const player = world.entity(world.spawn())
752
- * .add(Transform, { x: 0, y: 0, rotation: 0 })
753
- * .add(Health, { current: 100, max: 100 })
754
- * .add(Velocity, { vx: 0, vy: 0 });
755
- *
756
- * // Use the handle
757
- * player.update(Transform, { x: 10 });
758
- * const health = player.get(Health);
759
- *
760
- * // Mix with raw API
761
- * world.add(player.id, Armor, { value: 50 });
762
- * ```
763
- */
764
- entity(entityId) {
765
- return new EntityHandle(this, entityId);
766
- }
767
- }