murow 0.0.60 → 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 (425) 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/loop → types/core/driver}/drivers/immediate.d.ts +1 -1
  156. package/dist/{core/loop → types/core/driver}/drivers/raf.d.ts +1 -1
  157. package/dist/{core/loop → types/core/driver}/drivers/timeout.d.ts +1 -1
  158. package/dist/{core/loop → types/core/driver}/index.d.ts +1 -1
  159. package/dist/{core → types/core}/events/event-system.d.ts +14 -33
  160. package/dist/{core → types/core}/fixed-ticker/fixed-ticker.d.ts +1 -1
  161. package/dist/types/core/free-list/free-list.d.ts +31 -0
  162. package/dist/types/core/free-list/index.d.ts +1 -0
  163. package/dist/{core → types/core}/index.d.ts +7 -1
  164. package/dist/types/core/input/index.d.ts +3 -0
  165. package/dist/types/core/input/manager.d.ts +56 -0
  166. package/dist/types/core/input/sources/browser.d.ts +9 -0
  167. package/dist/types/core/input/sources/index.d.ts +1 -0
  168. package/dist/types/core/input/types.d.ts +36 -0
  169. package/dist/{core → types/core}/navmesh/navmesh.d.ts +1 -21
  170. package/dist/types/core/ray/index.d.ts +2 -0
  171. package/dist/types/core/ray/ray-2d.d.ts +37 -0
  172. package/dist/types/core/ray/ray-3d.d.ts +42 -0
  173. package/dist/types/core/simple-rng/index.d.ts +1 -0
  174. package/dist/types/core/simple-rng/simple-rng.d.ts +36 -0
  175. package/dist/types/core/sparse-batcher/index.d.ts +1 -0
  176. package/dist/types/core/sparse-batcher/sparse-batcher.d.ts +55 -0
  177. package/dist/{ecs → types/ecs}/system-builder.d.ts +20 -9
  178. package/dist/{ecs → types/ecs}/world.d.ts +11 -0
  179. package/dist/types/game/index.d.ts +1 -0
  180. package/dist/types/game/loop/index.d.ts +1 -0
  181. package/dist/types/game/loop/loop.d.ts +175 -0
  182. package/dist/{index.d.ts → types/index.d.ts} +2 -0
  183. package/dist/{net → types/net}/index.d.ts +2 -2
  184. package/dist/{net → types/net}/server.d.ts +39 -19
  185. package/dist/{protocol → types/protocol}/intent/define-intent.d.ts +15 -0
  186. package/dist/{protocol → types/protocol}/intent/index.d.ts +1 -1
  187. package/dist/types/renderer/base-2d-renderer.d.ts +13 -0
  188. package/dist/types/renderer/base-3d-renderer.d.ts +10 -0
  189. package/dist/types/renderer/base-renderer.d.ts +21 -0
  190. package/dist/types/renderer/index.d.ts +4 -0
  191. package/dist/types/renderer/types.d.ts +79 -0
  192. package/dist/webgpu/cjs/index.js +6004 -0
  193. package/dist/webgpu/esm/index.js +5972 -0
  194. package/dist/webgpu/types/2d/animation.d.ts +97 -0
  195. package/dist/webgpu/types/2d/renderer.d.ts +55 -0
  196. package/dist/webgpu/types/2d/shader.d.ts +61 -0
  197. package/dist/webgpu/types/2d/sprite-accessor.d.ts +47 -0
  198. package/dist/webgpu/types/2d/sprite-accessor.test.d.ts +1 -0
  199. package/dist/webgpu/types/3d/gltf-skin-parser.d.ts +101 -0
  200. package/dist/webgpu/types/3d/morph-animation.d.ts +69 -0
  201. package/dist/webgpu/types/3d/morph-animation.test.d.ts +1 -0
  202. package/dist/webgpu/types/3d/renderer.d.ts +216 -0
  203. package/dist/webgpu/types/3d/shader.d.ts +136 -0
  204. package/dist/webgpu/types/3d/skeletal-animation-compute/index.d.ts +2 -0
  205. package/dist/webgpu/types/3d/skeletal-animation-compute/kernel.d.ts +8 -0
  206. package/dist/webgpu/types/3d/skeletal-animation-compute/packer.d.ts +32 -0
  207. package/dist/webgpu/types/3d/skeletal-animation.d.ts +90 -0
  208. package/dist/webgpu/types/camera/camera-2d.d.ts +53 -0
  209. package/dist/webgpu/types/camera/camera-2d.test.d.ts +1 -0
  210. package/dist/webgpu/types/camera/camera-3d.d.ts +81 -0
  211. package/dist/webgpu/types/camera/camera-3d.test.d.ts +1 -0
  212. package/dist/webgpu/types/camera/index.d.ts +2 -0
  213. package/dist/webgpu/types/compute/compute-builder.d.ts +123 -0
  214. package/dist/webgpu/types/compute/compute-builder.test.d.ts +1 -0
  215. package/dist/webgpu/types/core/constants.d.ts +59 -0
  216. package/dist/webgpu/types/core/constants.test.d.ts +1 -0
  217. package/dist/webgpu/types/core/index.d.ts +2 -0
  218. package/dist/webgpu/types/core/math.d.ts +37 -0
  219. package/dist/webgpu/types/core/types.d.ts +125 -0
  220. package/dist/webgpu/types/core/types.test.d.ts +1 -0
  221. package/dist/webgpu/types/geometry/built-in.d.ts +58 -0
  222. package/dist/webgpu/types/geometry/built-in.test.d.ts +1 -0
  223. package/dist/webgpu/types/geometry/geometry-builder.d.ts +281 -0
  224. package/dist/webgpu/types/geometry/geometry-builder.test.d.ts +1 -0
  225. package/dist/webgpu/types/geometry/index.d.ts +2 -0
  226. package/dist/webgpu/types/index.d.ts +32 -0
  227. package/dist/webgpu/types/particle/emitter.d.ts +36 -0
  228. package/dist/webgpu/types/shaders/index.d.ts +2 -0
  229. package/dist/webgpu/types/shaders/runtime-transpile.d.ts +18 -0
  230. package/dist/webgpu/types/shaders/sprite-2d.wgsl.d.ts +10 -0
  231. package/dist/webgpu/types/shaders/typegpu.d.ts +9 -0
  232. package/dist/webgpu/types/shaders/utils.d.ts +28 -0
  233. package/dist/webgpu/types/shaders/utils.test.d.ts +1 -0
  234. package/dist/webgpu/types/spritesheet/index.d.ts +1 -0
  235. package/dist/webgpu/types/spritesheet/spritesheet.d.ts +57 -0
  236. package/dist/webgpu/types/spritesheet/spritesheet.test.d.ts +1 -0
  237. package/package.json +96 -26
  238. package/dist/core/binary-codec/binary-codec.js +0 -354
  239. package/dist/core/binary-codec/index.js +0 -1
  240. package/dist/core/events/event-system.js +0 -88
  241. package/dist/core/events/index.js +0 -1
  242. package/dist/core/fixed-ticker/fixed-ticker.js +0 -101
  243. package/dist/core/fixed-ticker/index.js +0 -1
  244. package/dist/core/generate-id/generate-id.js +0 -25
  245. package/dist/core/generate-id/index.js +0 -1
  246. package/dist/core/index.js +0 -9
  247. package/dist/core/lerp/index.js +0 -1
  248. package/dist/core/lerp/lerp.js +0 -42
  249. package/dist/core/loop/drivers/immediate.js +0 -61
  250. package/dist/core/loop/drivers/index.js +0 -3
  251. package/dist/core/loop/drivers/raf.js +0 -62
  252. package/dist/core/loop/drivers/timeout.js +0 -71
  253. package/dist/core/loop/index.js +0 -2
  254. package/dist/core/loop/loop.js +0 -47
  255. package/dist/core/navmesh/index.js +0 -1
  256. package/dist/core/navmesh/navmesh-worker-pool.js +0 -180
  257. package/dist/core/navmesh/navmesh.js +0 -799
  258. package/dist/core/navmesh/navmesh.worker.js +0 -79
  259. package/dist/core/pooled-codec/index.js +0 -1
  260. package/dist/core/pooled-codec/pooled-codec.js +0 -410
  261. package/dist/core/prediction/index.js +0 -1
  262. package/dist/core/prediction/prediction.js +0 -99
  263. package/dist/core.esm.js +0 -1
  264. package/dist/core.js +0 -1
  265. package/dist/ecs/component-store.js +0 -175
  266. package/dist/ecs/component.js +0 -43
  267. package/dist/ecs/entity-handle.js +0 -515
  268. package/dist/ecs/example.js +0 -125
  269. package/dist/ecs/index.js +0 -4
  270. package/dist/ecs/system-builder.js +0 -180
  271. package/dist/ecs/system.d.ts +0 -63
  272. package/dist/ecs/system.js +0 -92
  273. package/dist/ecs/world-systems.js +0 -79
  274. package/dist/ecs/world.js +0 -684
  275. package/dist/index.js +0 -24
  276. package/dist/net/adapters/browser-websocket.js +0 -74
  277. package/dist/net/adapters/bun-websocket.js +0 -245
  278. package/dist/net/buffer-pool.js +0 -89
  279. package/dist/net/client.js +0 -586
  280. package/dist/net/index.js +0 -58
  281. package/dist/net/server.js +0 -938
  282. package/dist/net/types.js +0 -31
  283. package/dist/net/validators.js +0 -88
  284. package/dist/protocol/index.js +0 -92
  285. package/dist/protocol/intent/define-intent.js +0 -125
  286. package/dist/protocol/intent/index.js +0 -91
  287. package/dist/protocol/intent/intent-registry.js +0 -91
  288. package/dist/protocol/rpc/define-rpc.js +0 -84
  289. package/dist/protocol/rpc/index.js +0 -3
  290. package/dist/protocol/rpc/rpc-registry.js +0 -159
  291. package/dist/protocol/rpc/rpc.js +0 -12
  292. package/dist/protocol/snapshot/index.js +0 -43
  293. package/dist/protocol/snapshot/snapshot-codec.js +0 -67
  294. package/dist/protocol/snapshot/snapshot-registry.js +0 -168
  295. package/dist/protocol/snapshot/snapshot.js +0 -30
  296. package/src/core/binary-codec/README.md +0 -60
  297. package/src/core/binary-codec/binary-codec.test.ts +0 -300
  298. package/src/core/binary-codec/binary-codec.ts +0 -448
  299. package/src/core/binary-codec/index.ts +0 -1
  300. package/src/core/events/README.md +0 -47
  301. package/src/core/events/event-system.test.ts +0 -243
  302. package/src/core/events/event-system.ts +0 -140
  303. package/src/core/events/index.ts +0 -1
  304. package/src/core/fixed-ticker/README.md +0 -77
  305. package/src/core/fixed-ticker/fixed-ticker.test.ts +0 -151
  306. package/src/core/fixed-ticker/fixed-ticker.ts +0 -169
  307. package/src/core/fixed-ticker/index.ts +0 -1
  308. package/src/core/generate-id/README.md +0 -18
  309. package/src/core/generate-id/generate-id.test.ts +0 -79
  310. package/src/core/generate-id/generate-id.ts +0 -37
  311. package/src/core/generate-id/index.ts +0 -1
  312. package/src/core/index.ts +0 -9
  313. package/src/core/lerp/README.md +0 -79
  314. package/src/core/lerp/index.ts +0 -1
  315. package/src/core/lerp/lerp.test.ts +0 -90
  316. package/src/core/lerp/lerp.ts +0 -42
  317. package/src/core/loop/README.md +0 -97
  318. package/src/core/loop/drivers/immediate.ts +0 -66
  319. package/src/core/loop/drivers/index.ts +0 -3
  320. package/src/core/loop/drivers/raf.ts +0 -67
  321. package/src/core/loop/drivers/timeout.ts +0 -77
  322. package/src/core/loop/index.ts +0 -2
  323. package/src/core/loop/loop.test.ts +0 -414
  324. package/src/core/loop/loop.ts +0 -71
  325. package/src/core/navmesh/README.md +0 -164
  326. package/src/core/navmesh/index.ts +0 -1
  327. package/src/core/navmesh/navmesh-worker-pool.ts +0 -236
  328. package/src/core/navmesh/navmesh-workers.test.ts +0 -356
  329. package/src/core/navmesh/navmesh.test.ts +0 -344
  330. package/src/core/navmesh/navmesh.ts +0 -1047
  331. package/src/core/navmesh/navmesh.worker.ts +0 -147
  332. package/src/core/pooled-codec/README.md +0 -70
  333. package/src/core/pooled-codec/index.ts +0 -1
  334. package/src/core/pooled-codec/pooled-codec.test.ts +0 -862
  335. package/src/core/pooled-codec/pooled-codec.ts +0 -504
  336. package/src/core/prediction/README.md +0 -64
  337. package/src/core/prediction/index.ts +0 -1
  338. package/src/core/prediction/prediction.test.ts +0 -423
  339. package/src/core/prediction/prediction.ts +0 -112
  340. package/src/ecs/README.md +0 -427
  341. package/src/ecs/benchmark.test.ts +0 -1645
  342. package/src/ecs/component-store.ts +0 -198
  343. package/src/ecs/component.ts +0 -90
  344. package/src/ecs/entity-handle.test.ts +0 -393
  345. package/src/ecs/entity-handle.ts +0 -563
  346. package/src/ecs/example.ts +0 -152
  347. package/src/ecs/index.ts +0 -4
  348. package/src/ecs/system-builder.ts +0 -309
  349. package/src/ecs/system.ts +0 -111
  350. package/src/ecs/world-systems.ts +0 -83
  351. package/src/ecs/world.test.ts +0 -310
  352. package/src/ecs/world.ts +0 -828
  353. package/src/index.ts +0 -28
  354. package/src/net/README.md +0 -474
  355. package/src/net/adapters/browser-websocket.ts +0 -86
  356. package/src/net/adapters/bun-websocket.ts +0 -292
  357. package/src/net/buffer-pool.ts +0 -106
  358. package/src/net/client.test.ts +0 -807
  359. package/src/net/client.ts +0 -695
  360. package/src/net/index.ts +0 -60
  361. package/src/net/server.test.ts +0 -799
  362. package/src/net/server.ts +0 -1116
  363. package/src/net/types.ts +0 -228
  364. package/src/net/validators.ts +0 -104
  365. package/src/protocol/README.md +0 -469
  366. package/src/protocol/index.ts +0 -93
  367. package/src/protocol/intent/define-intent.test.ts +0 -397
  368. package/src/protocol/intent/define-intent.ts +0 -182
  369. package/src/protocol/intent/index.ts +0 -94
  370. package/src/protocol/intent/intent-registry.test.ts +0 -198
  371. package/src/protocol/intent/intent-registry.ts +0 -112
  372. package/src/protocol/intent/intent.ts +0 -12
  373. package/src/protocol/rpc/define-rpc.test.ts +0 -141
  374. package/src/protocol/rpc/define-rpc.ts +0 -113
  375. package/src/protocol/rpc/index.ts +0 -3
  376. package/src/protocol/rpc/rpc-registry.test.ts +0 -168
  377. package/src/protocol/rpc/rpc-registry.ts +0 -176
  378. package/src/protocol/rpc/rpc.ts +0 -37
  379. package/src/protocol/snapshot/index.ts +0 -45
  380. package/src/protocol/snapshot/snapshot-codec.test.ts +0 -138
  381. package/src/protocol/snapshot/snapshot-codec.ts +0 -87
  382. package/src/protocol/snapshot/snapshot-registry.test.ts +0 -310
  383. package/src/protocol/snapshot/snapshot-registry.ts +0 -201
  384. package/src/protocol/snapshot/snapshot.test.ts +0 -76
  385. package/src/protocol/snapshot/snapshot.ts +0 -41
  386. /package/dist/{core → types/core}/binary-codec/index.d.ts +0 -0
  387. /package/dist/{core/loop/loop.d.ts → types/core/driver/driver.d.ts} +0 -0
  388. /package/dist/{core/loop → types/core/driver}/drivers/index.d.ts +0 -0
  389. /package/dist/{core → types/core}/events/index.d.ts +0 -0
  390. /package/dist/{core → types/core}/fixed-ticker/index.d.ts +0 -0
  391. /package/dist/{core → types/core}/generate-id/generate-id.d.ts +0 -0
  392. /package/dist/{core → types/core}/generate-id/index.d.ts +0 -0
  393. /package/dist/{core → types/core}/lerp/index.d.ts +0 -0
  394. /package/dist/{core → types/core}/lerp/lerp.d.ts +0 -0
  395. /package/dist/{core → types/core}/navmesh/index.d.ts +0 -0
  396. /package/dist/{core → types/core}/navmesh/navmesh-worker-pool.d.ts +0 -0
  397. /package/dist/{core → types/core}/navmesh/navmesh.worker.d.ts +0 -0
  398. /package/dist/{core → types/core}/pooled-codec/index.d.ts +0 -0
  399. /package/dist/{core → types/core}/pooled-codec/pooled-codec.d.ts +0 -0
  400. /package/dist/{core → types/core}/prediction/index.d.ts +0 -0
  401. /package/dist/{core → types/core}/prediction/prediction.d.ts +0 -0
  402. /package/dist/{ecs → types/ecs}/component-store.d.ts +0 -0
  403. /package/dist/{ecs → types/ecs}/component.d.ts +0 -0
  404. /package/dist/{ecs → types/ecs}/entity-handle.d.ts +0 -0
  405. /package/dist/{ecs → types/ecs}/example.d.ts +0 -0
  406. /package/dist/{ecs → types/ecs}/index.d.ts +0 -0
  407. /package/dist/{ecs → types/ecs}/world-systems.d.ts +0 -0
  408. /package/dist/{net → types/net}/adapters/browser-websocket.d.ts +0 -0
  409. /package/dist/{net → types/net}/adapters/bun-websocket.d.ts +0 -0
  410. /package/dist/{net → types/net}/buffer-pool.d.ts +0 -0
  411. /package/dist/{net → types/net}/client.d.ts +0 -0
  412. /package/dist/{net → types/net}/types.d.ts +0 -0
  413. /package/dist/{net → types/net}/validators.d.ts +0 -0
  414. /package/dist/{protocol → types/protocol}/index.d.ts +0 -0
  415. /package/dist/{protocol → types/protocol}/intent/intent-registry.d.ts +0 -0
  416. /package/dist/{protocol → types/protocol}/intent/intent.d.ts +0 -0
  417. /package/dist/{protocol → types/protocol}/rpc/define-rpc.d.ts +0 -0
  418. /package/dist/{protocol → types/protocol}/rpc/index.d.ts +0 -0
  419. /package/dist/{protocol → types/protocol}/rpc/rpc-registry.d.ts +0 -0
  420. /package/dist/{protocol → types/protocol}/rpc/rpc.d.ts +0 -0
  421. /package/dist/{protocol → types/protocol}/snapshot/index.d.ts +0 -0
  422. /package/dist/{protocol → types/protocol}/snapshot/snapshot-codec.d.ts +0 -0
  423. /package/dist/{protocol → types/protocol}/snapshot/snapshot-registry.d.ts +0 -0
  424. /package/dist/{protocol → types/protocol}/snapshot/snapshot.d.ts +0 -0
  425. /package/dist/{protocol/intent/intent.js → webgpu/types/2d/animation.test.d.ts} +0 -0
