murow 0.0.70 → 0.0.72

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 (470) hide show
  1. package/README.md +54 -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/renderer-2d.js +1 -0
  74. package/dist/cjs/renderer/base/renderer-3d.js +1 -0
  75. package/dist/cjs/renderer/base/renderer.js +1 -0
  76. package/dist/cjs/renderer/gltf/helpers.js +1 -0
  77. package/dist/cjs/renderer/gltf/parser.js +1 -0
  78. package/dist/cjs/renderer/gltf/skeletal-animation.js +1 -0
  79. package/dist/cjs/renderer/gltf/skin-parser.js +1 -0
  80. package/dist/cjs/renderer/index.js +1 -0
  81. package/dist/cjs/renderer/math.js +1 -0
  82. package/dist/cjs/renderer/prefab-bucket/concrete.js +1 -0
  83. package/dist/cjs/renderer/prefab-bucket/index.js +1 -0
  84. package/dist/cjs/renderer/prefab-bucket/parsers.js +1 -0
  85. package/dist/cjs/renderer/prefab-bucket/specs.js +1 -0
  86. package/dist/cjs/renderer/spritesheet/helpers.js +1 -0
  87. package/dist/cjs/renderer/spritesheet/parser.js +1 -0
  88. package/dist/cjs/renderer/types.js +1 -0
  89. package/dist/esm/core/binary-codec/binary-codec.js +1 -0
  90. package/dist/esm/core/binary-codec/index.js +1 -0
  91. package/dist/esm/core/driver/driver.js +1 -0
  92. package/dist/esm/core/driver/drivers/immediate.js +1 -0
  93. package/dist/esm/core/driver/drivers/index.js +1 -0
  94. package/dist/esm/core/driver/drivers/raf.js +1 -0
  95. package/dist/esm/core/driver/drivers/timeout.js +1 -0
  96. package/dist/esm/core/driver/index.js +1 -0
  97. package/dist/esm/core/events/event-system.js +1 -0
  98. package/dist/esm/core/events/index.js +1 -0
  99. package/dist/esm/core/fixed-ticker/fixed-ticker.js +1 -0
  100. package/dist/esm/core/fixed-ticker/index.js +1 -0
  101. package/dist/esm/core/free-list/free-list.js +1 -0
  102. package/dist/esm/core/free-list/index.js +1 -0
  103. package/dist/esm/core/generate-id/generate-id.js +1 -0
  104. package/dist/esm/core/generate-id/index.js +1 -0
  105. package/dist/esm/core/index.js +1 -0
  106. package/dist/esm/core/input/index.js +1 -0
  107. package/dist/esm/core/input/manager.js +1 -0
  108. package/dist/esm/core/input/sources/browser.js +1 -0
  109. package/dist/esm/core/input/sources/index.js +1 -0
  110. package/dist/esm/core/input/types.js +0 -0
  111. package/dist/esm/core/lerp/index.js +1 -0
  112. package/dist/esm/core/lerp/lerp.js +1 -0
  113. package/dist/esm/core/navmesh/index.js +1 -0
  114. package/dist/esm/core/navmesh/navmesh-worker-pool.js +1 -0
  115. package/dist/esm/core/navmesh/navmesh.js +1 -0
  116. package/dist/esm/core/navmesh/navmesh.worker.js +1 -0
  117. package/dist/esm/core/pooled-codec/index.js +1 -0
  118. package/dist/esm/core/pooled-codec/pooled-codec.js +1 -0
  119. package/dist/esm/core/prediction/index.js +1 -0
  120. package/dist/esm/core/prediction/prediction.js +1 -0
  121. package/dist/esm/core/ray/index.js +1 -0
  122. package/dist/esm/core/ray/ray-2d.js +1 -0
  123. package/dist/esm/core/ray/ray-3d.js +1 -0
  124. package/dist/esm/core/simple-rng/index.js +1 -0
  125. package/dist/esm/core/simple-rng/simple-rng.js +1 -0
  126. package/dist/esm/core/sparse-batcher/index.js +1 -0
  127. package/dist/esm/core/sparse-batcher/sparse-batcher.js +1 -0
  128. package/dist/esm/ecs/component-store.js +1 -0
  129. package/dist/esm/ecs/component.js +1 -0
  130. package/dist/esm/ecs/entity-handle.js +1 -0
  131. package/dist/esm/ecs/index.js +1 -0
  132. package/dist/esm/ecs/system-builder.js +1 -0
  133. package/dist/esm/ecs/world-systems.js +1 -0
  134. package/dist/esm/ecs/world.js +1 -0
  135. package/dist/esm/game/index.js +1 -0
  136. package/dist/esm/game/loop/index.js +1 -0
  137. package/dist/esm/game/loop/loop.js +1 -0
  138. package/dist/esm/index.js +1 -0
  139. package/dist/esm/net/adapters/browser-websocket.js +1 -0
  140. package/dist/esm/net/adapters/bun-websocket.js +1 -0
  141. package/dist/esm/net/buffer-pool.js +1 -0
  142. package/dist/esm/net/client.js +1 -0
  143. package/dist/esm/net/index.js +1 -0
  144. package/dist/esm/net/server.js +1 -0
  145. package/dist/esm/net/types.js +1 -0
  146. package/dist/esm/net/validators.js +1 -0
  147. package/dist/esm/protocol/index.js +1 -0
  148. package/dist/esm/protocol/intent/define-intent.js +1 -0
  149. package/dist/esm/protocol/intent/index.js +1 -0
  150. package/dist/esm/protocol/intent/intent-registry.js +1 -0
  151. package/dist/esm/protocol/intent/intent.js +0 -0
  152. package/dist/esm/protocol/rpc/define-rpc.js +1 -0
  153. package/dist/esm/protocol/rpc/index.js +1 -0
  154. package/dist/esm/protocol/rpc/rpc-registry.js +1 -0
  155. package/dist/esm/protocol/rpc/rpc.js +0 -0
  156. package/dist/esm/protocol/snapshot/index.js +1 -0
  157. package/dist/esm/protocol/snapshot/snapshot-codec.js +1 -0
  158. package/dist/esm/protocol/snapshot/snapshot-registry.js +1 -0
  159. package/dist/esm/protocol/snapshot/snapshot.js +1 -0
  160. package/dist/esm/renderer/base/renderer-2d.js +1 -0
  161. package/dist/esm/renderer/base/renderer-3d.js +1 -0
  162. package/dist/esm/renderer/base/renderer.js +1 -0
  163. package/dist/esm/renderer/gltf/helpers.js +1 -0
  164. package/dist/esm/renderer/gltf/parser.js +1 -0
  165. package/dist/esm/renderer/gltf/skeletal-animation.js +1 -0
  166. package/dist/esm/renderer/gltf/skin-parser.js +1 -0
  167. package/dist/esm/renderer/index.js +1 -0
  168. package/dist/esm/renderer/math.js +1 -0
  169. package/dist/esm/renderer/prefab-bucket/concrete.js +1 -0
  170. package/dist/esm/renderer/prefab-bucket/index.js +1 -0
  171. package/dist/esm/renderer/prefab-bucket/parsers.js +1 -0
  172. package/dist/esm/renderer/prefab-bucket/specs.js +0 -0
  173. package/dist/esm/renderer/spritesheet/helpers.js +1 -0
  174. package/dist/esm/renderer/spritesheet/parser.js +1 -0
  175. package/dist/esm/renderer/types.js +0 -0
  176. package/dist/{core → types/core}/binary-codec/binary-codec.d.ts +4 -0
  177. package/dist/{core → types/core}/events/event-system.d.ts +14 -33
  178. package/dist/types/core/free-list/free-list.d.ts +31 -0
  179. package/dist/types/core/free-list/index.d.ts +1 -0
  180. package/dist/{core → types/core}/index.d.ts +5 -0
  181. package/dist/{core → types/core}/input/index.d.ts +1 -0
  182. package/dist/{core → types/core}/input/manager.d.ts +2 -0
  183. package/dist/{core → types/core}/navmesh/navmesh.d.ts +1 -21
  184. package/dist/types/core/ray/index.d.ts +2 -0
  185. package/dist/types/core/ray/ray-2d.d.ts +37 -0
  186. package/dist/types/core/ray/ray-3d.d.ts +42 -0
  187. package/dist/types/core/simple-rng/index.d.ts +1 -0
  188. package/dist/types/core/simple-rng/simple-rng.d.ts +36 -0
  189. package/dist/types/core/sparse-batcher/index.d.ts +1 -0
  190. package/dist/types/core/sparse-batcher/sparse-batcher.d.ts +55 -0
  191. package/dist/{ecs → types/ecs}/world.d.ts +11 -0
  192. package/dist/{game → types/game}/loop/loop.d.ts +33 -29
  193. package/dist/{index.d.ts → types/index.d.ts} +1 -0
  194. package/dist/{net → types/net}/index.d.ts +2 -2
  195. package/dist/types/renderer/base/renderer-2d.d.ts +13 -0
  196. package/dist/types/renderer/base/renderer-3d.d.ts +10 -0
  197. package/dist/types/renderer/base/renderer.d.ts +21 -0
  198. package/dist/types/renderer/gltf/helpers.d.ts +43 -0
  199. package/dist/types/renderer/gltf/parser.d.ts +49 -0
  200. package/dist/types/renderer/gltf/skeletal-animation.d.ts +96 -0
  201. package/dist/types/renderer/gltf/skin-parser.d.ts +107 -0
  202. package/dist/types/renderer/index.d.ts +15 -0
  203. package/dist/types/renderer/math.d.ts +37 -0
  204. package/dist/types/renderer/prefab-bucket/concrete.d.ts +55 -0
  205. package/dist/types/renderer/prefab-bucket/index.d.ts +113 -0
  206. package/dist/types/renderer/prefab-bucket/parsers.d.ts +8 -0
  207. package/dist/types/renderer/prefab-bucket/specs.d.ts +166 -0
  208. package/dist/types/renderer/spritesheet/helpers.d.ts +38 -0
  209. package/dist/types/renderer/spritesheet/parser.d.ts +21 -0
  210. package/dist/types/renderer/types.d.ts +89 -0
  211. package/dist/webgpu/cjs/index.js +5401 -0
  212. package/dist/webgpu/esm/index.js +5378 -0
  213. package/dist/webgpu/types/2d/animation.d.ts +97 -0
  214. package/dist/webgpu/types/2d/renderer.d.ts +86 -0
  215. package/dist/webgpu/types/2d/shader.d.ts +61 -0
  216. package/dist/webgpu/types/2d/sprite-accessor.d.ts +47 -0
  217. package/dist/webgpu/types/3d/clip-resync-coordinator.d.ts +20 -0
  218. package/dist/webgpu/types/3d/morph-animation.d.ts +69 -0
  219. package/dist/webgpu/types/3d/morph-animation.test.d.ts +1 -0
  220. package/dist/webgpu/types/3d/renderer.d.ts +266 -0
  221. package/dist/webgpu/types/3d/shader.d.ts +136 -0
  222. package/dist/webgpu/types/3d/skeletal-animation-compute/index.d.ts +2 -0
  223. package/dist/webgpu/types/3d/skeletal-animation-compute/kernel.d.ts +25 -0
  224. package/dist/webgpu/types/3d/skeletal-animation-compute/packer.d.ts +32 -0
  225. package/dist/webgpu/types/camera/camera-2d.d.ts +53 -0
  226. package/dist/webgpu/types/camera/camera-2d.test.d.ts +1 -0
  227. package/dist/webgpu/types/camera/camera-3d.d.ts +81 -0
  228. package/dist/webgpu/types/camera/camera-3d.test.d.ts +1 -0
  229. package/dist/webgpu/types/camera/index.d.ts +2 -0
  230. package/dist/webgpu/types/compute/compute-builder.d.ts +123 -0
  231. package/dist/webgpu/types/compute/compute-builder.test.d.ts +1 -0
  232. package/dist/webgpu/types/core/constants.d.ts +59 -0
  233. package/dist/webgpu/types/core/constants.test.d.ts +1 -0
  234. package/dist/webgpu/types/core/index.d.ts +2 -0
  235. package/dist/webgpu/types/core/types.d.ts +125 -0
  236. package/dist/webgpu/types/core/types.test.d.ts +1 -0
  237. package/dist/webgpu/types/geometry/built-in.d.ts +58 -0
  238. package/dist/webgpu/types/geometry/built-in.test.d.ts +1 -0
  239. package/dist/webgpu/types/geometry/geometry-builder.d.ts +281 -0
  240. package/dist/webgpu/types/geometry/geometry-builder.test.d.ts +1 -0
  241. package/dist/webgpu/types/geometry/index.d.ts +2 -0
  242. package/dist/webgpu/types/index.d.ts +35 -0
  243. package/dist/webgpu/types/particle/emitter.d.ts +36 -0
  244. package/dist/webgpu/types/shaders/index.d.ts +2 -0
  245. package/dist/webgpu/types/shaders/runtime-transpile.d.ts +18 -0
  246. package/dist/webgpu/types/shaders/sprite-2d.wgsl.d.ts +10 -0
  247. package/dist/webgpu/types/shaders/typegpu.d.ts +9 -0
  248. package/dist/webgpu/types/shaders/utils.d.ts +28 -0
  249. package/dist/webgpu/types/shaders/utils.test.d.ts +1 -0
  250. package/dist/webgpu/types/spritesheet/index.d.ts +1 -0
  251. package/dist/webgpu/types/spritesheet/spritesheet.d.ts +28 -0
  252. package/dist/webgpu/types/spritesheet/spritesheet.test.d.ts +1 -0
  253. package/package.json +96 -26
  254. package/dist/core/binary-codec/binary-codec.js +0 -354
  255. package/dist/core/binary-codec/index.js +0 -1
  256. package/dist/core/driver/driver.js +0 -47
  257. package/dist/core/driver/drivers/immediate.js +0 -61
  258. package/dist/core/driver/drivers/index.js +0 -3
  259. package/dist/core/driver/drivers/raf.js +0 -62
  260. package/dist/core/driver/drivers/timeout.js +0 -71
  261. package/dist/core/driver/index.js +0 -2
  262. package/dist/core/events/event-system.js +0 -88
  263. package/dist/core/events/index.js +0 -1
  264. package/dist/core/fixed-ticker/fixed-ticker.js +0 -105
  265. package/dist/core/fixed-ticker/index.js +0 -1
  266. package/dist/core/generate-id/generate-id.js +0 -25
  267. package/dist/core/generate-id/index.js +0 -1
  268. package/dist/core/index.js +0 -10
  269. package/dist/core/input/index.js +0 -2
  270. package/dist/core/input/manager.js +0 -211
  271. package/dist/core/input/sources/browser.js +0 -29
  272. package/dist/core/input/sources/index.js +0 -1
  273. package/dist/core/lerp/index.js +0 -1
  274. package/dist/core/lerp/lerp.js +0 -42
  275. package/dist/core/navmesh/index.js +0 -1
  276. package/dist/core/navmesh/navmesh-worker-pool.js +0 -180
  277. package/dist/core/navmesh/navmesh.js +0 -799
  278. package/dist/core/navmesh/navmesh.worker.js +0 -79
  279. package/dist/core/pooled-codec/index.js +0 -1
  280. package/dist/core/pooled-codec/pooled-codec.js +0 -410
  281. package/dist/core/prediction/index.js +0 -1
  282. package/dist/core/prediction/prediction.js +0 -99
  283. package/dist/core.esm.js +0 -1
  284. package/dist/core.js +0 -1
  285. package/dist/ecs/component-store.js +0 -175
  286. package/dist/ecs/component.js +0 -43
  287. package/dist/ecs/entity-handle.js +0 -515
  288. package/dist/ecs/example.js +0 -125
  289. package/dist/ecs/index.js +0 -4
  290. package/dist/ecs/system-builder.js +0 -249
  291. package/dist/ecs/world-systems.js +0 -79
  292. package/dist/ecs/world.js +0 -767
  293. package/dist/game/index.js +0 -1
  294. package/dist/game/loop/index.js +0 -1
  295. package/dist/game/loop/loop.js +0 -108
  296. package/dist/index.js +0 -26
  297. package/dist/net/adapters/browser-websocket.js +0 -74
  298. package/dist/net/adapters/bun-websocket.js +0 -245
  299. package/dist/net/buffer-pool.js +0 -89
  300. package/dist/net/client.js +0 -586
  301. package/dist/net/index.js +0 -58
  302. package/dist/net/server.js +0 -974
  303. package/dist/net/types.js +0 -31
  304. package/dist/net/validators.js +0 -88
  305. package/dist/protocol/index.js +0 -92
  306. package/dist/protocol/intent/define-intent.js +0 -125
  307. package/dist/protocol/intent/index.js +0 -91
  308. package/dist/protocol/intent/intent-registry.js +0 -91
  309. package/dist/protocol/rpc/define-rpc.js +0 -84
  310. package/dist/protocol/rpc/index.js +0 -3
  311. package/dist/protocol/rpc/rpc-registry.js +0 -159
  312. package/dist/protocol/rpc/rpc.js +0 -12
  313. package/dist/protocol/snapshot/index.js +0 -43
  314. package/dist/protocol/snapshot/snapshot-codec.js +0 -67
  315. package/dist/protocol/snapshot/snapshot-registry.js +0 -168
  316. package/dist/protocol/snapshot/snapshot.js +0 -30
  317. package/src/core/binary-codec/README.md +0 -60
  318. package/src/core/binary-codec/binary-codec.test.ts +0 -300
  319. package/src/core/binary-codec/binary-codec.ts +0 -448
  320. package/src/core/binary-codec/index.ts +0 -1
  321. package/src/core/driver/README.md +0 -97
  322. package/src/core/driver/driver.test.ts +0 -414
  323. package/src/core/driver/driver.ts +0 -71
  324. package/src/core/driver/drivers/immediate.ts +0 -66
  325. package/src/core/driver/drivers/index.ts +0 -3
  326. package/src/core/driver/drivers/raf.ts +0 -67
  327. package/src/core/driver/drivers/timeout.ts +0 -77
  328. package/src/core/driver/index.ts +0 -2
  329. package/src/core/events/README.md +0 -47
  330. package/src/core/events/event-system.test.ts +0 -243
  331. package/src/core/events/event-system.ts +0 -140
  332. package/src/core/events/index.ts +0 -1
  333. package/src/core/fixed-ticker/README.md +0 -77
  334. package/src/core/fixed-ticker/fixed-ticker.test.ts +0 -151
  335. package/src/core/fixed-ticker/fixed-ticker.ts +0 -174
  336. package/src/core/fixed-ticker/index.ts +0 -1
  337. package/src/core/generate-id/README.md +0 -18
  338. package/src/core/generate-id/generate-id.test.ts +0 -79
  339. package/src/core/generate-id/generate-id.ts +0 -37
  340. package/src/core/generate-id/index.ts +0 -1
  341. package/src/core/index.ts +0 -10
  342. package/src/core/input/README.md +0 -24
  343. package/src/core/input/index.ts +0 -2
  344. package/src/core/input/manager.ts +0 -259
  345. package/src/core/input/sources/browser.ts +0 -39
  346. package/src/core/input/sources/index.ts +0 -1
  347. package/src/core/input/types.ts +0 -40
  348. package/src/core/lerp/README.md +0 -79
  349. package/src/core/lerp/index.ts +0 -1
  350. package/src/core/lerp/lerp.test.ts +0 -90
  351. package/src/core/lerp/lerp.ts +0 -42
  352. package/src/core/navmesh/README.md +0 -164
  353. package/src/core/navmesh/index.ts +0 -1
  354. package/src/core/navmesh/navmesh-worker-pool.ts +0 -236
  355. package/src/core/navmesh/navmesh-workers.test.ts +0 -356
  356. package/src/core/navmesh/navmesh.test.ts +0 -344
  357. package/src/core/navmesh/navmesh.ts +0 -1047
  358. package/src/core/navmesh/navmesh.worker.ts +0 -147
  359. package/src/core/pooled-codec/README.md +0 -70
  360. package/src/core/pooled-codec/index.ts +0 -1
  361. package/src/core/pooled-codec/pooled-codec.test.ts +0 -862
  362. package/src/core/pooled-codec/pooled-codec.ts +0 -504
  363. package/src/core/prediction/README.md +0 -64
  364. package/src/core/prediction/index.ts +0 -1
  365. package/src/core/prediction/prediction.test.ts +0 -423
  366. package/src/core/prediction/prediction.ts +0 -112
  367. package/src/ecs/README.md +0 -427
  368. package/src/ecs/benchmark.test.ts +0 -1645
  369. package/src/ecs/component-store.ts +0 -198
  370. package/src/ecs/component.ts +0 -90
  371. package/src/ecs/entity-handle.test.ts +0 -393
  372. package/src/ecs/entity-handle.ts +0 -563
  373. package/src/ecs/example.ts +0 -152
  374. package/src/ecs/index.ts +0 -4
  375. package/src/ecs/system-builder.ts +0 -404
  376. package/src/ecs/world-systems.ts +0 -83
  377. package/src/ecs/world.test.ts +0 -310
  378. package/src/ecs/world.ts +0 -904
  379. package/src/game/index.ts +0 -1
  380. package/src/game/loop/README.md +0 -32
  381. package/src/game/loop/index.ts +0 -1
  382. package/src/game/loop/loop.ts +0 -236
  383. package/src/index.ts +0 -32
  384. package/src/net/README.md +0 -474
  385. package/src/net/adapters/browser-websocket.ts +0 -86
  386. package/src/net/adapters/bun-websocket.ts +0 -292
  387. package/src/net/buffer-pool.ts +0 -106
  388. package/src/net/client.test.ts +0 -807
  389. package/src/net/client.ts +0 -695
  390. package/src/net/index.ts +0 -60
  391. package/src/net/server.test.ts +0 -799
  392. package/src/net/server.ts +0 -1152
  393. package/src/net/types.ts +0 -228
  394. package/src/net/validators.ts +0 -104
  395. package/src/protocol/README.md +0 -469
  396. package/src/protocol/index.ts +0 -93
  397. package/src/protocol/intent/define-intent.test.ts +0 -397
  398. package/src/protocol/intent/define-intent.ts +0 -201
  399. package/src/protocol/intent/index.ts +0 -94
  400. package/src/protocol/intent/intent-registry.test.ts +0 -198
  401. package/src/protocol/intent/intent-registry.ts +0 -112
  402. package/src/protocol/intent/intent.ts +0 -12
  403. package/src/protocol/rpc/define-rpc.test.ts +0 -141
  404. package/src/protocol/rpc/define-rpc.ts +0 -113
  405. package/src/protocol/rpc/index.ts +0 -3
  406. package/src/protocol/rpc/rpc-registry.test.ts +0 -168
  407. package/src/protocol/rpc/rpc-registry.ts +0 -176
  408. package/src/protocol/rpc/rpc.ts +0 -37
  409. package/src/protocol/snapshot/index.ts +0 -45
  410. package/src/protocol/snapshot/snapshot-codec.test.ts +0 -138
  411. package/src/protocol/snapshot/snapshot-codec.ts +0 -87
  412. package/src/protocol/snapshot/snapshot-registry.test.ts +0 -310
  413. package/src/protocol/snapshot/snapshot-registry.ts +0 -201
  414. package/src/protocol/snapshot/snapshot.test.ts +0 -76
  415. package/src/protocol/snapshot/snapshot.ts +0 -41
  416. /package/dist/{core → types/core}/binary-codec/index.d.ts +0 -0
  417. /package/dist/{core → types/core}/driver/driver.d.ts +0 -0
  418. /package/dist/{core → types/core}/driver/drivers/immediate.d.ts +0 -0
  419. /package/dist/{core → types/core}/driver/drivers/index.d.ts +0 -0
  420. /package/dist/{core → types/core}/driver/drivers/raf.d.ts +0 -0
  421. /package/dist/{core → types/core}/driver/drivers/timeout.d.ts +0 -0
  422. /package/dist/{core → types/core}/driver/index.d.ts +0 -0
  423. /package/dist/{core → types/core}/events/index.d.ts +0 -0
  424. /package/dist/{core → types/core}/fixed-ticker/fixed-ticker.d.ts +0 -0
  425. /package/dist/{core → types/core}/fixed-ticker/index.d.ts +0 -0
  426. /package/dist/{core → types/core}/generate-id/generate-id.d.ts +0 -0
  427. /package/dist/{core → types/core}/generate-id/index.d.ts +0 -0
  428. /package/dist/{core → types/core}/input/sources/browser.d.ts +0 -0
  429. /package/dist/{core → types/core}/input/sources/index.d.ts +0 -0
  430. /package/dist/{core → types/core}/input/types.d.ts +0 -0
  431. /package/dist/{core → types/core}/lerp/index.d.ts +0 -0
  432. /package/dist/{core → types/core}/lerp/lerp.d.ts +0 -0
  433. /package/dist/{core → types/core}/navmesh/index.d.ts +0 -0
  434. /package/dist/{core → types/core}/navmesh/navmesh-worker-pool.d.ts +0 -0
  435. /package/dist/{core → types/core}/navmesh/navmesh.worker.d.ts +0 -0
  436. /package/dist/{core → types/core}/pooled-codec/index.d.ts +0 -0
  437. /package/dist/{core → types/core}/pooled-codec/pooled-codec.d.ts +0 -0
  438. /package/dist/{core → types/core}/prediction/index.d.ts +0 -0
  439. /package/dist/{core → types/core}/prediction/prediction.d.ts +0 -0
  440. /package/dist/{ecs → types/ecs}/component-store.d.ts +0 -0
  441. /package/dist/{ecs → types/ecs}/component.d.ts +0 -0
  442. /package/dist/{ecs → types/ecs}/entity-handle.d.ts +0 -0
  443. /package/dist/{ecs → types/ecs}/example.d.ts +0 -0
  444. /package/dist/{ecs → types/ecs}/index.d.ts +0 -0
  445. /package/dist/{ecs → types/ecs}/system-builder.d.ts +0 -0
  446. /package/dist/{ecs → types/ecs}/world-systems.d.ts +0 -0
  447. /package/dist/{game → types/game}/index.d.ts +0 -0
  448. /package/dist/{game → types/game}/loop/index.d.ts +0 -0
  449. /package/dist/{net → types/net}/adapters/browser-websocket.d.ts +0 -0
  450. /package/dist/{net → types/net}/adapters/bun-websocket.d.ts +0 -0
  451. /package/dist/{net → types/net}/buffer-pool.d.ts +0 -0
  452. /package/dist/{net → types/net}/client.d.ts +0 -0
  453. /package/dist/{net → types/net}/server.d.ts +0 -0
  454. /package/dist/{net → types/net}/types.d.ts +0 -0
  455. /package/dist/{net → types/net}/validators.d.ts +0 -0
  456. /package/dist/{protocol → types/protocol}/index.d.ts +0 -0
  457. /package/dist/{protocol → types/protocol}/intent/define-intent.d.ts +0 -0
  458. /package/dist/{protocol → types/protocol}/intent/index.d.ts +0 -0
  459. /package/dist/{protocol → types/protocol}/intent/intent-registry.d.ts +0 -0
  460. /package/dist/{protocol → types/protocol}/intent/intent.d.ts +0 -0
  461. /package/dist/{protocol → types/protocol}/rpc/define-rpc.d.ts +0 -0
  462. /package/dist/{protocol → types/protocol}/rpc/index.d.ts +0 -0
  463. /package/dist/{protocol → types/protocol}/rpc/rpc-registry.d.ts +0 -0
  464. /package/dist/{protocol → types/protocol}/rpc/rpc.d.ts +0 -0
  465. /package/dist/{protocol → types/protocol}/snapshot/index.d.ts +0 -0
  466. /package/dist/{protocol → types/protocol}/snapshot/snapshot-codec.d.ts +0 -0
  467. /package/dist/{protocol → types/protocol}/snapshot/snapshot-registry.d.ts +0 -0
  468. /package/dist/{protocol → types/protocol}/snapshot/snapshot.d.ts +0 -0
  469. /package/dist/{core/input/types.js → webgpu/types/2d/animation.test.d.ts} +0 -0
  470. /package/dist/{protocol/intent/intent.js → webgpu/types/2d/sprite-accessor.test.d.ts} +0 -0
