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,799 +0,0 @@
1
- import { describe, expect, test, beforeEach } from "bun:test";
2
- import { ServerNetwork } from "./server";
3
- import { IntentRegistry } from "../protocol/intent/intent-registry";
4
- import { SnapshotRegistry } from "../protocol/snapshot/snapshot-registry";
5
- import { PooledCodec } from "../core/pooled-codec/pooled-codec";
6
- import { BinaryPrimitives } from "../core/binary-codec";
7
- import { defineIntent } from "../protocol/intent/define-intent";
8
- import type { TransportAdapter, ServerTransportAdapter } from "./types";
9
- import type { Snapshot } from "../protocol/snapshot/snapshot";
10
-
11
- // Define move intent using defineIntent
12
- const MoveIntent = defineIntent({
13
- kind: 1 as const,
14
- schema: {
15
- dx: BinaryPrimitives.f32,
16
- dy: BinaryPrimitives.f32,
17
- },
18
- });
19
-
20
- type MoveIntent = typeof MoveIntent.type;
21
-
22
- interface PlayerUpdate {
23
- x: number;
24
- y: number;
25
- health: number;
26
- }
27
-
28
- interface ScoreUpdate {
29
- score: number;
30
- }
31
-
32
- type GameSnapshots = PlayerUpdate | ScoreUpdate;
33
-
34
- // Mock peer transport
35
- class MockPeerTransport implements TransportAdapter {
36
- messageHandler: ((data: Uint8Array) => void) | null = null;
37
- private closeHandler: (() => void) | null = null;
38
- public sentMessages: Uint8Array[] = [];
39
- public closed = false;
40
-
41
- send(data: Uint8Array): void {
42
- this.sentMessages.push(new Uint8Array(data)); // Copy to avoid mutation
43
- }
44
-
45
- onMessage(handler: (data: Uint8Array) => void): void {
46
- this.messageHandler = handler;
47
- }
48
-
49
- onClose(handler: () => void): void {
50
- this.closeHandler = handler;
51
- }
52
-
53
- close(): void {
54
- this.closed = true;
55
- if (this.closeHandler) {
56
- this.closeHandler();
57
- }
58
- }
59
-
60
- // Test helper: simulate receiving a message
61
- simulateMessage(data: Uint8Array): void {
62
- if (this.messageHandler) {
63
- this.messageHandler(data);
64
- }
65
- }
66
- }
67
-
68
- // Mock server transport
69
- class MockServerTransport implements ServerTransportAdapter<MockPeerTransport> {
70
- private connectionHandler: ((peer: MockPeerTransport, peerId: string) => void) | null = null;
71
- private disconnectionHandler: ((peerId: string) => void) | null = null;
72
- private peers = new Map<string, MockPeerTransport>();
73
- public closed = false;
74
-
75
- onConnection(handler: (peer: MockPeerTransport, peerId: string) => void): void {
76
- this.connectionHandler = handler;
77
- }
78
-
79
- onDisconnection(handler: (peerId: string) => void): void {
80
- this.disconnectionHandler = handler;
81
- }
82
-
83
- getPeer(peerId: string): MockPeerTransport | undefined {
84
- return this.peers.get(peerId);
85
- }
86
-
87
- getPeerIds(): string[] {
88
- return Array.from(this.peers.keys());
89
- }
90
-
91
- close(): void {
92
- this.closed = true;
93
- }
94
-
95
- // Test helpers
96
- simulateConnection(peerId: string): MockPeerTransport {
97
- const peer = new MockPeerTransport();
98
- this.peers.set(peerId, peer);
99
- if (this.connectionHandler) {
100
- this.connectionHandler(peer, peerId);
101
- }
102
- return peer;
103
- }
104
-
105
- simulateDisconnection(peerId: string): void {
106
- this.peers.delete(peerId);
107
- if (this.disconnectionHandler) {
108
- this.disconnectionHandler(peerId);
109
- }
110
- }
111
- }
112
-
113
- describe("ServerNetwork", () => {
114
- let transport: MockServerTransport;
115
- let intentRegistry: IntentRegistry;
116
- let server: ServerNetwork<MockPeerTransport, GameSnapshots>;
117
-
118
- beforeEach(() => {
119
- transport = new MockServerTransport();
120
- intentRegistry = new IntentRegistry();
121
-
122
- // Register move intent
123
- intentRegistry.register(MoveIntent);
124
-
125
- server = new ServerNetwork<MockPeerTransport, GameSnapshots>({
126
- transport,
127
- intentRegistry,
128
- createPeerSnapshotRegistry: () => {
129
- const registry = new SnapshotRegistry<GameSnapshots>();
130
-
131
- const playerCodec = new PooledCodec({
132
- x: BinaryPrimitives.f32,
133
- y: BinaryPrimitives.f32,
134
- health: BinaryPrimitives.u8,
135
- });
136
- registry.register("player", playerCodec);
137
-
138
- const scoreCodec = new PooledCodec({
139
- score: BinaryPrimitives.u32,
140
- });
141
- registry.register("score", scoreCodec);
142
-
143
- return registry;
144
- },
145
- config: { debug: false },
146
- });
147
- });
148
-
149
- describe("Peer connection lifecycle", () => {
150
- test("should handle new peer connection", () => {
151
- const peer = transport.simulateConnection("peer1");
152
-
153
- expect(server.getPeerIds()).toEqual(["peer1"]);
154
- expect(server.getPeerState("peer1")).toBeDefined();
155
- expect(server.getPeerSnapshotRegistry("peer1")).toBeDefined();
156
- });
157
-
158
- test("should create peer-specific snapshot registry", () => {
159
- transport.simulateConnection("peer1");
160
- transport.simulateConnection("peer2");
161
-
162
- const registry1 = server.getPeerSnapshotRegistry("peer1");
163
- const registry2 = server.getPeerSnapshotRegistry("peer2");
164
-
165
- expect(registry1).toBeDefined();
166
- expect(registry2).toBeDefined();
167
- expect(registry1).not.toBe(registry2); // Each peer has own registry
168
- });
169
-
170
- test("should trigger onConnection handlers", () => {
171
- const connectedPeers: string[] = [];
172
- server.onConnection((peerId) => {
173
- connectedPeers.push(peerId);
174
- });
175
-
176
- transport.simulateConnection("peer1");
177
- transport.simulateConnection("peer2");
178
-
179
- expect(connectedPeers).toEqual(["peer1", "peer2"]);
180
- });
181
-
182
- test("should setup message handler for peer", () => {
183
- const peer = transport.simulateConnection("peer1");
184
- expect(peer.messageHandler).not.toBeNull();
185
- });
186
-
187
- test("should initialize peer state correctly", () => {
188
- transport.simulateConnection("peer1");
189
- const state = server.getPeerState("peer1");
190
-
191
- expect(state).toBeDefined();
192
- expect(state!.peerId).toBe("peer1");
193
- expect(state!.lastSentTick).toBe(0);
194
- expect(state!.connectedAt).toBeGreaterThan(0);
195
- expect(state!.metadata).toEqual({});
196
- });
197
-
198
- test("should handle peer disconnection", () => {
199
- transport.simulateConnection("peer1");
200
- expect(server.getPeerIds()).toHaveLength(1);
201
-
202
- transport.simulateDisconnection("peer1");
203
- expect(server.getPeerIds()).toHaveLength(0);
204
- expect(server.getPeerState("peer1")).toBeUndefined();
205
- expect(server.getPeerSnapshotRegistry("peer1")).toBeUndefined();
206
- });
207
-
208
- test("should trigger onDisconnection handlers", () => {
209
- const disconnectedPeers: string[] = [];
210
- server.onDisconnection((peerId) => {
211
- disconnectedPeers.push(peerId);
212
- });
213
-
214
- transport.simulateConnection("peer1");
215
- transport.simulateConnection("peer2");
216
- transport.simulateDisconnection("peer1");
217
-
218
- expect(disconnectedPeers).toEqual(["peer1"]);
219
- expect(server.getPeerIds()).toEqual(["peer2"]);
220
- });
221
-
222
- test("should handle multiple connection/disconnection handlers", () => {
223
- let connectCount = 0;
224
- let disconnectCount = 0;
225
-
226
- server.onConnection(() => connectCount++);
227
- server.onConnection(() => connectCount++);
228
- server.onDisconnection(() => disconnectCount++);
229
- server.onDisconnection(() => disconnectCount++);
230
-
231
- transport.simulateConnection("peer1");
232
- transport.simulateDisconnection("peer1");
233
-
234
- expect(connectCount).toBe(2);
235
- expect(disconnectCount).toBe(2);
236
- });
237
- });
238
-
239
- describe("Intent handling", () => {
240
- test("should receive and decode intent from peer", () => {
241
- const receivedIntents: Array<{ peerId: string; intent: MoveIntent }> = [];
242
- server.onIntent<MoveIntent>(MoveIntent, (peerId, intent) => {
243
- receivedIntents.push({ peerId, intent });
244
- });
245
-
246
- const peer = transport.simulateConnection("peer1");
247
-
248
- // Encode intent
249
- const intent: MoveIntent = {
250
- kind: 1,
251
- tick: 42,
252
- dx: 10.5,
253
- dy: -5.3,
254
- };
255
- const intentData = intentRegistry.encode(intent);
256
-
257
- // Wrap with message type header
258
- const message = new Uint8Array(1 + intentData.byteLength);
259
- message[0] = 0x01; // MessageType.INTENT
260
- message.set(intentData, 1);
261
-
262
- peer.simulateMessage(message);
263
-
264
- expect(receivedIntents).toHaveLength(1);
265
- expect(receivedIntents[0].peerId).toBe("peer1");
266
- expect(receivedIntents[0].intent.kind).toBe(1);
267
- expect(receivedIntents[0].intent.tick).toBe(42);
268
- expect(receivedIntents[0].intent.dx).toBeCloseTo(10.5, 2);
269
- expect(receivedIntents[0].intent.dy).toBeCloseTo(-5.3, 2);
270
- });
271
-
272
- test("should handle intents from multiple peers", () => {
273
- const receivedIntents: Array<{ peerId: string; intent: MoveIntent }> = [];
274
- server.onIntent<MoveIntent>(MoveIntent, (peerId, intent) => {
275
- receivedIntents.push({ peerId, intent });
276
- });
277
-
278
- const peer1 = transport.simulateConnection("peer1");
279
- const peer2 = transport.simulateConnection("peer2");
280
-
281
- // Send intent from peer1
282
- const intent1: MoveIntent = { kind: 1, tick: 1, dx: 1, dy: 1 };
283
- const intentData1 = intentRegistry.encode(intent1);
284
- const message1 = new Uint8Array(1 + intentData1.byteLength);
285
- message1[0] = 0x01;
286
- message1.set(intentData1, 1);
287
- peer1.simulateMessage(message1);
288
-
289
- // Send intent from peer2
290
- const intent2: MoveIntent = { kind: 1, tick: 2, dx: 2, dy: 2 };
291
- const intentData2 = intentRegistry.encode(intent2);
292
- const message2 = new Uint8Array(1 + intentData2.byteLength);
293
- message2[0] = 0x01;
294
- message2.set(intentData2, 1);
295
- peer2.simulateMessage(message2);
296
-
297
- expect(receivedIntents).toHaveLength(2);
298
- expect(receivedIntents[0].peerId).toBe("peer1");
299
- expect(receivedIntents[1].peerId).toBe("peer2");
300
- });
301
-
302
- test("should handle missing intent handler gracefully", () => {
303
- const peer = transport.simulateConnection("peer1");
304
-
305
- const intent: MoveIntent = { kind: 1, tick: 1, dx: 1, dy: 1 };
306
- const intentData = intentRegistry.encode(intent);
307
- const message = new Uint8Array(1 + intentData.byteLength);
308
- message[0] = 0x01;
309
- message.set(intentData, 1);
310
-
311
- // No handler registered - should not throw
312
- expect(() => peer.simulateMessage(message)).not.toThrow();
313
- });
314
-
315
- test("should handle malformed intent data gracefully", () => {
316
- server.onIntent<MoveIntent>(MoveIntent, () => {});
317
- const peer = transport.simulateConnection("peer1");
318
-
319
- // Send malformed intent
320
- const badMessage = new Uint8Array([0x01, 99, 88, 77]);
321
- expect(() => peer.simulateMessage(badMessage)).not.toThrow();
322
- });
323
- });
324
-
325
- describe("sendSnapshotToPeer", () => {
326
- test("should send snapshot to specific peer", () => {
327
- const peer = transport.simulateConnection("peer1");
328
-
329
- const snapshot: Snapshot<PlayerUpdate> = {
330
- tick: 100,
331
- updates: {
332
- x: 50.5,
333
- y: 100.2,
334
- health: 80,
335
- },
336
- };
337
-
338
- server.sendSnapshotToPeer("peer1", "player", snapshot);
339
-
340
- expect(peer.sentMessages).toHaveLength(1);
341
- const message = peer.sentMessages[0];
342
-
343
- // Check message type header
344
- expect(message[0]).toBe(0x02); // MessageType.SNAPSHOT
345
-
346
- // Decode and verify
347
- const snapshotData = message.subarray(1);
348
- const registry = server.getPeerSnapshotRegistry("peer1")!;
349
- const decoded = registry.decode<PlayerUpdate>(snapshotData);
350
-
351
- expect(decoded.type).toBe("player");
352
- expect(decoded.snapshot.tick).toBe(100);
353
- expect(decoded.snapshot.updates.x).toBeCloseTo(50.5, 2);
354
- expect(decoded.snapshot.updates.y).toBeCloseTo(100.2, 2);
355
- expect(decoded.snapshot.updates.health).toBe(80);
356
- });
357
-
358
- test("should update peer lastSentTick", () => {
359
- transport.simulateConnection("peer1");
360
-
361
- const snapshot: Snapshot<PlayerUpdate> = {
362
- tick: 100,
363
- updates: { x: 1, y: 2, health: 100 },
364
- };
365
-
366
- server.sendSnapshotToPeer("peer1", "player", snapshot);
367
-
368
- const state = server.getPeerState("peer1");
369
- expect(state!.lastSentTick).toBe(100);
370
- });
371
-
372
- test("should handle sending to unknown peer gracefully", () => {
373
- const snapshot: Snapshot<PlayerUpdate> = {
374
- tick: 100,
375
- updates: { x: 1, y: 2, health: 100 },
376
- };
377
-
378
- // Should not throw
379
- expect(() => server.sendSnapshotToPeer("unknown", "player", snapshot)).not.toThrow();
380
- });
381
-
382
- test("should throw if peer has no snapshot registry", () => {
383
- // This shouldn't happen in normal usage, but test defensive code
384
- const peer = transport.simulateConnection("peer1");
385
-
386
- // Manually remove registry to simulate edge case
387
- (server as any).peerSnapshotRegistries.delete("peer1");
388
-
389
- const snapshot: Snapshot<PlayerUpdate> = {
390
- tick: 100,
391
- updates: { x: 1, y: 2, health: 100 },
392
- };
393
-
394
- expect(() => server.sendSnapshotToPeer("peer1", "player", snapshot)).toThrow(
395
- "No snapshot registry registered for peer: peer1"
396
- );
397
- });
398
- });
399
-
400
- describe("broadcastSnapshot", () => {
401
- test("should send snapshot to all connected peers", () => {
402
- const peer1 = transport.simulateConnection("peer1");
403
- const peer2 = transport.simulateConnection("peer2");
404
- const peer3 = transport.simulateConnection("peer3");
405
-
406
- const snapshot: Snapshot<ScoreUpdate> = {
407
- tick: 50,
408
- updates: { score: 9999 },
409
- };
410
-
411
- server.broadcastSnapshot("score", snapshot);
412
-
413
- expect(peer1.sentMessages).toHaveLength(1);
414
- expect(peer2.sentMessages).toHaveLength(1);
415
- expect(peer3.sentMessages).toHaveLength(1);
416
-
417
- // Verify all peers received same snapshot
418
- for (const peer of [peer1, peer2, peer3]) {
419
- const message = peer.sentMessages[0];
420
- expect(message[0]).toBe(0x02); // MessageType.SNAPSHOT
421
- }
422
- });
423
-
424
- test("should use peer-specific registries for encoding", () => {
425
- const peer1 = transport.simulateConnection("peer1");
426
- const peer2 = transport.simulateConnection("peer2");
427
-
428
- const snapshot: Snapshot<PlayerUpdate> = {
429
- tick: 100,
430
- updates: { x: 10, y: 20, health: 100 },
431
- };
432
-
433
- server.broadcastSnapshot("player", snapshot);
434
-
435
- // Each peer should receive encoded snapshot
436
- const registry1 = server.getPeerSnapshotRegistry("peer1")!;
437
- const registry2 = server.getPeerSnapshotRegistry("peer2")!;
438
-
439
- const decoded1 = registry1.decode<PlayerUpdate>(peer1.sentMessages[0].subarray(1));
440
- const decoded2 = registry2.decode<PlayerUpdate>(peer2.sentMessages[0].subarray(1));
441
-
442
- expect(decoded1.snapshot.tick).toBe(100);
443
- expect(decoded2.snapshot.tick).toBe(100);
444
- });
445
-
446
- test("should respect filter function", () => {
447
- const peer1 = transport.simulateConnection("peer1");
448
- const peer2 = transport.simulateConnection("peer2");
449
- const peer3 = transport.simulateConnection("peer3");
450
-
451
- const snapshot: Snapshot<ScoreUpdate> = {
452
- tick: 50,
453
- updates: { score: 100 },
454
- };
455
-
456
- // Only send to peer2 and peer3
457
- server.broadcastSnapshot("score", snapshot, (peerId) => peerId !== "peer1");
458
-
459
- expect(peer1.sentMessages).toHaveLength(0);
460
- expect(peer2.sentMessages).toHaveLength(1);
461
- expect(peer3.sentMessages).toHaveLength(1);
462
- });
463
-
464
- test("should handle empty peer list gracefully", () => {
465
- const snapshot: Snapshot<ScoreUpdate> = {
466
- tick: 1,
467
- updates: { score: 0 },
468
- };
469
-
470
- // No peers connected - should not throw
471
- expect(() => server.broadcastSnapshot("score", snapshot)).not.toThrow();
472
- });
473
- });
474
-
475
- describe("broadcastSnapshotWithCustomization", () => {
476
- test("should customize snapshot for each peer", () => {
477
- const peer1 = transport.simulateConnection("peer1");
478
- const peer2 = transport.simulateConnection("peer2");
479
-
480
- const baseSnapshot: Snapshot<PlayerUpdate> = {
481
- tick: 100,
482
- updates: { x: 10, y: 20, health: 100 },
483
- };
484
-
485
- // Customize: double the x coordinate for each peer
486
- server.broadcastSnapshotWithCustomization("player", baseSnapshot, (peerId, snapshot) => {
487
- return {
488
- tick: snapshot.tick,
489
- updates: {
490
- ...snapshot.updates,
491
- x: snapshot.updates.x! * 2,
492
- },
493
- };
494
- });
495
-
496
- const registry1 = server.getPeerSnapshotRegistry("peer1")!;
497
- const registry2 = server.getPeerSnapshotRegistry("peer2")!;
498
-
499
- const decoded1 = registry1.decode<PlayerUpdate>(peer1.sentMessages[0].subarray(1));
500
- const decoded2 = registry2.decode<PlayerUpdate>(peer2.sentMessages[0].subarray(1));
501
-
502
- expect(decoded1.snapshot.updates.x).toBeCloseTo(20, 2); // 10 * 2
503
- expect(decoded2.snapshot.updates.x).toBeCloseTo(20, 2); // 10 * 2
504
- });
505
-
506
- test("should allow different customization per peer", () => {
507
- const peer1 = transport.simulateConnection("peer1");
508
- const peer2 = transport.simulateConnection("peer2");
509
-
510
- const baseSnapshot: Snapshot<ScoreUpdate> = {
511
- tick: 100,
512
- updates: { score: 100 },
513
- };
514
-
515
- // Give peer1 double score, peer2 triple score
516
- server.broadcastSnapshotWithCustomization("score", baseSnapshot, (peerId, snapshot) => {
517
- const multiplier = peerId === "peer1" ? 2 : 3;
518
- return {
519
- tick: snapshot.tick,
520
- updates: {
521
- score: snapshot.updates.score! * multiplier,
522
- },
523
- };
524
- });
525
-
526
- const registry1 = server.getPeerSnapshotRegistry("peer1")!;
527
- const registry2 = server.getPeerSnapshotRegistry("peer2")!;
528
-
529
- const decoded1 = registry1.decode<ScoreUpdate>(peer1.sentMessages[0].subarray(1));
530
- const decoded2 = registry2.decode<ScoreUpdate>(peer2.sentMessages[0].subarray(1));
531
-
532
- expect(decoded1.snapshot.updates.score).toBe(200); // 100 * 2
533
- expect(decoded2.snapshot.updates.score).toBe(300); // 100 * 3
534
- });
535
- });
536
-
537
- describe("Peer metadata", () => {
538
- test("should set and retrieve peer metadata", () => {
539
- transport.simulateConnection("peer1");
540
-
541
- server.setPeerMetadata("peer1", "username", "Alice");
542
- server.setPeerMetadata("peer1", "team", "blue");
543
-
544
- const state = server.getPeerState("peer1");
545
- expect(state!.metadata["username"]).toBe("Alice");
546
- expect(state!.metadata["team"]).toBe("blue");
547
- });
548
-
549
- test("should handle setting metadata for unknown peer", () => {
550
- // Should not throw
551
- expect(() => server.setPeerMetadata("unknown", "key", "value")).not.toThrow();
552
- });
553
- });
554
-
555
- describe("Peer queries", () => {
556
- test("should return all peer IDs", () => {
557
- transport.simulateConnection("peer1");
558
- transport.simulateConnection("peer2");
559
- transport.simulateConnection("peer3");
560
-
561
- const peerIds = server.getPeerIds();
562
- expect(peerIds).toHaveLength(3);
563
- expect(peerIds).toContain("peer1");
564
- expect(peerIds).toContain("peer2");
565
- expect(peerIds).toContain("peer3");
566
- });
567
-
568
- test("should return empty array when no peers", () => {
569
- expect(server.getPeerIds()).toEqual([]);
570
- });
571
-
572
- test("should return undefined for unknown peer state", () => {
573
- expect(server.getPeerState("unknown")).toBeUndefined();
574
- });
575
-
576
- test("should return undefined for unknown peer registry", () => {
577
- expect(server.getPeerSnapshotRegistry("unknown")).toBeUndefined();
578
- });
579
- });
580
-
581
- describe("Message handling", () => {
582
- test("should ignore empty messages", () => {
583
- const peer = transport.simulateConnection("peer1");
584
- expect(() => peer.simulateMessage(new Uint8Array(0))).not.toThrow();
585
- });
586
-
587
- test("should handle custom message type", () => {
588
- const peer = transport.simulateConnection("peer1");
589
- const message = new Uint8Array([0xff, 1, 2, 3]); // MessageType.CUSTOM
590
- expect(() => peer.simulateMessage(message)).not.toThrow();
591
- });
592
-
593
- test("should handle unknown message types", () => {
594
- const peer = transport.simulateConnection("peer1");
595
- const message = new Uint8Array([0x99, 1, 2, 3]); // Unknown type
596
- expect(() => peer.simulateMessage(message)).not.toThrow();
597
- });
598
-
599
- test("should reject messages exceeding max size", () => {
600
- const smallServer = new ServerNetwork<MockPeerTransport, GameSnapshots>({
601
- transport,
602
- intentRegistry,
603
- createPeerSnapshotRegistry: () => new SnapshotRegistry<GameSnapshots>(),
604
- config: { maxMessageSize: 10 },
605
- });
606
-
607
- const intentsReceived: MoveIntent[] = [];
608
- smallServer.onIntent<MoveIntent>(MoveIntent, (_, intent) => {
609
- intentsReceived.push(intent);
610
- });
611
-
612
- const peer = transport.simulateConnection("peer1");
613
-
614
- // Create large message
615
- const largeMessage = new Uint8Array(100);
616
- largeMessage[0] = 0x01; // MessageType.INTENT
617
-
618
- peer.simulateMessage(largeMessage);
619
- expect(intentsReceived).toHaveLength(0);
620
- });
621
- });
622
-
623
- describe("close", () => {
624
- test("should close server transport", () => {
625
- server.close();
626
- expect(transport.closed).toBe(true);
627
- });
628
- });
629
-
630
- describe("Debug logging", () => {
631
- test("should not log when debug is false", () => {
632
- const logs: string[] = [];
633
- const originalLog = console.log;
634
- console.log = (...args: any[]) => logs.push(args.join(" "));
635
-
636
- transport.simulateConnection("peer1");
637
-
638
- console.log = originalLog;
639
- expect(logs.filter((l) => l.includes("[ServerNetwork]"))).toHaveLength(0);
640
- });
641
-
642
- test("should log when debug is true", () => {
643
- const logs: string[] = [];
644
- const originalLog = console.log;
645
- console.log = (...args: any[]) => logs.push(args.join(" "));
646
-
647
- const debugServer = new ServerNetwork<MockPeerTransport, GameSnapshots>({
648
- transport,
649
- intentRegistry,
650
- createPeerSnapshotRegistry: () => new SnapshotRegistry<GameSnapshots>(),
651
- config: { debug: true },
652
- });
653
-
654
- transport.simulateConnection("peer1");
655
-
656
- console.log = originalLog;
657
- expect(logs.filter((l) => l.includes("[ServerNetwork]")).length).toBeGreaterThan(0);
658
- });
659
- });
660
-
661
- describe("Delta detection with sendSnapshotToPeerIfChanged", () => {
662
- test("should send snapshot on first call (no previous hash)", () => {
663
- const peer = transport.simulateConnection("peer1");
664
-
665
- const snapshot: Snapshot<PlayerUpdate> = {
666
- tick: 1,
667
- updates: { x: 10, y: 20, health: 100 },
668
- };
669
-
670
- const wasSent = server.sendSnapshotToPeerIfChanged("peer1", "player", snapshot);
671
-
672
- expect(wasSent).toBe(true);
673
- expect(peer.sentMessages.length).toBe(1);
674
- });
675
-
676
- test("should not send snapshot if data unchanged", () => {
677
- const peer = transport.simulateConnection("peer1");
678
-
679
- const snapshot: Snapshot<PlayerUpdate> = {
680
- tick: 1,
681
- updates: { x: 10, y: 20, health: 100 },
682
- };
683
-
684
- // First send
685
- server.sendSnapshotToPeerIfChanged("peer1", "player", snapshot);
686
- expect(peer.sentMessages.length).toBe(1);
687
-
688
- // Second send with same data (different tick, same updates)
689
- const snapshot2: Snapshot<PlayerUpdate> = {
690
- tick: 2,
691
- updates: { x: 10, y: 20, health: 100 },
692
- };
693
-
694
- const wasSent = server.sendSnapshotToPeerIfChanged("peer1", "player", snapshot2);
695
-
696
- expect(wasSent).toBe(false);
697
- expect(peer.sentMessages.length).toBe(1); // Still only 1 message
698
- });
699
-
700
- test("should send snapshot if data changed", () => {
701
- const peer = transport.simulateConnection("peer1");
702
-
703
- const snapshot1: Snapshot<PlayerUpdate> = {
704
- tick: 1,
705
- updates: { x: 10, y: 20, health: 100 },
706
- };
707
-
708
- server.sendSnapshotToPeerIfChanged("peer1", "player", snapshot1);
709
- expect(peer.sentMessages.length).toBe(1);
710
-
711
- // Send with changed position
712
- const snapshot2: Snapshot<PlayerUpdate> = {
713
- tick: 2,
714
- updates: { x: 15, y: 20, health: 100 }, // x changed
715
- };
716
-
717
- const wasSent = server.sendSnapshotToPeerIfChanged("peer1", "player", snapshot2);
718
-
719
- expect(wasSent).toBe(true);
720
- expect(peer.sentMessages.length).toBe(2);
721
- });
722
-
723
- test("should track hashes separately per peer", () => {
724
- const peer1 = transport.simulateConnection("peer1");
725
- const peer2 = transport.simulateConnection("peer2");
726
-
727
- const snapshot: Snapshot<PlayerUpdate> = {
728
- tick: 1,
729
- updates: { x: 10, y: 20, health: 100 },
730
- };
731
-
732
- // Send to peer1
733
- const sent1 = server.sendSnapshotToPeerIfChanged("peer1", "player", snapshot);
734
- expect(sent1).toBe(true);
735
- expect(peer1.sentMessages.length).toBe(1);
736
-
737
- // Send same snapshot to peer2 - should send because peer2 hasn't received it
738
- const sent2 = server.sendSnapshotToPeerIfChanged("peer2", "player", snapshot);
739
- expect(sent2).toBe(true);
740
- expect(peer2.sentMessages.length).toBe(1);
741
-
742
- // Send again to peer1 - should not send (duplicate)
743
- const sent3 = server.sendSnapshotToPeerIfChanged("peer1", "player", snapshot);
744
- expect(sent3).toBe(false);
745
- expect(peer1.sentMessages.length).toBe(1);
746
- });
747
-
748
- test("should track hashes separately per snapshot type", () => {
749
- const peer = transport.simulateConnection("peer1");
750
-
751
- const playerSnapshot: Snapshot<PlayerUpdate> = {
752
- tick: 1,
753
- updates: { x: 10, y: 20, health: 100 },
754
- };
755
-
756
- const scoreSnapshot: Snapshot<ScoreUpdate> = {
757
- tick: 1,
758
- updates: { score: 50 },
759
- };
760
-
761
- // Send player snapshot
762
- server.sendSnapshotToPeerIfChanged("peer1", "player", playerSnapshot);
763
- expect(peer.sentMessages.length).toBe(1);
764
-
765
- // Send score snapshot - different type, should send
766
- server.sendSnapshotToPeerIfChanged("peer1", "score", scoreSnapshot);
767
- expect(peer.sentMessages.length).toBe(2);
768
-
769
- // Send player snapshot again - should not send (duplicate)
770
- const sent = server.sendSnapshotToPeerIfChanged("peer1", "player", playerSnapshot);
771
- expect(sent).toBe(false);
772
- expect(peer.sentMessages.length).toBe(2);
773
- });
774
-
775
- test("should cleanup hashes on peer disconnect", () => {
776
- const peer = transport.simulateConnection("peer1");
777
-
778
- const snapshot: Snapshot<PlayerUpdate> = {
779
- tick: 1,
780
- updates: { x: 10, y: 20, health: 100 },
781
- };
782
-
783
- // Send snapshot
784
- server.sendSnapshotToPeerIfChanged("peer1", "player", snapshot);
785
- expect(peer.sentMessages.length).toBe(1);
786
-
787
- // Disconnect
788
- transport.simulateDisconnection("peer1");
789
-
790
- // Reconnect with same ID
791
- const newPeer = transport.simulateConnection("peer1");
792
-
793
- // Should send again (hash was cleared on disconnect)
794
- const wasSent = server.sendSnapshotToPeerIfChanged("peer1", "player", snapshot);
795
- expect(wasSent).toBe(true);
796
- expect(newPeer.sentMessages.length).toBe(1);
797
- });
798
- });
799
- });