@@ -1,1047 +0,0 @@
1
- type ObstacleId = number;
2
-
3
- export type Obstacle =
4
- | CircleObstacle
5
- | RectObstacle
6
- | PolygonObstacle;
7
-
8
- /**
9
- * NavMesh configuration options
10
- */
11
- export interface NavMeshOptions<TWorkers extends boolean | 'auto' = false> {
12
- /**
13
- * Enable Web Workers for pathfinding
14
- *
15
- * - `false` (default): Synchronous pathfinding on main thread
16
- * - `true`: Always use worker pool (4 workers)
17
- * - `'auto'`: Automatically use workers when beneficial (>= 20 pending paths)
18
- *
19
- * @default false
20
- *
21
- * @remarks
22
- * Workers provide 3-4.5x speedup for parallel pathfinding (20+ concurrent requests).
23
- * For single/sequential pathfinding, sync is faster due to message passing overhead (~0.5ms).
24
- *
25
- * Use 'auto' for games where pathfinding load varies (e.g., RTS with unit groups).
26
- */
27
- workers?: TWorkers;
28
-
29
- /**
30
- * Number of workers to spawn (only used when workers = true)
31
- * @default 4
32
- */
33
- workerPoolSize?: number;
34
-
35
- /**
36
- * Path to worker script (required if workers = true and running in browser)
37
- * For Node.js/Bun, this is handled automatically
38
- * @example './navmesh.worker.js'
39
- */
40
- workerPath?: string;
41
- }
42
-
43
- /**
44
- * Helper type to determine return type based on worker configuration
45
- */
46
- type PathResult<TWorkers extends boolean | 'auto' | undefined> =
47
- TWorkers extends false | undefined
48
- ? Vec2[] // Sync only
49
- : TWorkers extends true
50
- ? Promise<Vec2[]> // Always async
51
- : Vec2[] | Promise<Vec2[]>; // Auto: can be either
52
-
53
- export type ObstacleInput =
54
- | Omit<CircleObstacle, 'id'>
55
- | Omit<RectObstacle, 'id'>
56
- | Omit<PolygonObstacle, 'id'>;
57
-
58
- interface Vec2 {
59
- x: number;
60
- y: number;
61
- }
62
-
63
- interface BaseObstacle {
64
- id: ObstacleId;
65
- type: 'circle' | 'rect' | 'polygon';
66
- solid?: boolean; // default true
67
- }
68
-
69
- export interface CircleObstacle extends BaseObstacle {
70
- type: 'circle';
71
- pos: Vec2;
72
- radius: number;
73
- }
74
-
75
- export interface RectObstacle extends BaseObstacle {
76
- type: 'rect';
77
- pos: Vec2; // bottom-left corner
78
- size: Vec2;
79
- rotation?: number; // radians, around center
80
- }
81
-
82
- /**
83
- * Polygon obstacle.
84
- * IMPORTANT: `points` must be defined relative to local origin (0,0).
85
- * The polygon will be rotated around (0,0) then translated to `pos`.
86
- * Do NOT define points in world space.
87
- */
88
- export interface PolygonObstacle extends BaseObstacle {
89
- type: 'polygon';
90
- points: Vec2[]; // MUST be relative to (0,0)
91
- pos: Vec2; // world position
92
- rotation?: number; // radians, around local origin (0,0)
93
- }
94
-
95
- /* ---------------------------------- */
96
- /* Utils */
97
- /* ---------------------------------- */
98
-
99
- const dirs = [
100
- { x: 1, y: 0 },
101
- { x: -1, y: 0 },
102
- { x: 0, y: 1 },
103
- { x: 0, y: -1 },
104
- ];
105
-
106
- /**
107
- * Converts world coordinates to grid cell coordinates (floor).
108
- */
109
- const toCell = (v: Vec2): Vec2 => ({
110
- x: Math.floor(v.x),
111
- y: Math.floor(v.y),
112
- });
113
-
114
- /**
115
- * Converts grid cell coordinates to world coordinates (cell center).
116
- */
117
- const fromCell = (v: Vec2): Vec2 => ({
118
- x: v.x + 0.5,
119
- y: v.y + 0.5
120
- });
121
-
122
- /**
123
- * Generates unique sequential IDs for obstacles.
124
- */
125
- const genId = (() => {
126
- let i = 1;
127
- return () => i++;
128
- })();
129
-
130
- /**
131
- * Encodes grid coordinates as a single integer for use as Map/Set keys.
132
- * Uses 32-bit safe packing: lower 16 bits = x, upper 16 bits = y.
133
- * Supports coordinates in range [-32768, 32767].
134
- */
135
- const encodeCell = (x: number, y: number): number =>
136
- (x & 0xffff) | ((y & 0xffff) << 16);
137
-
138
- /**
139
- * Decodes an encoded cell back to {x, y}.
140
- * Properly handles sign extension for negative coordinates.
141
- */
142
- const decodeCell = (n: number): Vec2 => ({
143
- x: (n << 16) >> 16,
144
- y: n >> 16,
145
- });
146
-
147
- /* ---------------------------------- */
148
- /* Binary Heap (Priority Queue) */
149
- /* ---------------------------------- */
150
-
151
- /**
152
- * Min-heap priority queue for A*.
153
- * Supports O(log n) insert and extract-min operations.
154
- */
155
- class BinaryHeap<T> {
156
- private heap: T[] = [];
157
-
158
- constructor(private scoreFn: (item: T) => number) {}
159
-
160
- push(item: T) {
161
- this.heap.push(item);
162
- this.bubbleUp(this.heap.length - 1);
163
- }
164
-
165
- pop(): T | undefined {
166
- const result = this.heap[0];
167
- const end = this.heap.pop();
168
-
169
- if (this.heap.length > 0 && end !== undefined) {
170
- this.heap[0] = end;
171
- this.sinkDown(0);
172
- }
173
-
174
- return result;
175
- }
176
-
177
- get size(): number {
178
- return this.heap.length;
179
- }
180
-
181
- private bubbleUp(n: number) {
182
- const element = this.heap[n];
183
- const score = this.scoreFn(element);
184
-
185
- while (n > 0) {
186
- const parentN = ((n + 1) >> 1) - 1;
187
- const parent = this.heap[parentN];
188
-
189
- if (score >= this.scoreFn(parent)) break;
190
-
191
- this.heap[parentN] = element;
192
- this.heap[n] = parent;
193
- n = parentN;
194
- }
195
- }
196
-
197
- private sinkDown(n: number) {
198
- const length = this.heap.length;
199
- const element = this.heap[n];
200
- const elemScore = this.scoreFn(element);
201
-
202
- while (true) {
203
- const child2N = (n + 1) << 1;
204
- const child1N = child2N - 1;
205
- let swap: number | null = null;
206
- let child1Score: number;
207
-
208
- if (child1N < length) {
209
- const child1 = this.heap[child1N];
210
- child1Score = this.scoreFn(child1);
211
- if (child1Score < elemScore) {
212
- swap = child1N;
213
- }
214
- }
215
-
216
- if (child2N < length) {
217
- const child2 = this.heap[child2N];
218
- const child2Score = this.scoreFn(child2);
219
- if (child2Score < (swap === null ? elemScore : child1Score!)) {
220
- swap = child2N;
221
- }
222
- }
223
-
224
- if (swap === null) break;
225
-
226
- this.heap[n] = this.heap[swap];
227
- this.heap[swap] = element;
228
- n = swap;
229
- }
230
- }
231
- }
232
-
233
- /* ---------------------------------- */
234
- /* Spatial Hash */
235
- /* ---------------------------------- */
236
-
237
- /**
238
- * Spatial hash for fast obstacle queries.
239
- * Divides space into fixed-size cells and indexes obstacles by cell.
240
- * Provides O(1) average case lookup instead of O(n) linear scan.
241
- *
242
- * Cell size = 1 matches grid pathfinding unit cells.
243
- */
244
- class SpatialHash {
245
- private cellSize: number;
246
- private grid = new Map<number, Set<ObstacleId>>();
247
- private obstacleCells = new Map<ObstacleId, Set<number>>();
248
-
249
- constructor(cellSize = 1) {
250
- this.cellSize = cellSize;
251
- }
252
-
253
- /**
254
- * Returns hash key for a world position.
255
- */
256
- private hash(x: number, y: number): number {
257
- const cx = Math.floor(x / this.cellSize);
258
- const cy = Math.floor(y / this.cellSize);
259
- return encodeCell(cx, cy);
260
- }
261
-
262
- /**
263
- * Adds an obstacle to the spatial hash.
264
- */
265
- add(id: ObstacleId, obstacle: Obstacle) {
266
- const cells = this.getCellsForObstacle(obstacle);
267
-
268
- for (const cell of cells) {
269
- if (!this.grid.has(cell)) {
270
- this.grid.set(cell, new Set());
271
- }
272
- this.grid.get(cell)!.add(id);
273
- }
274
-
275
- this.obstacleCells.set(id, cells);
276
- }
277
-
278
- /**
279
- * Removes an obstacle from the spatial hash.
280
- */
281
- remove(id: ObstacleId) {
282
- const cells = this.obstacleCells.get(id);
283
- if (!cells) return;
284
-
285
- for (const cell of cells) {
286
- const bucket = this.grid.get(cell);
287
- if (bucket) {
288
- bucket.delete(id);
289
- if (bucket.size === 0) {
290
- this.grid.delete(cell);
291
- }
292
- }
293
- }
294
-
295
- this.obstacleCells.delete(id);
296
- }
297
-
298
- /**
299
- * Returns obstacle IDs that might contain the given point.
300
- */
301
- query(pos: Vec2): Set<ObstacleId> {
302
- const cell = this.hash(pos.x, pos.y);
303
- return this.grid.get(cell) || new Set();
304
- }
305
-
306
- /**
307
- * Clears the entire spatial hash.
308
- */
309
- clear() {
310
- this.grid.clear();
311
- this.obstacleCells.clear();
312
- }
313
-
314
- /**
315
- * Determines which cells an obstacle overlaps.
316
- */
317
- private getCellsForObstacle(o: Obstacle): Set<number> {
318
- const cells = new Set<number>();
319
-
320
- if (o.type === 'circle') {
321
- const r = o.radius;
322
- const minX = Math.floor((o.pos.x - r) / this.cellSize);
323
- const maxX = Math.floor((o.pos.x + r) / this.cellSize);
324
- const minY = Math.floor((o.pos.y - r) / this.cellSize);
325
- const maxY = Math.floor((o.pos.y + r) / this.cellSize);
326
-
327
- for (let x = minX; x <= maxX; x++) {
328
- for (let y = minY; y <= maxY; y++) {
329
- cells.add(encodeCell(x, y));
330
- }
331
- }
332
- } else if (o.type === 'rect') {
333
- const cx = o.pos.x + o.size.x / 2;
334
- const cy = o.pos.y + o.size.y / 2;
335
- const hw = o.size.x / 2;
336
- const hh = o.size.y / 2;
337
- const diagonal = Math.sqrt(hw * hw + hh * hh);
338
-
339
- const minX = Math.floor((cx - diagonal) / this.cellSize);
340
- const maxX = Math.floor((cx + diagonal) / this.cellSize);
341
- const minY = Math.floor((cy - diagonal) / this.cellSize);
342
- const maxY = Math.floor((cy + diagonal) / this.cellSize);
343
-
344
- for (let x = minX; x <= maxX; x++) {
345
- for (let y = minY; y <= maxY; y++) {
346
- cells.add(encodeCell(x, y));
347
- }
348
- }
349
- } else if (o.type === 'polygon') {
350
- const bounds = getPolygonBounds(o);
351
- const minX = Math.floor(bounds.minX / this.cellSize);
352
- const maxX = Math.floor(bounds.maxX / this.cellSize);
353
- const minY = Math.floor(bounds.minY / this.cellSize);
354
- const maxY = Math.floor(bounds.maxY / this.cellSize);
355
-
356
- for (let x = minX; x <= maxX; x++) {
357
- for (let y = minY; y <= maxY; y++) {
358
- cells.add(encodeCell(x, y));
359
- }
360
- }
361
- }
362
-
363
- return cells;
364
- }
365
- }
366
-
367
- /* ---------------------------------- */
368
- /* Geometry helpers */
369
- /* ---------------------------------- */
370
-
371
- /**
372
- * Tests if a point is inside a circle obstacle.
373
- */
374
- function pointInCircle(p: Vec2, c: CircleObstacle): boolean {
375
- const dx = p.x - c.pos.x;
376
- const dy = p.y - c.pos.y;
377
- return dx * dx + dy * dy <= c.radius * c.radius;
378
- }
379
-
380
- /**
381
- * Tests if a point is inside a rectangle obstacle.
382
- * Handles rotation around the rectangle's center.
383
- */
384
- function pointInRect(p: Vec2, r: RectObstacle): boolean {
385
- const cx = r.pos.x + r.size.x / 2;
386
- const cy = r.pos.y + r.size.y / 2;
387
-
388
- if (r.rotation) {
389
- const cos = Math.cos(-r.rotation);
390
- const sin = Math.sin(-r.rotation);
391
- const dx = p.x - cx;
392
- const dy = p.y - cy;
393
- const localX = dx * cos - dy * sin;
394
- const localY = dx * sin + dy * cos;
395
-
396
- return Math.abs(localX) <= r.size.x / 2 &&
397
- Math.abs(localY) <= r.size.y / 2;
398
- }
399
-
400
- return (
401
- p.x >= r.pos.x &&
402
- p.y >= r.pos.y &&
403
- p.x <= r.pos.x + r.size.x &&
404
- p.y <= r.pos.y + r.size.y
405
- );
406
- }
407
-
408
- /**
409
- * Tests if a point is inside a polygon obstacle using ray casting.
410
- * REQUIRES: polygon.points are defined relative to local origin (0,0).
411
- * Uses numerically stable intersection test.
412
- */
413
- function pointInPolygon(p: Vec2, poly: PolygonObstacle): boolean {
414
- let inside = false;
415
- const pts = poly.points;
416
- const cos = poly.rotation ? Math.cos(poly.rotation) : 1;
417
- const sin = poly.rotation ? Math.sin(poly.rotation) : 0;
418
-
419
- for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) {
420
- let xi = pts[i].x;
421
- let yi = pts[i].y;
422
- let xj = pts[j].x;
423
- let yj = pts[j].y;
424
-
425
- if (poly.rotation) {
426
- const tempXi = xi * cos - yi * sin;
427
- const tempYi = xi * sin + yi * cos;
428
- const tempXj = xj * cos - yj * sin;
429
- const tempYj = xj * sin + yj * cos;
430
- xi = tempXi;
431
- yi = tempYi;
432
- xj = tempXj;
433
- yj = tempYj;
434
- }
435
-
436
- xi += poly.pos.x;
437
- yi += poly.pos.y;
438
- xj += poly.pos.x;
439
- yj += poly.pos.y;
440
-
441
- // Stable ray casting test
442
- const intersect =
443
- (yi > p.y) !== (yj > p.y) &&
444
- p.x < ((xj - xi) * (p.y - yi)) / (yj - yi) + xi;
445
-
446
- if (intersect) inside = !inside;
447
- }
448
-
449
- return inside;
450
- }
451
-
452
- /**
453
- * Computes axis-aligned bounding box for a transformed polygon.
454
- */
455
- function getPolygonBounds(poly: PolygonObstacle): {
456
- minX: number;
457
- minY: number;
458
- maxX: number;
459
- maxY: number;
460
- } {
461
- let minX = Infinity, minY = Infinity;
462
- let maxX = -Infinity, maxY = -Infinity;
463
-
464
- const cos = poly.rotation ? Math.cos(poly.rotation) : 1;
465
- const sin = poly.rotation ? Math.sin(poly.rotation) : 0;
466
-
467
- for (const p of poly.points) {
468
- let x = p.x;
469
- let y = p.y;
470
-
471
- if (poly.rotation) {
472
- const tx = x * cos - y * sin;
473
- const ty = x * sin + y * cos;
474
- x = tx;
475
- y = ty;
476
- }
477
-
478
- x += poly.pos.x;
479
- y += poly.pos.y;
480
-
481
- minX = Math.min(minX, x);
482
- minY = Math.min(minY, y);
483
- maxX = Math.max(maxX, x);
484
- maxY = Math.max(maxY, y);
485
- }
486
-
487
- return { minX, minY, maxX, maxY };
488
- }
489
-
490
- /* ---------------------------------- */
491
- /* Obstacles */
492
- /* ---------------------------------- */
493
-
494
- /**
495
- * Manages obstacles with spatial hashing for fast queries.
496
- * Version tracking prevents unnecessary rebuilds.
497
- */
498
- class Obstacles {
499
- private items = new Map<ObstacleId, Obstacle>();
500
- private spatial = new SpatialHash(1); // Match grid cell size
501
- private _cachedItems: Obstacle[] = [];
502
- dirty = true;
503
- version = 0;
504
-
505
- add(obstacle: ObstacleInput): ObstacleId {
506
- const id = genId();
507
- const newObstacle = { ...obstacle, id } as Obstacle;
508
- this.items.set(id, newObstacle);
509
- this.spatial.add(id, newObstacle);
510
- this.dirty = true;
511
- this.version++;
512
- return id;
513
- }
514
-
515
- move(id: ObstacleId, pos: Vec2) {
516
- const o = this.items.get(id);
517
- if (!o) return;
518
-
519
- // Remove from old position in spatial hash
520
- this.spatial.remove(id);
521
-
522
- // Create updated obstacle
523
- const updated = {
524
- ...o,
525
- pos: { ...pos },
526
- };
527
-
528
- this.items.set(id, updated as Obstacle);
529
- this.spatial.add(id, updated as Obstacle);
530
- this.dirty = true;
531
- this.version++;
532
- }
533
-
534
- remove(id: ObstacleId) {
535
- this.spatial.remove(id);
536
- this.items.delete(id);
537
- this.dirty = true;
538
- this.version++;
539
- }
540
-
541
- /**
542
- * Fast spatial query using hash grid.
543
- * O(1) average case instead of O(n) linear scan.
544
- */
545
- at(pos: Vec2): Obstacle | undefined {
546
- const candidates = this.spatial.query(pos);
547
-
548
- for (const id of candidates) {
549
- const o = this.items.get(id);
550
- if (!o || o.solid === false) continue;
551
-
552
- if (o.type === 'circle' && pointInCircle(pos, o)) return o;
553
- if (o.type === 'rect' && pointInRect(pos, o)) return o;
554
- if (o.type === 'polygon' && pointInPolygon(pos, o)) return o;
555
- }
556
- }
557
-
558
- get values(): Obstacle[] {
559
- if (!this.dirty) return this._cachedItems;
560
- this._cachedItems = [...this.items.values()];
561
- this.dirty = false;
562
- return this._cachedItems;
563
- }
564
- }
565
-
566
- /* ---------------------------------- */
567
- /* Grid Nav */
568
- /* ---------------------------------- */
569
-
570
- /**
571
- * Grid navigation with simple full rebuild.
572
- * Fast enough for most games (< 1000 obstacles).
573
- *
574
- * Performance: O(n * area) where n = obstacle count.
575
- * Typical rebuild time: < 1ms for 100 obstacles on 100x100 grid.
576
- */
577
- class GridNav {
578
- private blocked = new Set<number>();
579
-
580
- constructor(private obstacles: Obstacles) {}
581
-
582
- /**
583
- * Rebuilds the entire blocked cell set.
584
- * Simple and correct - no incremental complexity.
585
- */
586
- rebuild() {
587
- this.blocked.clear();
588
-
589
- for (const o of this.obstacles.values) {
590
- if (o.solid === false) continue;
591
-
592
- if (o.type === 'circle') {
593
- const r = Math.ceil(o.radius);
594
- const cx = Math.floor(o.pos.x);
595
- const cy = Math.floor(o.pos.y);
596
-
597
- for (let dx = -r; dx <= r; dx++) {
598
- for (let dy = -r; dy <= r; dy++) {
599
- const cellX = cx + dx;
600
- const cellY = cy + dy;
601
- const cellCenter = { x: cellX + 0.5, y: cellY + 0.5 };
602
- if (pointInCircle(cellCenter, o)) {
603
- this.blocked.add(encodeCell(cellX, cellY));
604
- }
605
- }
606
- }
607
- } else if (o.type === 'rect') {
608
- const cx = o.pos.x + o.size.x / 2;
609
- const cy = o.pos.y + o.size.y / 2;
610
- const hw = o.size.x / 2;
611
- const hh = o.size.y / 2;
612
- const diagonal = Math.sqrt(hw * hw + hh * hh);
613
-
614
- const minX = Math.floor(cx - diagonal);
615
- const maxX = Math.ceil(cx + diagonal);
616
- const minY = Math.floor(cy - diagonal);
617
- const maxY = Math.ceil(cy + diagonal);
618
-
619
- for (let x = minX; x <= maxX; x++) {
620
- for (let y = minY; y <= maxY; y++) {
621
- const cellCenter = { x: x + 0.5, y: y + 0.5 };
622
- if (pointInRect(cellCenter, o)) {
623
- this.blocked.add(encodeCell(x, y));
624
- }
625
- }
626
- }
627
- } else if (o.type === 'polygon') {
628
- const bounds = getPolygonBounds(o);
629
- const minX = Math.floor(bounds.minX);
630
- const maxX = Math.ceil(bounds.maxX);
631
- const minY = Math.floor(bounds.minY);
632
- const maxY = Math.ceil(bounds.maxY);
633
-
634
- for (let x = minX; x <= maxX; x++) {
635
- for (let y = minY; y <= maxY; y++) {
636
- const cellCenter = { x: x + 0.5, y: y + 0.5 };
637
- if (pointInPolygon(cellCenter, o)) {
638
- this.blocked.add(encodeCell(x, y));
639
- }
640
- }
641
- }
642
- }
643
- }
644
- }
645
-
646
- findPath(from: Vec2, to: Vec2): Vec2[] {
647
- return aStar(
648
- toCell(from),
649
- toCell(to),
650
- (x, y) => !this.blocked.has(encodeCell(x, y))
651
- ).map(fromCell);
652
- }
653
- }
654
-
655
- /* ---------------------------------- */
656
- /* Graph Nav */
657
- /* ---------------------------------- */
658
-
659
- /**
660
- * Line-of-sight navigation with grid fallback.
661
- * Not a true navmesh - use GridNav for production.
662
- */
663
- class GraphNav {
664
- constructor(private obstacles: Obstacles) {}
665
-
666
- rebuild() {}
667
-
668
- findPath(from: Vec2, to: Vec2): Vec2[] {
669
- // Uniform sampling along path for LOS check
670
- const steps = Math.ceil(
671
- Math.hypot(to.x - from.x, to.y - from.y) * 2
672
- );
673
-
674
- let blocked = false;
675
-
676
- for (let i = 1; i <= steps; i++) {
677
- const t = i / steps;
678
- const p = {
679
- x: from.x + (to.x - from.x) * t,
680
- y: from.y + (to.y - from.y) * t,
681
- };
682
-
683
- if (this.obstacles.at(p)) {
684
- blocked = true;
685
- break;
686
- }
687
- }
688
-
689
- if (!blocked) {
690
- return [from, to];
691
- }
692
-
693
- // Fallback to grid A*
694
- const cellPath = aStar(
695
- toCell(from),
696
- toCell(to),
697
- (x, y) => {
698
- const p = { x: x + 0.5, y: y + 0.5 };
699
- return !this.obstacles.at(p);
700
- }
701
- );
702
-
703
- return cellPath.map(fromCell);
704
- }
705
- }
706
-
707
- /* ---------------------------------- */
708
- /* NavMesh */
709
- /* ---------------------------------- */
710
-
711
- type NavType = 'grid' | 'graph';
712
-
713
- /**
714
- * Navigation mesh with spatial hashing and smart rebuild.
715
- *
716
- * Features:
717
- * - Spatial hash: O(1) obstacle queries
718
- * - Version tracking: zero unnecessary rebuilds
719
- * - Binary heap A*: handles 10k+ node searches
720
- * - Simple full rebuild: correct and fast enough
721
- * - Optional Web Workers: 3-4.5x speedup for parallel pathfinding
722
- *
723
- * Performance characteristics:
724
- * - Obstacle query: O(1) average via spatial hash
725
- * - Grid rebuild: O(n * area), < 1ms for typical games
726
- * - Pathfinding: O(b^d * log n) with binary heap
727
- * - Worker overhead: ~0.5ms per request (use for 20+ concurrent paths)
728
- *
729
- * Production ready for:
730
- * - Grid-based games
731
- * - RTS with < 1000 dynamic obstacles
732
- * - Turn-based games
733
- * - Moderate map sizes (< 1M cells)
734
- *
735
- * @example
736
- * ```ts
737
- * // Simple usage (synchronous) - typed as Vec2[]
738
- * const navmesh = new NavMesh('grid');
739
- * const path = navmesh.findPath({ from: {x:0, y:0}, to: {x:10, y:10} });
740
- *
741
- * // With workers (automatic) - typed as Vec2[] | Promise<Vec2[]>
742
- * const navmesh = new NavMesh('grid', { workers: 'auto' });
743
- * const path = await navmesh.findPath({ from: {x:0, y:0}, to: {x:10, y:10} });
744
- *
745
- * // With workers (always) - typed as Promise<Vec2[]>
746
- * const navmesh = new NavMesh('grid', { workers: true });
747
- * const path = await navmesh.findPath({ from: {x:0, y:0}, to: {x:10, y:10} });
748
- * ```
749
- */
750
- export class NavMesh<TWorkers extends boolean | 'auto' = false> {
751
- private grid?: GridNav;
752
- private graph?: GraphNav;
753
- private lastVersion = -1;
754
- obstacles: Obstacles;
755
-
756
- // Worker support
757
- private options: Required<NavMeshOptions<TWorkers>>;
758
- private workerPool?: any; // Lazy-loaded NavMeshWorkerPool
759
- private pendingPaths = 0;
760
- private readonly AUTO_WORKER_THRESHOLD = 20; // Use workers when >= 20 pending paths
761
-
762
- constructor(
763
- private type: NavType,
764
- options?: NavMeshOptions<TWorkers>
765
- ) {
766
- this.obstacles = new Obstacles();
767
-
768
- // Set defaults - cast to any to avoid complex type gymnastics
769
- this.options = {
770
- workers: (options?.workers ?? false) as any,
771
- workerPoolSize: options?.workerPoolSize ?? 4,
772
- workerPath: options?.workerPath ?? './navmesh.worker.js',
773
- };
774
-
775
- // Initialize sync navigation
776
- if (type === 'grid') this.grid = new GridNav(this.obstacles);
777
- if (type === 'graph') this.graph = new GraphNav(this.obstacles);
778
-
779
- // Initialize worker pool if workers = true
780
- if (this.options.workers === true) {
781
- this.initWorkerPool();
782
- }
783
- }
784
-
785
- /**
786
- * Lazy initialize worker pool
787
- */
788
- private async initWorkerPool() {
789
- if (this.workerPool) return;
790
-
791
- try {
792
- // Dynamic import to avoid bundling worker pool if not needed
793
- const { NavMeshWorkerPool } = await import('./navmesh-worker-pool');
794
-
795
- this.workerPool = new NavMeshWorkerPool(
796
- this.options.workerPoolSize,
797
- this.options.workerPath,
798
- this.type,
799
- this.obstacles.values
800
- );
801
-
802
- await this.workerPool.init();
803
- } catch (error) {
804
- console.warn('Failed to initialize worker pool, falling back to sync:', error);
805
- this.options.workers = false as any; // Disable workers on failure
806
- }
807
- }
808
-
809
- /**
810
- * Check if we should use workers for this request
811
- */
812
- private shouldUseWorkers(): boolean {
813
- if (this.options.workers === false) return false;
814
- if (this.options.workers === true) return true;
815
-
816
- // Auto mode: use workers if we have many pending paths
817
- return this.pendingPaths >= this.AUTO_WORKER_THRESHOLD;
818
- }
819
-
820
- /**
821
- * Adds an obstacle and returns its unique ID.
822
- * For polygons: ensure points are defined relative to (0,0).
823
- */
824
- addObstacle(obstacle: ObstacleInput): ObstacleId {
825
- return this.obstacles.add(obstacle);
826
- }
827
-
828
- /**
829
- * Moves an existing obstacle to a new position.
830
- */
831
- moveObstacle(id: ObstacleId, pos: Vec2) {
832
- this.obstacles.move(id, pos);
833
- }
834
-
835
- /**
836
- * Removes an obstacle by ID.
837
- */
838
- removeObstacle(id: ObstacleId) {
839
- this.obstacles.remove(id);
840
- }
841
-
842
- /**
843
- * Returns all current obstacles.
844
- */
845
- getObstacles(): Obstacle[] {
846
- return this.obstacles.values;
847
- }
848
-
849
- /**
850
- * Finds a path from start to goal.
851
- * Automatically rebuilds navigation data if obstacles changed.
852
- * Returns empty array if no path exists.
853
- *
854
- * @remarks
855
- * - If workers are disabled (false): Returns Vec2[] synchronously
856
- * - If workers are enabled (true): Returns Promise<Vec2[]>
857
- * - If workers are 'auto': Returns Vec2[] | Promise<Vec2[]> based on load
858
- *
859
- * @example
860
- * ```ts
861
- * // Synchronous (no workers) - typed as Vec2[]
862
- * const navmesh = new NavMesh('grid');
863
- * const path = navmesh.findPath({ from, to });
864
- *
865
- * // Asynchronous (with workers) - typed as Promise<Vec2[]>
866
- * const navmesh = new NavMesh('grid', { workers: true });
867
- * const path = await navmesh.findPath({ from, to });
868
- *
869
- * // Auto mode - typed as Vec2[] | Promise<Vec2[]>
870
- * const navmesh = new NavMesh('grid', { workers: 'auto' });
871
- * const result = navmesh.findPath({ from, to });
872
- * const path = result instanceof Promise ? await result : result;
873
- * ```
874
- */
875
- findPath({ from, to }: { from: Vec2; to: Vec2 }): PathResult<TWorkers> {
876
- // Check if we should use workers
877
- if (this.shouldUseWorkers() && this.workerPool) {
878
- // Async path (with workers)
879
- this.pendingPaths++;
880
- return this.findPathAsync(from, to).finally(() => {
881
- this.pendingPaths--;
882
- }) as PathResult<TWorkers>;
883
- }
884
-
885
- // Sync path (no workers)
886
- this.rebuild();
887
- return (this.type === 'grid'
888
- ? this.grid!.findPath(from, to)
889
- : this.graph!.findPath(from, to)) as PathResult<TWorkers>;
890
- }
891
-
892
- /**
893
- * Async pathfinding using worker pool
894
- */
895
- private async findPathAsync(from: Vec2, to: Vec2): Promise<Vec2[]> {
896
- // Lazy init for 'auto' mode
897
- if (this.options.workers === 'auto' && !this.workerPool) {
898
- await this.initWorkerPool();
899
- }
900
-
901
- if (!this.workerPool) {
902
- // Fallback to sync if workers failed to init
903
- this.rebuild();
904
- return this.type === 'grid'
905
- ? this.grid!.findPath(from, to)
906
- : this.graph!.findPath(from, to);
907
- }
908
-
909
- return this.workerPool.findPath(from, to);
910
- }
911
-
912
- /**
913
- * Smart rebuild - only rebuilds if obstacles changed.
914
- * Version checking eliminates unnecessary work.
915
- */
916
- rebuild() {
917
- if (this.lastVersion === this.obstacles.version) return;
918
-
919
- this.grid?.rebuild();
920
- this.graph?.rebuild();
921
-
922
- this.lastVersion = this.obstacles.version;
923
- }
924
-
925
- /**
926
- * Cleanup resources (terminate worker pool if active)
927
- * Call this when you're done with the NavMesh instance.
928
- *
929
- * @example
930
- * ```ts
931
- * const navmesh = new NavMesh('grid', { workers: true });
932
- * // ... use navmesh ...
933
- * navmesh.dispose(); // Cleanup workers
934
- * ```
935
- */
936
- dispose() {
937
- if (this.workerPool) {
938
- this.workerPool.terminate();
939
- this.workerPool = undefined;
940
- }
941
- }
942
-
943
- /**
944
- * Get current worker status for debugging/monitoring
945
- */
946
- getWorkerStatus() {
947
- return {
948
- workersEnabled: this.options.workers,
949
- workerPoolActive: !!this.workerPool,
950
- pendingPaths: this.pendingPaths,
951
- usingWorkersNow: this.shouldUseWorkers(),
952
- };
953
- }
954
- }
955
-
956
- /* ---------------------------------- */
957
- /* A* */
958
- /* ---------------------------------- */
959
-
960
- /**
961
- * A* pathfinding with binary heap and proper open set tracking.
962
- *
963
- * Optimizations:
964
- * - Binary heap: O(log n) operations
965
- * - Open set tracking: prevents duplicate nodes
966
- * - Integer cell encoding: eliminates string allocation
967
- * - Closed set: avoids reprocessing
968
- *
969
- * Performance: Handles 10k+ node searches efficiently.
970
- * Time: O(b^d * log n) where b = branching, d = depth, n = nodes.
971
- */
972
- function aStar(
973
- start: Vec2,
974
- goal: Vec2,
975
- walkable: (x: number, y: number) => boolean
976
- ): Vec2[] {
977
- const cameFrom = new Map<number, number>();
978
- const g = new Map<number, number>();
979
- const closed = new Set<number>();
980
- const openSet = new Set<number>();
981
-
982
- const key = (p: Vec2): number => encodeCell(p.x, p.y);
983
- const h = (a: Vec2, b: Vec2): number =>
984
- Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
985
-
986
- const open = new BinaryHeap<number>((nodeKey) => {
987
- const pos = decodeCell(nodeKey);
988
- return g.get(nodeKey)! + h(pos, goal);
989
- });
990
-
991
- const startKey = key(start);
992
- g.set(startKey, 0);
993
- open.push(startKey);
994
- openSet.add(startKey);
995
-
996
- while (open.size > 0) {
997
- const currentKey = open.pop()!;
998
- openSet.delete(currentKey);
999
- const current = decodeCell(currentKey);
1000
-
1001
- if (current.x === goal.x && current.y === goal.y) {
1002
- return reconstruct(cameFrom, current);
1003
- }
1004
-
1005
- closed.add(currentKey);
1006
-
1007
- for (const d of dirs) {
1008
- const n = { x: current.x + d.x, y: current.y + d.y };
1009
- if (!walkable(n.x, n.y)) continue;
1010
-
1011
- const nk = key(n);
1012
- if (closed.has(nk)) continue;
1013
-
1014
- const ng = g.get(currentKey)! + 1;
1015
-
1016
- if (ng < (g.get(nk) ?? Infinity)) {
1017
- g.set(nk, ng);
1018
- cameFrom.set(nk, currentKey);
1019
-
1020
- if (!openSet.has(nk)) {
1021
- open.push(nk);
1022
- openSet.add(nk);
1023
- }
1024
- }
1025
- }
1026
- }
1027
-
1028
- return [];
1029
- }
1030
-
1031
- /**
1032
- * Reconstructs path from A* came-from map.
1033
- */
1034
- function reconstruct(
1035
- cameFrom: Map<number, number>,
1036
- current: Vec2
1037
- ): Vec2[] {
1038
- const path = [current];
1039
- let k = encodeCell(current.x, current.y);
1040
-
1041
- while (cameFrom.has(k)) {
1042
- k = cameFrom.get(k)!;
1043
- path.push(decodeCell(k));
1044
- }
1045
-
1046
- return path.reverse();
1047
- }