murow 0.0.70 → 0.0.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (439) hide show
  1. package/README.md +52 -37
  2. package/dist/cjs/core/binary-codec/binary-codec.js +1 -0
  3. package/dist/cjs/core/binary-codec/index.js +1 -0
  4. package/dist/cjs/core/driver/driver.js +1 -0
  5. package/dist/cjs/core/driver/drivers/immediate.js +1 -0
  6. package/dist/cjs/core/driver/drivers/index.js +1 -0
  7. package/dist/cjs/core/driver/drivers/raf.js +1 -0
  8. package/dist/cjs/core/driver/drivers/timeout.js +1 -0
  9. package/dist/cjs/core/driver/index.js +1 -0
  10. package/dist/cjs/core/events/event-system.js +1 -0
  11. package/dist/cjs/core/events/index.js +1 -0
  12. package/dist/cjs/core/fixed-ticker/fixed-ticker.js +1 -0
  13. package/dist/cjs/core/fixed-ticker/index.js +1 -0
  14. package/dist/cjs/core/free-list/free-list.js +1 -0
  15. package/dist/cjs/core/free-list/index.js +1 -0
  16. package/dist/cjs/core/generate-id/generate-id.js +1 -0
  17. package/dist/cjs/core/generate-id/index.js +1 -0
  18. package/dist/cjs/core/index.js +1 -0
  19. package/dist/cjs/core/input/index.js +1 -0
  20. package/dist/cjs/core/input/manager.js +1 -0
  21. package/dist/cjs/core/input/sources/browser.js +1 -0
  22. package/dist/cjs/core/input/sources/index.js +1 -0
  23. package/dist/cjs/core/input/types.js +1 -0
  24. package/dist/cjs/core/lerp/index.js +1 -0
  25. package/dist/cjs/core/lerp/lerp.js +1 -0
  26. package/dist/cjs/core/navmesh/index.js +1 -0
  27. package/dist/cjs/core/navmesh/navmesh-worker-pool.js +1 -0
  28. package/dist/cjs/core/navmesh/navmesh.js +1 -0
  29. package/dist/cjs/core/navmesh/navmesh.worker.js +1 -0
  30. package/dist/cjs/core/pooled-codec/index.js +1 -0
  31. package/dist/cjs/core/pooled-codec/pooled-codec.js +1 -0
  32. package/dist/cjs/core/prediction/index.js +1 -0
  33. package/dist/cjs/core/prediction/prediction.js +1 -0
  34. package/dist/cjs/core/ray/index.js +1 -0
  35. package/dist/cjs/core/ray/ray-2d.js +1 -0
  36. package/dist/cjs/core/ray/ray-3d.js +1 -0
  37. package/dist/cjs/core/simple-rng/index.js +1 -0
  38. package/dist/cjs/core/simple-rng/simple-rng.js +1 -0
  39. package/dist/cjs/core/sparse-batcher/index.js +1 -0
  40. package/dist/cjs/core/sparse-batcher/sparse-batcher.js +1 -0
  41. package/dist/cjs/ecs/component-store.js +1 -0
  42. package/dist/cjs/ecs/component.js +1 -0
  43. package/dist/cjs/ecs/entity-handle.js +1 -0
  44. package/dist/cjs/ecs/index.js +1 -0
  45. package/dist/cjs/ecs/system-builder.js +1 -0
  46. package/dist/cjs/ecs/world-systems.js +1 -0
  47. package/dist/cjs/ecs/world.js +1 -0
  48. package/dist/cjs/game/index.js +1 -0
  49. package/dist/cjs/game/loop/index.js +1 -0
  50. package/dist/cjs/game/loop/loop.js +1 -0
  51. package/dist/cjs/index.js +1 -0
  52. package/dist/cjs/net/adapters/browser-websocket.js +1 -0
  53. package/dist/cjs/net/adapters/bun-websocket.js +1 -0
  54. package/dist/cjs/net/buffer-pool.js +1 -0
  55. package/dist/cjs/net/client.js +1 -0
  56. package/dist/cjs/net/index.js +1 -0
  57. package/dist/cjs/net/server.js +1 -0
  58. package/dist/cjs/net/types.js +1 -0
  59. package/dist/cjs/net/validators.js +1 -0
  60. package/dist/cjs/protocol/index.js +1 -0
  61. package/dist/cjs/protocol/intent/define-intent.js +1 -0
  62. package/dist/cjs/protocol/intent/index.js +1 -0
  63. package/dist/cjs/protocol/intent/intent-registry.js +1 -0
  64. package/dist/cjs/protocol/intent/intent.js +1 -0
  65. package/dist/cjs/protocol/rpc/define-rpc.js +1 -0
  66. package/dist/cjs/protocol/rpc/index.js +1 -0
  67. package/dist/cjs/protocol/rpc/rpc-registry.js +1 -0
  68. package/dist/cjs/protocol/rpc/rpc.js +1 -0
  69. package/dist/cjs/protocol/snapshot/index.js +1 -0
  70. package/dist/cjs/protocol/snapshot/snapshot-codec.js +1 -0
  71. package/dist/cjs/protocol/snapshot/snapshot-registry.js +1 -0
  72. package/dist/cjs/protocol/snapshot/snapshot.js +1 -0
  73. package/dist/cjs/renderer/base-2d-renderer.js +1 -0
  74. package/dist/cjs/renderer/base-3d-renderer.js +1 -0
  75. package/dist/cjs/renderer/base-renderer.js +1 -0
  76. package/dist/cjs/renderer/index.js +1 -0
  77. package/dist/cjs/renderer/types.js +1 -0
  78. package/dist/esm/core/binary-codec/binary-codec.js +1 -0
  79. package/dist/esm/core/binary-codec/index.js +1 -0
  80. package/dist/esm/core/driver/driver.js +1 -0
  81. package/dist/esm/core/driver/drivers/immediate.js +1 -0
  82. package/dist/esm/core/driver/drivers/index.js +1 -0
  83. package/dist/esm/core/driver/drivers/raf.js +1 -0
  84. package/dist/esm/core/driver/drivers/timeout.js +1 -0
  85. package/dist/esm/core/driver/index.js +1 -0
  86. package/dist/esm/core/events/event-system.js +1 -0
  87. package/dist/esm/core/events/index.js +1 -0
  88. package/dist/esm/core/fixed-ticker/fixed-ticker.js +1 -0
  89. package/dist/esm/core/fixed-ticker/index.js +1 -0
  90. package/dist/esm/core/free-list/free-list.js +1 -0
  91. package/dist/esm/core/free-list/index.js +1 -0
  92. package/dist/esm/core/generate-id/generate-id.js +1 -0
  93. package/dist/esm/core/generate-id/index.js +1 -0
  94. package/dist/esm/core/index.js +1 -0
  95. package/dist/esm/core/input/index.js +1 -0
  96. package/dist/esm/core/input/manager.js +1 -0
  97. package/dist/esm/core/input/sources/browser.js +1 -0
  98. package/dist/esm/core/input/sources/index.js +1 -0
  99. package/dist/esm/core/input/types.js +0 -0
  100. package/dist/esm/core/lerp/index.js +1 -0
  101. package/dist/esm/core/lerp/lerp.js +1 -0
  102. package/dist/esm/core/navmesh/index.js +1 -0
  103. package/dist/esm/core/navmesh/navmesh-worker-pool.js +1 -0
  104. package/dist/esm/core/navmesh/navmesh.js +1 -0
  105. package/dist/esm/core/navmesh/navmesh.worker.js +1 -0
  106. package/dist/esm/core/pooled-codec/index.js +1 -0
  107. package/dist/esm/core/pooled-codec/pooled-codec.js +1 -0
  108. package/dist/esm/core/prediction/index.js +1 -0
  109. package/dist/esm/core/prediction/prediction.js +1 -0
  110. package/dist/esm/core/ray/index.js +1 -0
  111. package/dist/esm/core/ray/ray-2d.js +1 -0
  112. package/dist/esm/core/ray/ray-3d.js +1 -0
  113. package/dist/esm/core/simple-rng/index.js +1 -0
  114. package/dist/esm/core/simple-rng/simple-rng.js +1 -0
  115. package/dist/esm/core/sparse-batcher/index.js +1 -0
  116. package/dist/esm/core/sparse-batcher/sparse-batcher.js +1 -0
  117. package/dist/esm/ecs/component-store.js +1 -0
  118. package/dist/esm/ecs/component.js +1 -0
  119. package/dist/esm/ecs/entity-handle.js +1 -0
  120. package/dist/esm/ecs/index.js +1 -0
  121. package/dist/esm/ecs/system-builder.js +1 -0
  122. package/dist/esm/ecs/world-systems.js +1 -0
  123. package/dist/esm/ecs/world.js +1 -0
  124. package/dist/esm/game/index.js +1 -0
  125. package/dist/esm/game/loop/index.js +1 -0
  126. package/dist/esm/game/loop/loop.js +1 -0
  127. package/dist/esm/index.js +1 -0
  128. package/dist/esm/net/adapters/browser-websocket.js +1 -0
  129. package/dist/esm/net/adapters/bun-websocket.js +1 -0
  130. package/dist/esm/net/buffer-pool.js +1 -0
  131. package/dist/esm/net/client.js +1 -0
  132. package/dist/esm/net/index.js +1 -0
  133. package/dist/esm/net/server.js +1 -0
  134. package/dist/esm/net/types.js +1 -0
  135. package/dist/esm/net/validators.js +1 -0
  136. package/dist/esm/protocol/index.js +1 -0
  137. package/dist/esm/protocol/intent/define-intent.js +1 -0
  138. package/dist/esm/protocol/intent/index.js +1 -0
  139. package/dist/esm/protocol/intent/intent-registry.js +1 -0
  140. package/dist/esm/protocol/intent/intent.js +0 -0
  141. package/dist/esm/protocol/rpc/define-rpc.js +1 -0
  142. package/dist/esm/protocol/rpc/index.js +1 -0
  143. package/dist/esm/protocol/rpc/rpc-registry.js +1 -0
  144. package/dist/esm/protocol/rpc/rpc.js +0 -0
  145. package/dist/esm/protocol/snapshot/index.js +1 -0
  146. package/dist/esm/protocol/snapshot/snapshot-codec.js +1 -0
  147. package/dist/esm/protocol/snapshot/snapshot-registry.js +1 -0
  148. package/dist/esm/protocol/snapshot/snapshot.js +1 -0
  149. package/dist/esm/renderer/base-2d-renderer.js +1 -0
  150. package/dist/esm/renderer/base-3d-renderer.js +1 -0
  151. package/dist/esm/renderer/base-renderer.js +1 -0
  152. package/dist/esm/renderer/index.js +1 -0
  153. package/dist/esm/renderer/types.js +0 -0
  154. package/dist/{core → types/core}/binary-codec/binary-codec.d.ts +4 -0
  155. package/dist/{core → types/core}/events/event-system.d.ts +14 -33
  156. package/dist/types/core/free-list/free-list.d.ts +31 -0
  157. package/dist/types/core/free-list/index.d.ts +1 -0
  158. package/dist/{core → types/core}/index.d.ts +5 -0
  159. package/dist/{core → types/core}/input/index.d.ts +1 -0
  160. package/dist/{core → types/core}/input/manager.d.ts +2 -0
  161. package/dist/{core → types/core}/navmesh/navmesh.d.ts +1 -21
  162. package/dist/types/core/ray/index.d.ts +2 -0
  163. package/dist/types/core/ray/ray-2d.d.ts +37 -0
  164. package/dist/types/core/ray/ray-3d.d.ts +42 -0
  165. package/dist/types/core/simple-rng/index.d.ts +1 -0
  166. package/dist/types/core/simple-rng/simple-rng.d.ts +36 -0
  167. package/dist/types/core/sparse-batcher/index.d.ts +1 -0
  168. package/dist/types/core/sparse-batcher/sparse-batcher.d.ts +55 -0
  169. package/dist/{ecs → types/ecs}/world.d.ts +11 -0
  170. package/dist/{game → types/game}/loop/loop.d.ts +33 -29
  171. package/dist/{index.d.ts → types/index.d.ts} +1 -0
  172. package/dist/{net → types/net}/index.d.ts +2 -2
  173. package/dist/types/renderer/base-2d-renderer.d.ts +13 -0
  174. package/dist/types/renderer/base-3d-renderer.d.ts +10 -0
  175. package/dist/types/renderer/base-renderer.d.ts +21 -0
  176. package/dist/types/renderer/index.d.ts +4 -0
  177. package/dist/types/renderer/types.d.ts +79 -0
  178. package/dist/webgpu/cjs/index.js +6004 -0
  179. package/dist/webgpu/esm/index.js +5972 -0
  180. package/dist/webgpu/types/2d/animation.d.ts +97 -0
  181. package/dist/webgpu/types/2d/renderer.d.ts +55 -0
  182. package/dist/webgpu/types/2d/shader.d.ts +61 -0
  183. package/dist/webgpu/types/2d/sprite-accessor.d.ts +47 -0
  184. package/dist/webgpu/types/3d/gltf-skin-parser.d.ts +101 -0
  185. package/dist/webgpu/types/3d/morph-animation.d.ts +69 -0
  186. package/dist/webgpu/types/3d/morph-animation.test.d.ts +1 -0
  187. package/dist/webgpu/types/3d/renderer.d.ts +216 -0
  188. package/dist/webgpu/types/3d/shader.d.ts +136 -0
  189. package/dist/webgpu/types/3d/skeletal-animation-compute/index.d.ts +2 -0
  190. package/dist/webgpu/types/3d/skeletal-animation-compute/kernel.d.ts +8 -0
  191. package/dist/webgpu/types/3d/skeletal-animation-compute/packer.d.ts +32 -0
  192. package/dist/webgpu/types/3d/skeletal-animation.d.ts +90 -0
  193. package/dist/webgpu/types/camera/camera-2d.d.ts +53 -0
  194. package/dist/webgpu/types/camera/camera-2d.test.d.ts +1 -0
  195. package/dist/webgpu/types/camera/camera-3d.d.ts +81 -0
  196. package/dist/webgpu/types/camera/camera-3d.test.d.ts +1 -0
  197. package/dist/webgpu/types/camera/index.d.ts +2 -0
  198. package/dist/webgpu/types/compute/compute-builder.d.ts +123 -0
  199. package/dist/webgpu/types/compute/compute-builder.test.d.ts +1 -0
  200. package/dist/webgpu/types/core/constants.d.ts +59 -0
  201. package/dist/webgpu/types/core/constants.test.d.ts +1 -0
  202. package/dist/webgpu/types/core/index.d.ts +2 -0
  203. package/dist/webgpu/types/core/math.d.ts +37 -0
  204. package/dist/webgpu/types/core/types.d.ts +125 -0
  205. package/dist/webgpu/types/core/types.test.d.ts +1 -0
  206. package/dist/webgpu/types/geometry/built-in.d.ts +58 -0
  207. package/dist/webgpu/types/geometry/built-in.test.d.ts +1 -0
  208. package/dist/webgpu/types/geometry/geometry-builder.d.ts +281 -0
  209. package/dist/webgpu/types/geometry/geometry-builder.test.d.ts +1 -0
  210. package/dist/webgpu/types/geometry/index.d.ts +2 -0
  211. package/dist/webgpu/types/index.d.ts +32 -0
  212. package/dist/webgpu/types/particle/emitter.d.ts +36 -0
  213. package/dist/webgpu/types/shaders/index.d.ts +2 -0
  214. package/dist/webgpu/types/shaders/runtime-transpile.d.ts +18 -0
  215. package/dist/webgpu/types/shaders/sprite-2d.wgsl.d.ts +10 -0
  216. package/dist/webgpu/types/shaders/typegpu.d.ts +9 -0
  217. package/dist/webgpu/types/shaders/utils.d.ts +28 -0
  218. package/dist/webgpu/types/shaders/utils.test.d.ts +1 -0
  219. package/dist/webgpu/types/spritesheet/index.d.ts +1 -0
  220. package/dist/webgpu/types/spritesheet/spritesheet.d.ts +57 -0
  221. package/dist/webgpu/types/spritesheet/spritesheet.test.d.ts +1 -0
  222. package/package.json +96 -26
  223. package/dist/core/binary-codec/binary-codec.js +0 -354
  224. package/dist/core/binary-codec/index.js +0 -1
  225. package/dist/core/driver/driver.js +0 -47
  226. package/dist/core/driver/drivers/immediate.js +0 -61
  227. package/dist/core/driver/drivers/index.js +0 -3
  228. package/dist/core/driver/drivers/raf.js +0 -62
  229. package/dist/core/driver/drivers/timeout.js +0 -71
  230. package/dist/core/driver/index.js +0 -2
  231. package/dist/core/events/event-system.js +0 -88
  232. package/dist/core/events/index.js +0 -1
  233. package/dist/core/fixed-ticker/fixed-ticker.js +0 -105
  234. package/dist/core/fixed-ticker/index.js +0 -1
  235. package/dist/core/generate-id/generate-id.js +0 -25
  236. package/dist/core/generate-id/index.js +0 -1
  237. package/dist/core/index.js +0 -10
  238. package/dist/core/input/index.js +0 -2
  239. package/dist/core/input/manager.js +0 -211
  240. package/dist/core/input/sources/browser.js +0 -29
  241. package/dist/core/input/sources/index.js +0 -1
  242. package/dist/core/lerp/index.js +0 -1
  243. package/dist/core/lerp/lerp.js +0 -42
  244. package/dist/core/navmesh/index.js +0 -1
  245. package/dist/core/navmesh/navmesh-worker-pool.js +0 -180
  246. package/dist/core/navmesh/navmesh.js +0 -799
  247. package/dist/core/navmesh/navmesh.worker.js +0 -79
  248. package/dist/core/pooled-codec/index.js +0 -1
  249. package/dist/core/pooled-codec/pooled-codec.js +0 -410
  250. package/dist/core/prediction/index.js +0 -1
  251. package/dist/core/prediction/prediction.js +0 -99
  252. package/dist/core.esm.js +0 -1
  253. package/dist/core.js +0 -1
  254. package/dist/ecs/component-store.js +0 -175
  255. package/dist/ecs/component.js +0 -43
  256. package/dist/ecs/entity-handle.js +0 -515
  257. package/dist/ecs/example.js +0 -125
  258. package/dist/ecs/index.js +0 -4
  259. package/dist/ecs/system-builder.js +0 -249
  260. package/dist/ecs/world-systems.js +0 -79
  261. package/dist/ecs/world.js +0 -767
  262. package/dist/game/index.js +0 -1
  263. package/dist/game/loop/index.js +0 -1
  264. package/dist/game/loop/loop.js +0 -108
  265. package/dist/index.js +0 -26
  266. package/dist/net/adapters/browser-websocket.js +0 -74
  267. package/dist/net/adapters/bun-websocket.js +0 -245
  268. package/dist/net/buffer-pool.js +0 -89
  269. package/dist/net/client.js +0 -586
  270. package/dist/net/index.js +0 -58
  271. package/dist/net/server.js +0 -974
  272. package/dist/net/types.js +0 -31
  273. package/dist/net/validators.js +0 -88
  274. package/dist/protocol/index.js +0 -92
  275. package/dist/protocol/intent/define-intent.js +0 -125
  276. package/dist/protocol/intent/index.js +0 -91
  277. package/dist/protocol/intent/intent-registry.js +0 -91
  278. package/dist/protocol/rpc/define-rpc.js +0 -84
  279. package/dist/protocol/rpc/index.js +0 -3
  280. package/dist/protocol/rpc/rpc-registry.js +0 -159
  281. package/dist/protocol/rpc/rpc.js +0 -12
  282. package/dist/protocol/snapshot/index.js +0 -43
  283. package/dist/protocol/snapshot/snapshot-codec.js +0 -67
  284. package/dist/protocol/snapshot/snapshot-registry.js +0 -168
  285. package/dist/protocol/snapshot/snapshot.js +0 -30
  286. package/src/core/binary-codec/README.md +0 -60
  287. package/src/core/binary-codec/binary-codec.test.ts +0 -300
  288. package/src/core/binary-codec/binary-codec.ts +0 -448
  289. package/src/core/binary-codec/index.ts +0 -1
  290. package/src/core/driver/README.md +0 -97
  291. package/src/core/driver/driver.test.ts +0 -414
  292. package/src/core/driver/driver.ts +0 -71
  293. package/src/core/driver/drivers/immediate.ts +0 -66
  294. package/src/core/driver/drivers/index.ts +0 -3
  295. package/src/core/driver/drivers/raf.ts +0 -67
  296. package/src/core/driver/drivers/timeout.ts +0 -77
  297. package/src/core/driver/index.ts +0 -2
  298. package/src/core/events/README.md +0 -47
  299. package/src/core/events/event-system.test.ts +0 -243
  300. package/src/core/events/event-system.ts +0 -140
  301. package/src/core/events/index.ts +0 -1
  302. package/src/core/fixed-ticker/README.md +0 -77
  303. package/src/core/fixed-ticker/fixed-ticker.test.ts +0 -151
  304. package/src/core/fixed-ticker/fixed-ticker.ts +0 -174
  305. package/src/core/fixed-ticker/index.ts +0 -1
  306. package/src/core/generate-id/README.md +0 -18
  307. package/src/core/generate-id/generate-id.test.ts +0 -79
  308. package/src/core/generate-id/generate-id.ts +0 -37
  309. package/src/core/generate-id/index.ts +0 -1
  310. package/src/core/index.ts +0 -10
  311. package/src/core/input/README.md +0 -24
  312. package/src/core/input/index.ts +0 -2
  313. package/src/core/input/manager.ts +0 -259
  314. package/src/core/input/sources/browser.ts +0 -39
  315. package/src/core/input/sources/index.ts +0 -1
  316. package/src/core/input/types.ts +0 -40
  317. package/src/core/lerp/README.md +0 -79
  318. package/src/core/lerp/index.ts +0 -1
  319. package/src/core/lerp/lerp.test.ts +0 -90
  320. package/src/core/lerp/lerp.ts +0 -42
  321. package/src/core/navmesh/README.md +0 -164
  322. package/src/core/navmesh/index.ts +0 -1
  323. package/src/core/navmesh/navmesh-worker-pool.ts +0 -236
  324. package/src/core/navmesh/navmesh-workers.test.ts +0 -356
  325. package/src/core/navmesh/navmesh.test.ts +0 -344
  326. package/src/core/navmesh/navmesh.ts +0 -1047
  327. package/src/core/navmesh/navmesh.worker.ts +0 -147
  328. package/src/core/pooled-codec/README.md +0 -70
  329. package/src/core/pooled-codec/index.ts +0 -1
  330. package/src/core/pooled-codec/pooled-codec.test.ts +0 -862
  331. package/src/core/pooled-codec/pooled-codec.ts +0 -504
  332. package/src/core/prediction/README.md +0 -64
  333. package/src/core/prediction/index.ts +0 -1
  334. package/src/core/prediction/prediction.test.ts +0 -423
  335. package/src/core/prediction/prediction.ts +0 -112
  336. package/src/ecs/README.md +0 -427
  337. package/src/ecs/benchmark.test.ts +0 -1645
  338. package/src/ecs/component-store.ts +0 -198
  339. package/src/ecs/component.ts +0 -90
  340. package/src/ecs/entity-handle.test.ts +0 -393
  341. package/src/ecs/entity-handle.ts +0 -563
  342. package/src/ecs/example.ts +0 -152
  343. package/src/ecs/index.ts +0 -4
  344. package/src/ecs/system-builder.ts +0 -404
  345. package/src/ecs/world-systems.ts +0 -83
  346. package/src/ecs/world.test.ts +0 -310
  347. package/src/ecs/world.ts +0 -904
  348. package/src/game/index.ts +0 -1
  349. package/src/game/loop/README.md +0 -32
  350. package/src/game/loop/index.ts +0 -1
  351. package/src/game/loop/loop.ts +0 -236
  352. package/src/index.ts +0 -32
  353. package/src/net/README.md +0 -474
  354. package/src/net/adapters/browser-websocket.ts +0 -86
  355. package/src/net/adapters/bun-websocket.ts +0 -292
  356. package/src/net/buffer-pool.ts +0 -106
  357. package/src/net/client.test.ts +0 -807
  358. package/src/net/client.ts +0 -695
  359. package/src/net/index.ts +0 -60
  360. package/src/net/server.test.ts +0 -799
  361. package/src/net/server.ts +0 -1152
  362. package/src/net/types.ts +0 -228
  363. package/src/net/validators.ts +0 -104
  364. package/src/protocol/README.md +0 -469
  365. package/src/protocol/index.ts +0 -93
  366. package/src/protocol/intent/define-intent.test.ts +0 -397
  367. package/src/protocol/intent/define-intent.ts +0 -201
  368. package/src/protocol/intent/index.ts +0 -94
  369. package/src/protocol/intent/intent-registry.test.ts +0 -198
  370. package/src/protocol/intent/intent-registry.ts +0 -112
  371. package/src/protocol/intent/intent.ts +0 -12
  372. package/src/protocol/rpc/define-rpc.test.ts +0 -141
  373. package/src/protocol/rpc/define-rpc.ts +0 -113
  374. package/src/protocol/rpc/index.ts +0 -3
  375. package/src/protocol/rpc/rpc-registry.test.ts +0 -168
  376. package/src/protocol/rpc/rpc-registry.ts +0 -176
  377. package/src/protocol/rpc/rpc.ts +0 -37
  378. package/src/protocol/snapshot/index.ts +0 -45
  379. package/src/protocol/snapshot/snapshot-codec.test.ts +0 -138
  380. package/src/protocol/snapshot/snapshot-codec.ts +0 -87
  381. package/src/protocol/snapshot/snapshot-registry.test.ts +0 -310
  382. package/src/protocol/snapshot/snapshot-registry.ts +0 -201
  383. package/src/protocol/snapshot/snapshot.test.ts +0 -76
  384. package/src/protocol/snapshot/snapshot.ts +0 -41
  385. /package/dist/{core → types/core}/binary-codec/index.d.ts +0 -0
  386. /package/dist/{core → types/core}/driver/driver.d.ts +0 -0
  387. /package/dist/{core → types/core}/driver/drivers/immediate.d.ts +0 -0
  388. /package/dist/{core → types/core}/driver/drivers/index.d.ts +0 -0
  389. /package/dist/{core → types/core}/driver/drivers/raf.d.ts +0 -0
  390. /package/dist/{core → types/core}/driver/drivers/timeout.d.ts +0 -0
  391. /package/dist/{core → types/core}/driver/index.d.ts +0 -0
  392. /package/dist/{core → types/core}/events/index.d.ts +0 -0
  393. /package/dist/{core → types/core}/fixed-ticker/fixed-ticker.d.ts +0 -0
  394. /package/dist/{core → types/core}/fixed-ticker/index.d.ts +0 -0
  395. /package/dist/{core → types/core}/generate-id/generate-id.d.ts +0 -0
  396. /package/dist/{core → types/core}/generate-id/index.d.ts +0 -0
  397. /package/dist/{core → types/core}/input/sources/browser.d.ts +0 -0
  398. /package/dist/{core → types/core}/input/sources/index.d.ts +0 -0
  399. /package/dist/{core → types/core}/input/types.d.ts +0 -0
  400. /package/dist/{core → types/core}/lerp/index.d.ts +0 -0
  401. /package/dist/{core → types/core}/lerp/lerp.d.ts +0 -0
  402. /package/dist/{core → types/core}/navmesh/index.d.ts +0 -0
  403. /package/dist/{core → types/core}/navmesh/navmesh-worker-pool.d.ts +0 -0
  404. /package/dist/{core → types/core}/navmesh/navmesh.worker.d.ts +0 -0
  405. /package/dist/{core → types/core}/pooled-codec/index.d.ts +0 -0
  406. /package/dist/{core → types/core}/pooled-codec/pooled-codec.d.ts +0 -0
  407. /package/dist/{core → types/core}/prediction/index.d.ts +0 -0
  408. /package/dist/{core → types/core}/prediction/prediction.d.ts +0 -0
  409. /package/dist/{ecs → types/ecs}/component-store.d.ts +0 -0
  410. /package/dist/{ecs → types/ecs}/component.d.ts +0 -0
  411. /package/dist/{ecs → types/ecs}/entity-handle.d.ts +0 -0
  412. /package/dist/{ecs → types/ecs}/example.d.ts +0 -0
  413. /package/dist/{ecs → types/ecs}/index.d.ts +0 -0
  414. /package/dist/{ecs → types/ecs}/system-builder.d.ts +0 -0
  415. /package/dist/{ecs → types/ecs}/world-systems.d.ts +0 -0
  416. /package/dist/{game → types/game}/index.d.ts +0 -0
  417. /package/dist/{game → types/game}/loop/index.d.ts +0 -0
  418. /package/dist/{net → types/net}/adapters/browser-websocket.d.ts +0 -0
  419. /package/dist/{net → types/net}/adapters/bun-websocket.d.ts +0 -0
  420. /package/dist/{net → types/net}/buffer-pool.d.ts +0 -0
  421. /package/dist/{net → types/net}/client.d.ts +0 -0
  422. /package/dist/{net → types/net}/server.d.ts +0 -0
  423. /package/dist/{net → types/net}/types.d.ts +0 -0
  424. /package/dist/{net → types/net}/validators.d.ts +0 -0
  425. /package/dist/{protocol → types/protocol}/index.d.ts +0 -0
  426. /package/dist/{protocol → types/protocol}/intent/define-intent.d.ts +0 -0
  427. /package/dist/{protocol → types/protocol}/intent/index.d.ts +0 -0
  428. /package/dist/{protocol → types/protocol}/intent/intent-registry.d.ts +0 -0
  429. /package/dist/{protocol → types/protocol}/intent/intent.d.ts +0 -0
  430. /package/dist/{protocol → types/protocol}/rpc/define-rpc.d.ts +0 -0
  431. /package/dist/{protocol → types/protocol}/rpc/index.d.ts +0 -0
  432. /package/dist/{protocol → types/protocol}/rpc/rpc-registry.d.ts +0 -0
  433. /package/dist/{protocol → types/protocol}/rpc/rpc.d.ts +0 -0
  434. /package/dist/{protocol → types/protocol}/snapshot/index.d.ts +0 -0
  435. /package/dist/{protocol → types/protocol}/snapshot/snapshot-codec.d.ts +0 -0
  436. /package/dist/{protocol → types/protocol}/snapshot/snapshot-registry.d.ts +0 -0
  437. /package/dist/{protocol → types/protocol}/snapshot/snapshot.d.ts +0 -0
  438. /package/dist/{core/input/types.js → webgpu/types/2d/animation.test.d.ts} +0 -0
  439. /package/dist/{protocol/intent/intent.js → webgpu/types/2d/sprite-accessor.test.d.ts} +0 -0
@@ -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
- });