@@ -1,807 +0,0 @@
1
- import { describe, expect, test, beforeEach } from "bun:test";
2
- import { ClientNetwork } from "./client";
3
- import { IntentRegistry } from "../protocol/intent/intent-registry";
4
- import { SnapshotRegistry } from "../protocol/snapshot/snapshot-registry";
5
- import { RpcRegistry } from "../protocol/rpc/rpc-registry";
6
- import { PooledCodec } from "../core/pooled-codec/pooled-codec";
7
- import { BinaryPrimitives } from "../core/binary-codec";
8
- import { defineIntent } from "../protocol/intent/define-intent";
9
- import { defineRPC } from "../protocol/rpc/define-rpc";
10
- import type { TransportAdapter } from "./types";
11
- import { MessageType } from "./types";
12
- import type { Snapshot } from "../protocol/snapshot/snapshot";
13
-
14
- // Define move intent using defineIntent
15
- const MoveIntent = defineIntent({
16
- kind: 1 as const,
17
- schema: {
18
- dx: BinaryPrimitives.f32,
19
- dy: BinaryPrimitives.f32,
20
- },
21
- });
22
-
23
- type MoveIntent = typeof MoveIntent.type;
24
-
25
- interface PlayerUpdate {
26
- x: number;
27
- y: number;
28
- health: number;
29
- }
30
-
31
- interface ScoreUpdate {
32
- score: number;
33
- }
34
-
35
- type GameSnapshots = PlayerUpdate | ScoreUpdate;
36
-
37
- // Mock transport adapter
38
- class MockTransportAdapter implements TransportAdapter {
39
- messageHandler: ((data: Uint8Array) => void) | null = null;
40
- closeHandler: (() => void) | null = null;
41
- openHandler: (() => void) | null = null;
42
- public sentMessages: Uint8Array[] = [];
43
- public closed = false;
44
-
45
- send(data: Uint8Array): void {
46
- this.sentMessages.push(new Uint8Array(data)); // Copy to avoid mutation
47
- }
48
-
49
- onMessage(handler: (data: Uint8Array) => void): void {
50
- this.messageHandler = handler;
51
- }
52
-
53
- onClose(handler: () => void): void {
54
- this.closeHandler = handler;
55
- }
56
-
57
- onOpen(handler: () => void): void {
58
- this.openHandler = handler;
59
- }
60
-
61
- close(): void {
62
- this.closed = true;
63
- if (this.closeHandler) {
64
- this.closeHandler();
65
- }
66
- }
67
-
68
- // Test helper: simulate receiving a message
69
- simulateMessage(data: Uint8Array): void {
70
- if (this.messageHandler) {
71
- this.messageHandler(data);
72
- }
73
- }
74
-
75
- // Test helper: simulate disconnection
76
- simulateDisconnect(): void {
77
- if (this.closeHandler) {
78
- this.closeHandler();
79
- }
80
- }
81
- }
82
-
83
- describe("ClientNetwork", () => {
84
- let transport: MockTransportAdapter;
85
- let intentRegistry: IntentRegistry;
86
- let snapshotRegistry: SnapshotRegistry<GameSnapshots>;
87
- let client: ClientNetwork<GameSnapshots>;
88
-
89
- beforeEach(() => {
90
- transport = new MockTransportAdapter();
91
- intentRegistry = new IntentRegistry();
92
- snapshotRegistry = new SnapshotRegistry<GameSnapshots>();
93
-
94
- // Register move intent
95
- intentRegistry.register(MoveIntent);
96
-
97
- // Register snapshot codecs
98
- const playerCodec = new PooledCodec({
99
- x: BinaryPrimitives.f32,
100
- y: BinaryPrimitives.f32,
101
- health: BinaryPrimitives.u8,
102
- });
103
- snapshotRegistry.register("player", playerCodec);
104
-
105
- const scoreCodec = new PooledCodec({
106
- score: BinaryPrimitives.u32,
107
- });
108
- snapshotRegistry.register("score", scoreCodec);
109
-
110
- client = new ClientNetwork<GameSnapshots>({
111
- transport,
112
- intentRegistry,
113
- snapshotRegistry,
114
- config: { debug: false },
115
- });
116
-
117
- // Simulate connection opened
118
- if (transport.openHandler) {
119
- transport.openHandler();
120
- }
121
- });
122
-
123
- describe("Construction", () => {
124
- test("should initialize and mark as connected", () => {
125
- expect(client.isConnected()).toBe(true);
126
- });
127
-
128
- test("should setup transport handlers", () => {
129
- expect(transport.messageHandler).not.toBeNull();
130
- expect(transport.closeHandler).not.toBeNull();
131
- });
132
-
133
- test("should trigger onConnect handlers", () => {
134
- let connectCalled = false;
135
- const newTransport = new MockTransportAdapter();
136
- const newClient = new ClientNetwork<GameSnapshots>({
137
- transport: newTransport,
138
- intentRegistry,
139
- snapshotRegistry,
140
- });
141
-
142
- newClient.onConnect(() => {
143
- connectCalled = true;
144
- });
145
-
146
- // Connection happens during constructor
147
- expect(connectCalled).toBe(false); // Handler registered after construction
148
- });
149
- });
150
-
151
- describe("sendIntent", () => {
152
- test("should encode and send intent to server", () => {
153
- const intent: MoveIntent = {
154
- kind: 1,
155
- tick: 100,
156
- dx: 5.5,
157
- dy: -3.2,
158
- };
159
-
160
- client.sendIntent(intent);
161
-
162
- expect(transport.sentMessages).toHaveLength(1);
163
- const message = transport.sentMessages[0];
164
-
165
- // Check message type header
166
- expect(message[0]).toBe(0x01); // MessageType.INTENT
167
-
168
- // Verify intent data (skip message type byte)
169
- const intentData = message.subarray(1);
170
- const decoded = intentRegistry.decode(intentData) as MoveIntent;
171
- expect(decoded.kind).toBe(1);
172
- expect(decoded.tick).toBe(100);
173
- expect(decoded.dx).toBeCloseTo(5.5, 2);
174
- expect(decoded.dy).toBeCloseTo(-3.2, 2);
175
- });
176
-
177
- test("should not send intent when disconnected", () => {
178
- transport.simulateDisconnect();
179
-
180
- const intent: MoveIntent = {
181
- kind: 1,
182
- tick: 100,
183
- dx: 1,
184
- dy: 1,
185
- };
186
-
187
- client.sendIntent(intent);
188
- expect(transport.sentMessages).toHaveLength(0);
189
- });
190
-
191
- test("should handle encoding errors gracefully", () => {
192
- const badIntentRegistry = new IntentRegistry();
193
- const badClient = new ClientNetwork<GameSnapshots>({
194
- transport: new MockTransportAdapter(),
195
- intentRegistry: badIntentRegistry,
196
- snapshotRegistry,
197
- });
198
-
199
- const intent: MoveIntent = {
200
- kind: 99 as 1, // Not registered
201
- tick: 100,
202
- dx: 1,
203
- dy: 1,
204
- };
205
-
206
- // Should not throw
207
- expect(() => badClient.sendIntent(intent)).not.toThrow();
208
- });
209
- });
210
-
211
- describe("onSnapshot", () => {
212
- test("should receive and decode player snapshot", () => {
213
- let receivedSnapshot: Snapshot<PlayerUpdate> | null = null;
214
-
215
- client.onSnapshot<PlayerUpdate>("player", (snapshot) => {
216
- receivedSnapshot = snapshot;
217
- });
218
-
219
- // Create snapshot
220
- const snapshot: Snapshot<PlayerUpdate> = {
221
- tick: 42,
222
- updates: {
223
- x: 10.5,
224
- y: 20.3,
225
- health: 100,
226
- },
227
- };
228
-
229
- // Encode and send
230
- const snapshotData = snapshotRegistry.encode("player", snapshot);
231
- const message = new Uint8Array(1 + snapshotData.byteLength);
232
- message[0] = 0x02; // MessageType.SNAPSHOT
233
- message.set(snapshotData, 1);
234
-
235
- transport.simulateMessage(message);
236
-
237
- expect(receivedSnapshot).not.toBeNull();
238
- expect(receivedSnapshot!.tick).toBe(42);
239
- expect(receivedSnapshot!.updates.x).toBeCloseTo(10.5, 2);
240
- expect(receivedSnapshot!.updates.y).toBeCloseTo(20.3, 2);
241
- expect(receivedSnapshot!.updates.health).toBe(100);
242
- });
243
-
244
- test("should receive and decode score snapshot", () => {
245
- let receivedSnapshot: Snapshot<ScoreUpdate> | null = null;
246
-
247
- client.onSnapshot<ScoreUpdate>("score", (snapshot) => {
248
- receivedSnapshot = snapshot;
249
- });
250
-
251
- const snapshot: Snapshot<ScoreUpdate> = {
252
- tick: 100,
253
- updates: {
254
- score: 9999,
255
- },
256
- };
257
-
258
- const snapshotData = snapshotRegistry.encode("score", snapshot);
259
- const message = new Uint8Array(1 + snapshotData.byteLength);
260
- message[0] = 0x02; // MessageType.SNAPSHOT
261
- message.set(snapshotData, 1);
262
-
263
- transport.simulateMessage(message);
264
-
265
- expect(receivedSnapshot).not.toBeNull();
266
- expect(receivedSnapshot!.tick).toBe(100);
267
- expect(receivedSnapshot!.updates.score).toBe(9999);
268
- });
269
-
270
- test("should handle multiple snapshot types independently", () => {
271
- const playerSnapshots: Snapshot<PlayerUpdate>[] = [];
272
- const scoreSnapshots: Snapshot<ScoreUpdate>[] = [];
273
-
274
- client.onSnapshot<PlayerUpdate>("player", (s) => playerSnapshots.push(s));
275
- client.onSnapshot<ScoreUpdate>("score", (s) => scoreSnapshots.push(s));
276
-
277
- // Send player snapshot
278
- const playerSnapshot: Snapshot<PlayerUpdate> = {
279
- tick: 1,
280
- updates: { x: 1, y: 2, health: 50 },
281
- };
282
- const playerData = snapshotRegistry.encode("player", playerSnapshot);
283
- const playerMsg = new Uint8Array(1 + playerData.byteLength);
284
- playerMsg[0] = 0x02;
285
- playerMsg.set(playerData, 1);
286
- transport.simulateMessage(playerMsg);
287
-
288
- // Send score snapshot
289
- const scoreSnapshot: Snapshot<ScoreUpdate> = {
290
- tick: 2,
291
- updates: { score: 123 },
292
- };
293
- const scoreData = snapshotRegistry.encode("score", scoreSnapshot);
294
- const scoreMsg = new Uint8Array(1 + scoreData.byteLength);
295
- scoreMsg[0] = 0x02;
296
- scoreMsg.set(scoreData, 1);
297
- transport.simulateMessage(scoreMsg);
298
-
299
- expect(playerSnapshots).toHaveLength(1);
300
- expect(scoreSnapshots).toHaveLength(1);
301
- expect(playerSnapshots[0].tick).toBe(1);
302
- expect(scoreSnapshots[0].tick).toBe(2);
303
- });
304
-
305
- test("should return unsubscribe function", () => {
306
- let callCount = 0;
307
- const unsubscribe = client.onSnapshot<PlayerUpdate>("player", () => {
308
- callCount++;
309
- });
310
-
311
- const snapshot: Snapshot<PlayerUpdate> = {
312
- tick: 1,
313
- updates: { x: 1, y: 1, health: 100 },
314
- };
315
- const snapshotData = snapshotRegistry.encode("player", snapshot);
316
- const message = new Uint8Array(1 + snapshotData.byteLength);
317
- message[0] = 0x02;
318
- message.set(snapshotData, 1);
319
-
320
- transport.simulateMessage(message);
321
- expect(callCount).toBe(1);
322
-
323
- // Unsubscribe
324
- unsubscribe();
325
-
326
- // Send another snapshot
327
- transport.simulateMessage(message);
328
- expect(callCount).toBe(1); // Should not increase
329
- });
330
-
331
- test("should handle unknown snapshot types gracefully", () => {
332
- // Register handler for "player" only
333
- let called = false;
334
- client.onSnapshot<PlayerUpdate>("player", () => {
335
- called = true;
336
- });
337
-
338
- // Send snapshot for unhandled type "score" (registered but no handler)
339
- const snapshot: Snapshot<ScoreUpdate> = {
340
- tick: 1,
341
- updates: { score: 42 },
342
- };
343
- const snapshotData = snapshotRegistry.encode("score", snapshot);
344
- const message = new Uint8Array(1 + snapshotData.byteLength);
345
- message[0] = 0x02;
346
- message.set(snapshotData, 1);
347
-
348
- // Should not throw or call the player handler
349
- expect(() => transport.simulateMessage(message)).not.toThrow();
350
- expect(called).toBe(false);
351
- });
352
- });
353
-
354
- describe("Connection lifecycle", () => {
355
- test("should trigger onConnect handler when connection opens", () => {
356
- let connectCalled = false;
357
- const newTransport = new MockTransportAdapter();
358
-
359
- const newClient = new ClientNetwork<GameSnapshots>({
360
- transport: newTransport,
361
- intentRegistry,
362
- snapshotRegistry,
363
- });
364
-
365
- newClient.onConnect(() => {
366
- connectCalled = true;
367
- });
368
-
369
- // Not connected yet - waiting for transport to open
370
- expect(connectCalled).toBe(false);
371
- expect(newClient.isConnected()).toBe(false);
372
-
373
- // Trigger open event
374
- if (newTransport.openHandler) {
375
- newTransport.openHandler();
376
- }
377
-
378
- // Now should be connected and handler should have been called
379
- expect(connectCalled).toBe(true);
380
- expect(newClient.isConnected()).toBe(true);
381
- });
382
-
383
- test("should trigger onDisconnect handler", () => {
384
- let disconnectCalled = false;
385
- client.onDisconnect(() => {
386
- disconnectCalled = true;
387
- });
388
-
389
- transport.simulateDisconnect();
390
-
391
- expect(disconnectCalled).toBe(true);
392
- expect(client.isConnected()).toBe(false);
393
- });
394
-
395
- test("should handle multiple disconnect handlers", () => {
396
- let count = 0;
397
- client.onDisconnect(() => count++);
398
- client.onDisconnect(() => count++);
399
- client.onDisconnect(() => count++);
400
-
401
- transport.simulateDisconnect();
402
- expect(count).toBe(3);
403
- });
404
-
405
- test("should return unsubscribe function for onConnect", () => {
406
- let callCount = 0;
407
- const unsub = client.onConnect(() => callCount++);
408
- unsub();
409
-
410
- // Create new client to trigger connect
411
- const newTransport = new MockTransportAdapter();
412
- const newClient = new ClientNetwork<GameSnapshots>({
413
- transport: newTransport,
414
- intentRegistry,
415
- snapshotRegistry,
416
- });
417
-
418
- expect(callCount).toBe(0);
419
- });
420
-
421
- test("should return unsubscribe function for onDisconnect", () => {
422
- let callCount = 0;
423
- const unsub = client.onDisconnect(() => callCount++);
424
-
425
- transport.simulateDisconnect();
426
- expect(callCount).toBe(1);
427
-
428
- unsub();
429
- // Can't trigger disconnect again on same transport, but verifies unsubscribe works
430
- });
431
- });
432
-
433
- describe("disconnect", () => {
434
- test("should close transport connection", () => {
435
- client.disconnect();
436
- expect(transport.closed).toBe(true);
437
- });
438
-
439
- test("should trigger disconnect handlers when calling disconnect", () => {
440
- let disconnectCalled = false;
441
- client.onDisconnect(() => {
442
- disconnectCalled = true;
443
- });
444
-
445
- client.disconnect();
446
- expect(disconnectCalled).toBe(true);
447
- expect(client.isConnected()).toBe(false);
448
- });
449
- });
450
-
451
- describe("Message handling", () => {
452
- test("should ignore empty messages", () => {
453
- let snapshotReceived = false;
454
- client.onSnapshot<PlayerUpdate>("player", () => {
455
- snapshotReceived = true;
456
- });
457
-
458
- transport.simulateMessage(new Uint8Array(0));
459
- expect(snapshotReceived).toBe(false);
460
- });
461
-
462
- test("should handle custom message type gracefully", () => {
463
- const message = new Uint8Array([0xff]); // MessageType.CUSTOM
464
- expect(() => transport.simulateMessage(message)).not.toThrow();
465
- });
466
-
467
- test("should handle unknown message types gracefully", () => {
468
- const message = new Uint8Array([0x99, 1, 2, 3]); // Unknown type
469
- expect(() => transport.simulateMessage(message)).not.toThrow();
470
- });
471
-
472
- test("should reject messages exceeding max size", () => {
473
- const smallClient = new ClientNetwork<GameSnapshots>({
474
- transport,
475
- intentRegistry,
476
- snapshotRegistry,
477
- config: { maxMessageSize: 10 },
478
- });
479
-
480
- let snapshotReceived = false;
481
- smallClient.onSnapshot<PlayerUpdate>("player", () => {
482
- snapshotReceived = true;
483
- });
484
-
485
- // Create large message
486
- const largeMessage = new Uint8Array(100);
487
- largeMessage[0] = 0x02; // MessageType.SNAPSHOT
488
-
489
- transport.simulateMessage(largeMessage);
490
- expect(snapshotReceived).toBe(false);
491
- });
492
-
493
- test("should handle malformed snapshot data gracefully", () => {
494
- let snapshotReceived = false;
495
- client.onSnapshot<PlayerUpdate>("player", () => {
496
- snapshotReceived = true;
497
- });
498
-
499
- // Send malformed data
500
- const badMessage = new Uint8Array([0x02, 99, 88, 77]); // Invalid snapshot
501
- expect(() => transport.simulateMessage(badMessage)).not.toThrow();
502
- expect(snapshotReceived).toBe(false);
503
- });
504
- });
505
-
506
- describe("Debug logging", () => {
507
- test("should not log when debug is false", () => {
508
- const logs: string[] = [];
509
- const originalLog = console.log;
510
- console.log = (...args: any[]) => logs.push(args.join(" "));
511
-
512
- const intent: MoveIntent = {
513
- kind: 1,
514
- tick: 1,
515
- dx: 1,
516
- dy: 1,
517
- };
518
- client.sendIntent(intent);
519
-
520
- console.log = originalLog;
521
- expect(logs.filter((l) => l.includes("[ClientNetwork]"))).toHaveLength(0);
522
- });
523
-
524
- test("should log when debug is true", () => {
525
- const logs: string[] = [];
526
- const originalLog = console.log;
527
- console.log = (...args: any[]) => logs.push(args.join(" "));
528
-
529
- const debugClient = new ClientNetwork<GameSnapshots>({
530
- transport: new MockTransportAdapter(),
531
- intentRegistry,
532
- snapshotRegistry,
533
- config: { debug: true },
534
- });
535
-
536
- const intent: MoveIntent = {
537
- kind: 1,
538
- tick: 1,
539
- dx: 1,
540
- dy: 1,
541
- };
542
- debugClient.sendIntent(intent);
543
-
544
- console.log = originalLog;
545
- expect(logs.filter((l) => l.includes("[ClientNetwork]")).length).toBeGreaterThan(0);
546
- });
547
- });
548
-
549
- describe("Memory pooling", () => {
550
- test("should reuse pooled objects across snapshots (zero-copy)", () => {
551
- const transport = new MockTransportAdapter();
552
- const client = new ClientNetwork<GameSnapshots>({
553
- transport,
554
- intentRegistry,
555
- snapshotRegistry,
556
- config: { debug: false },
557
- });
558
-
559
- // Extract data immediately (correct pattern for zero-copy)
560
- const extractedData: Array<{ tick: number; x: number; y: number; health: number }> = [];
561
-
562
- client.onSnapshot<PlayerUpdate>("player", (snapshot) => {
563
- // CORRECT: Extract data immediately, don't store references
564
- extractedData.push({
565
- tick: snapshot.tick,
566
- x: snapshot.updates.x!,
567
- y: snapshot.updates.y!,
568
- health: snapshot.updates.health!,
569
- });
570
- });
571
-
572
- // Simulate opening connection
573
- if (transport.openHandler) transport.openHandler();
574
-
575
- // Send first snapshot (wrap with MessageType.SNAPSHOT header)
576
- const snapshot1Data = snapshotRegistry.encode("player", {
577
- tick: 1,
578
- updates: { x: 10, y: 20, health: 100 },
579
- });
580
- const snapshot1 = new Uint8Array(1 + snapshot1Data.byteLength);
581
- snapshot1[0] = MessageType.SNAPSHOT;
582
- snapshot1.set(snapshot1Data, 1);
583
- if (transport.messageHandler) transport.messageHandler(snapshot1);
584
-
585
- // Send second snapshot with different data
586
- const snapshot2Data = snapshotRegistry.encode("player", {
587
- tick: 2,
588
- updates: { x: 15, y: 25, health: 90 },
589
- });
590
- const snapshot2 = new Uint8Array(1 + snapshot2Data.byteLength);
591
- snapshot2[0] = MessageType.SNAPSHOT;
592
- snapshot2.set(snapshot2Data, 1);
593
- if (transport.messageHandler) transport.messageHandler(snapshot2);
594
-
595
- // Verify both snapshots were received correctly
596
- expect(extractedData.length).toBe(2);
597
-
598
- // First snapshot data should be correct
599
- expect(extractedData[0].tick).toBe(1);
600
- expect(extractedData[0].x).toBe(10);
601
- expect(extractedData[0].y).toBe(20);
602
- expect(extractedData[0].health).toBe(100);
603
-
604
- // Second snapshot data should be correct
605
- expect(extractedData[1].tick).toBe(2);
606
- expect(extractedData[1].x).toBe(15);
607
- expect(extractedData[1].y).toBe(25);
608
- expect(extractedData[1].health).toBe(90);
609
- });
610
-
611
- test("handlers must extract data immediately (zero-copy pattern)", () => {
612
- const transport = new MockTransportAdapter();
613
- const client = new ClientNetwork<GameSnapshots>({
614
- transport,
615
- intentRegistry,
616
- snapshotRegistry,
617
- config: { debug: false },
618
- });
619
-
620
- // Simulate a reconciliator-like usage pattern (correct way)
621
- interface ExtractedState {
622
- x: number;
623
- y: number;
624
- health: number;
625
- }
626
- let extractedState: ExtractedState | null = null;
627
-
628
- client.onSnapshot<PlayerUpdate>("player", (snapshot) => {
629
- // CORRECT: Extract data immediately instead of storing references
630
- extractedState = {
631
- x: snapshot.updates.x!,
632
- y: snapshot.updates.y!,
633
- health: snapshot.updates.health!,
634
- };
635
- });
636
-
637
- // Simulate opening connection
638
- if (transport.openHandler) transport.openHandler();
639
-
640
- // Send first snapshot (wrap with MessageType.SNAPSHOT header)
641
- const snapshot1Data = snapshotRegistry.encode("player", {
642
- tick: 1,
643
- updates: { x: 10, y: 20, health: 100 },
644
- });
645
- const snapshot1 = new Uint8Array(1 + snapshot1Data.byteLength);
646
- snapshot1[0] = MessageType.SNAPSHOT;
647
- snapshot1.set(snapshot1Data, 1);
648
- if (transport.messageHandler) transport.messageHandler(snapshot1);
649
-
650
- const firstState = extractedState!;
651
- expect(firstState.x).toBe(10);
652
- expect(firstState.y).toBe(20);
653
- expect(firstState.health).toBe(100);
654
-
655
- // Send second snapshot (wrap with MessageType.SNAPSHOT header)
656
- const snapshot2Data = snapshotRegistry.encode("player", {
657
- tick: 2,
658
- updates: { x: 99, y: 99, health: 50 },
659
- });
660
- const snapshot2 = new Uint8Array(1 + snapshot2Data.byteLength);
661
- snapshot2[0] = MessageType.SNAPSHOT;
662
- snapshot2.set(snapshot2Data, 1);
663
- if (transport.messageHandler) transport.messageHandler(snapshot2);
664
-
665
- // First extracted state should NOT be mutated (we extracted primitives)
666
- expect(firstState.x).toBe(10);
667
- expect(firstState.y).toBe(20);
668
- expect(firstState.health).toBe(100);
669
-
670
- // New extracted state should have the new values
671
- expect(extractedState!.x).toBe(99);
672
- expect(extractedState!.y).toBe(99);
673
- expect(extractedState!.health).toBe(50);
674
- });
675
- });
676
-
677
- describe("RPC Memory pooling", () => {
678
- // Define RPC for testing
679
- const TestRPC = defineRPC({
680
- method: "testRpc",
681
- schema: {
682
- value: BinaryPrimitives.u32,
683
- message: BinaryPrimitives.string(32),
684
- },
685
- });
686
-
687
- interface TestRPCData {
688
- value: number;
689
- message: string;
690
- }
691
-
692
- test("should reuse pooled objects across RPC calls", () => {
693
- const rpcRegistry = new RpcRegistry();
694
- rpcRegistry.register(TestRPC);
695
-
696
- const transport = new MockTransportAdapter();
697
- const client = new ClientNetwork<GameSnapshots>({
698
- transport,
699
- intentRegistry,
700
- snapshotRegistry,
701
- rpcRegistry,
702
- config: { debug: false },
703
- });
704
-
705
- const receivedRpcs: Array<TestRPCData> = [];
706
-
707
- client.onRPC(TestRPC, (data) => {
708
- // Store the RPC data - this should be safe due to shallow copy
709
- receivedRpcs.push(data);
710
- });
711
-
712
- // Simulate opening connection
713
- if (transport.openHandler) transport.openHandler();
714
-
715
- // Send first RPC
716
- const rpc1Data = rpcRegistry.encode(TestRPC, {
717
- value: 100,
718
- message: "first",
719
- });
720
- const rpc1 = new Uint8Array(1 + rpc1Data.byteLength);
721
- rpc1[0] = MessageType.CUSTOM;
722
- rpc1.set(rpc1Data, 1);
723
- if (transport.messageHandler) transport.messageHandler(rpc1);
724
-
725
- // Send second RPC with different data
726
- const rpc2Data = rpcRegistry.encode(TestRPC, {
727
- value: 200,
728
- message: "second",
729
- });
730
- const rpc2 = new Uint8Array(1 + rpc2Data.byteLength);
731
- rpc2[0] = MessageType.CUSTOM;
732
- rpc2.set(rpc2Data, 1);
733
- if (transport.messageHandler) transport.messageHandler(rpc2);
734
-
735
- // Verify both RPCs were received correctly
736
- expect(receivedRpcs.length).toBe(2);
737
-
738
- // First RPC should maintain its original values
739
- expect(receivedRpcs[0].value).toBe(100);
740
- expect(receivedRpcs[0].message).toBe("first");
741
-
742
- // Second RPC should have its own values
743
- expect(receivedRpcs[1].value).toBe(200);
744
- expect(receivedRpcs[1].message).toBe("second");
745
-
746
- // The data objects should be different references (shallow copy worked)
747
- expect(receivedRpcs[0]).not.toBe(receivedRpcs[1]);
748
- });
749
-
750
- test("handlers can safely store references to RPC data", () => {
751
- const rpcRegistry = new RpcRegistry();
752
- rpcRegistry.register(TestRPC);
753
-
754
- const transport = new MockTransportAdapter();
755
- const client = new ClientNetwork<GameSnapshots>({
756
- transport,
757
- intentRegistry,
758
- snapshotRegistry,
759
- rpcRegistry,
760
- config: { debug: false },
761
- });
762
-
763
- // Simulate storing RPC data (common pattern)
764
- let storedData: TestRPCData | null = null;
765
-
766
- client.onRPC(TestRPC, (data) => {
767
- // Store the data directly
768
- storedData = data;
769
- });
770
-
771
- // Simulate opening connection
772
- if (transport.openHandler) transport.openHandler();
773
-
774
- // Send first RPC
775
- const rpc1Data = rpcRegistry.encode(TestRPC, {
776
- value: 42,
777
- message: "hello",
778
- });
779
- const rpc1 = new Uint8Array(1 + rpc1Data.byteLength);
780
- rpc1[0] = MessageType.CUSTOM;
781
- rpc1.set(rpc1Data, 1);
782
- if (transport.messageHandler) transport.messageHandler(rpc1);
783
-
784
- const firstData = storedData;
785
- expect((firstData as unknown as TestRPCData)?.value).toBe(42);
786
- expect((firstData as unknown as TestRPCData)?.message).toBe("hello");
787
-
788
- // Send second RPC
789
- const rpc2Data = rpcRegistry.encode(TestRPC, {
790
- value: 999,
791
- message: "world",
792
- });
793
- const rpc2 = new Uint8Array(1 + rpc2Data.byteLength);
794
- rpc2[0] = MessageType.CUSTOM;
795
- rpc2.set(rpc2Data, 1);
796
- if (transport.messageHandler) transport.messageHandler(rpc2);
797
-
798
- // First stored data should NOT be mutated by the second RPC
799
- expect((firstData as unknown as TestRPCData)?.value).toBe(42);
800
- expect((firstData as unknown as TestRPCData)?.message).toBe("hello");
801
-
802
- // New stored data should have the new values
803
- expect((storedData as unknown as TestRPCData)?.value).toBe(999);
804
- expect((storedData as unknown as TestRPCData)?.message).toBe("world");
805
- });
806
- });
807
- });