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.
- package/README.md +52 -37
- package/dist/cjs/core/binary-codec/binary-codec.js +1 -0
- package/dist/cjs/core/binary-codec/index.js +1 -0
- package/dist/cjs/core/driver/driver.js +1 -0
- package/dist/cjs/core/driver/drivers/immediate.js +1 -0
- package/dist/cjs/core/driver/drivers/index.js +1 -0
- package/dist/cjs/core/driver/drivers/raf.js +1 -0
- package/dist/cjs/core/driver/drivers/timeout.js +1 -0
- package/dist/cjs/core/driver/index.js +1 -0
- package/dist/cjs/core/events/event-system.js +1 -0
- package/dist/cjs/core/events/index.js +1 -0
- package/dist/cjs/core/fixed-ticker/fixed-ticker.js +1 -0
- package/dist/cjs/core/fixed-ticker/index.js +1 -0
- package/dist/cjs/core/free-list/free-list.js +1 -0
- package/dist/cjs/core/free-list/index.js +1 -0
- package/dist/cjs/core/generate-id/generate-id.js +1 -0
- package/dist/cjs/core/generate-id/index.js +1 -0
- package/dist/cjs/core/index.js +1 -0
- package/dist/cjs/core/input/index.js +1 -0
- package/dist/cjs/core/input/manager.js +1 -0
- package/dist/cjs/core/input/sources/browser.js +1 -0
- package/dist/cjs/core/input/sources/index.js +1 -0
- package/dist/cjs/core/input/types.js +1 -0
- package/dist/cjs/core/lerp/index.js +1 -0
- package/dist/cjs/core/lerp/lerp.js +1 -0
- package/dist/cjs/core/navmesh/index.js +1 -0
- package/dist/cjs/core/navmesh/navmesh-worker-pool.js +1 -0
- package/dist/cjs/core/navmesh/navmesh.js +1 -0
- package/dist/cjs/core/navmesh/navmesh.worker.js +1 -0
- package/dist/cjs/core/pooled-codec/index.js +1 -0
- package/dist/cjs/core/pooled-codec/pooled-codec.js +1 -0
- package/dist/cjs/core/prediction/index.js +1 -0
- package/dist/cjs/core/prediction/prediction.js +1 -0
- package/dist/cjs/core/ray/index.js +1 -0
- package/dist/cjs/core/ray/ray-2d.js +1 -0
- package/dist/cjs/core/ray/ray-3d.js +1 -0
- package/dist/cjs/core/simple-rng/index.js +1 -0
- package/dist/cjs/core/simple-rng/simple-rng.js +1 -0
- package/dist/cjs/core/sparse-batcher/index.js +1 -0
- package/dist/cjs/core/sparse-batcher/sparse-batcher.js +1 -0
- package/dist/cjs/ecs/component-store.js +1 -0
- package/dist/cjs/ecs/component.js +1 -0
- package/dist/cjs/ecs/entity-handle.js +1 -0
- package/dist/cjs/ecs/index.js +1 -0
- package/dist/cjs/ecs/system-builder.js +1 -0
- package/dist/cjs/ecs/world-systems.js +1 -0
- package/dist/cjs/ecs/world.js +1 -0
- package/dist/cjs/game/index.js +1 -0
- package/dist/cjs/game/loop/index.js +1 -0
- package/dist/cjs/game/loop/loop.js +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/net/adapters/browser-websocket.js +1 -0
- package/dist/cjs/net/adapters/bun-websocket.js +1 -0
- package/dist/cjs/net/buffer-pool.js +1 -0
- package/dist/cjs/net/client.js +1 -0
- package/dist/cjs/net/index.js +1 -0
- package/dist/cjs/net/server.js +1 -0
- package/dist/cjs/net/types.js +1 -0
- package/dist/cjs/net/validators.js +1 -0
- package/dist/cjs/protocol/index.js +1 -0
- package/dist/cjs/protocol/intent/define-intent.js +1 -0
- package/dist/cjs/protocol/intent/index.js +1 -0
- package/dist/cjs/protocol/intent/intent-registry.js +1 -0
- package/dist/cjs/protocol/intent/intent.js +1 -0
- package/dist/cjs/protocol/rpc/define-rpc.js +1 -0
- package/dist/cjs/protocol/rpc/index.js +1 -0
- package/dist/cjs/protocol/rpc/rpc-registry.js +1 -0
- package/dist/cjs/protocol/rpc/rpc.js +1 -0
- package/dist/cjs/protocol/snapshot/index.js +1 -0
- package/dist/cjs/protocol/snapshot/snapshot-codec.js +1 -0
- package/dist/cjs/protocol/snapshot/snapshot-registry.js +1 -0
- package/dist/cjs/protocol/snapshot/snapshot.js +1 -0
- package/dist/cjs/renderer/base-2d-renderer.js +1 -0
- package/dist/cjs/renderer/base-3d-renderer.js +1 -0
- package/dist/cjs/renderer/base-renderer.js +1 -0
- package/dist/cjs/renderer/index.js +1 -0
- package/dist/cjs/renderer/types.js +1 -0
- package/dist/esm/core/binary-codec/binary-codec.js +1 -0
- package/dist/esm/core/binary-codec/index.js +1 -0
- package/dist/esm/core/driver/driver.js +1 -0
- package/dist/esm/core/driver/drivers/immediate.js +1 -0
- package/dist/esm/core/driver/drivers/index.js +1 -0
- package/dist/esm/core/driver/drivers/raf.js +1 -0
- package/dist/esm/core/driver/drivers/timeout.js +1 -0
- package/dist/esm/core/driver/index.js +1 -0
- package/dist/esm/core/events/event-system.js +1 -0
- package/dist/esm/core/events/index.js +1 -0
- package/dist/esm/core/fixed-ticker/fixed-ticker.js +1 -0
- package/dist/esm/core/fixed-ticker/index.js +1 -0
- package/dist/esm/core/free-list/free-list.js +1 -0
- package/dist/esm/core/free-list/index.js +1 -0
- package/dist/esm/core/generate-id/generate-id.js +1 -0
- package/dist/esm/core/generate-id/index.js +1 -0
- package/dist/esm/core/index.js +1 -0
- package/dist/esm/core/input/index.js +1 -0
- package/dist/esm/core/input/manager.js +1 -0
- package/dist/esm/core/input/sources/browser.js +1 -0
- package/dist/esm/core/input/sources/index.js +1 -0
- package/dist/esm/core/input/types.js +0 -0
- package/dist/esm/core/lerp/index.js +1 -0
- package/dist/esm/core/lerp/lerp.js +1 -0
- package/dist/esm/core/navmesh/index.js +1 -0
- package/dist/esm/core/navmesh/navmesh-worker-pool.js +1 -0
- package/dist/esm/core/navmesh/navmesh.js +1 -0
- package/dist/esm/core/navmesh/navmesh.worker.js +1 -0
- package/dist/esm/core/pooled-codec/index.js +1 -0
- package/dist/esm/core/pooled-codec/pooled-codec.js +1 -0
- package/dist/esm/core/prediction/index.js +1 -0
- package/dist/esm/core/prediction/prediction.js +1 -0
- package/dist/esm/core/ray/index.js +1 -0
- package/dist/esm/core/ray/ray-2d.js +1 -0
- package/dist/esm/core/ray/ray-3d.js +1 -0
- package/dist/esm/core/simple-rng/index.js +1 -0
- package/dist/esm/core/simple-rng/simple-rng.js +1 -0
- package/dist/esm/core/sparse-batcher/index.js +1 -0
- package/dist/esm/core/sparse-batcher/sparse-batcher.js +1 -0
- package/dist/esm/ecs/component-store.js +1 -0
- package/dist/esm/ecs/component.js +1 -0
- package/dist/esm/ecs/entity-handle.js +1 -0
- package/dist/esm/ecs/index.js +1 -0
- package/dist/esm/ecs/system-builder.js +1 -0
- package/dist/esm/ecs/world-systems.js +1 -0
- package/dist/esm/ecs/world.js +1 -0
- package/dist/esm/game/index.js +1 -0
- package/dist/esm/game/loop/index.js +1 -0
- package/dist/esm/game/loop/loop.js +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/net/adapters/browser-websocket.js +1 -0
- package/dist/esm/net/adapters/bun-websocket.js +1 -0
- package/dist/esm/net/buffer-pool.js +1 -0
- package/dist/esm/net/client.js +1 -0
- package/dist/esm/net/index.js +1 -0
- package/dist/esm/net/server.js +1 -0
- package/dist/esm/net/types.js +1 -0
- package/dist/esm/net/validators.js +1 -0
- package/dist/esm/protocol/index.js +1 -0
- package/dist/esm/protocol/intent/define-intent.js +1 -0
- package/dist/esm/protocol/intent/index.js +1 -0
- package/dist/esm/protocol/intent/intent-registry.js +1 -0
- package/dist/esm/protocol/intent/intent.js +0 -0
- package/dist/esm/protocol/rpc/define-rpc.js +1 -0
- package/dist/esm/protocol/rpc/index.js +1 -0
- package/dist/esm/protocol/rpc/rpc-registry.js +1 -0
- package/dist/esm/protocol/rpc/rpc.js +0 -0
- package/dist/esm/protocol/snapshot/index.js +1 -0
- package/dist/esm/protocol/snapshot/snapshot-codec.js +1 -0
- package/dist/esm/protocol/snapshot/snapshot-registry.js +1 -0
- package/dist/esm/protocol/snapshot/snapshot.js +1 -0
- package/dist/esm/renderer/base-2d-renderer.js +1 -0
- package/dist/esm/renderer/base-3d-renderer.js +1 -0
- package/dist/esm/renderer/base-renderer.js +1 -0
- package/dist/esm/renderer/index.js +1 -0
- package/dist/esm/renderer/types.js +0 -0
- package/dist/{core → types/core}/binary-codec/binary-codec.d.ts +4 -0
- package/dist/{core → types/core}/events/event-system.d.ts +14 -33
- package/dist/types/core/free-list/free-list.d.ts +31 -0
- package/dist/types/core/free-list/index.d.ts +1 -0
- package/dist/{core → types/core}/index.d.ts +5 -0
- package/dist/{core → types/core}/input/index.d.ts +1 -0
- package/dist/{core → types/core}/input/manager.d.ts +2 -0
- package/dist/{core → types/core}/navmesh/navmesh.d.ts +1 -21
- package/dist/types/core/ray/index.d.ts +2 -0
- package/dist/types/core/ray/ray-2d.d.ts +37 -0
- package/dist/types/core/ray/ray-3d.d.ts +42 -0
- package/dist/types/core/simple-rng/index.d.ts +1 -0
- package/dist/types/core/simple-rng/simple-rng.d.ts +36 -0
- package/dist/types/core/sparse-batcher/index.d.ts +1 -0
- package/dist/types/core/sparse-batcher/sparse-batcher.d.ts +55 -0
- package/dist/{ecs → types/ecs}/world.d.ts +11 -0
- package/dist/{game → types/game}/loop/loop.d.ts +33 -29
- package/dist/{index.d.ts → types/index.d.ts} +1 -0
- package/dist/{net → types/net}/index.d.ts +2 -2
- package/dist/types/renderer/base-2d-renderer.d.ts +13 -0
- package/dist/types/renderer/base-3d-renderer.d.ts +10 -0
- package/dist/types/renderer/base-renderer.d.ts +21 -0
- package/dist/types/renderer/index.d.ts +4 -0
- package/dist/types/renderer/types.d.ts +79 -0
- package/dist/webgpu/cjs/index.js +6004 -0
- package/dist/webgpu/esm/index.js +5972 -0
- package/dist/webgpu/types/2d/animation.d.ts +97 -0
- package/dist/webgpu/types/2d/renderer.d.ts +55 -0
- package/dist/webgpu/types/2d/shader.d.ts +61 -0
- package/dist/webgpu/types/2d/sprite-accessor.d.ts +47 -0
- package/dist/webgpu/types/3d/gltf-skin-parser.d.ts +101 -0
- package/dist/webgpu/types/3d/morph-animation.d.ts +69 -0
- package/dist/webgpu/types/3d/morph-animation.test.d.ts +1 -0
- package/dist/webgpu/types/3d/renderer.d.ts +216 -0
- package/dist/webgpu/types/3d/shader.d.ts +136 -0
- package/dist/webgpu/types/3d/skeletal-animation-compute/index.d.ts +2 -0
- package/dist/webgpu/types/3d/skeletal-animation-compute/kernel.d.ts +8 -0
- package/dist/webgpu/types/3d/skeletal-animation-compute/packer.d.ts +32 -0
- package/dist/webgpu/types/3d/skeletal-animation.d.ts +90 -0
- package/dist/webgpu/types/camera/camera-2d.d.ts +53 -0
- package/dist/webgpu/types/camera/camera-2d.test.d.ts +1 -0
- package/dist/webgpu/types/camera/camera-3d.d.ts +81 -0
- package/dist/webgpu/types/camera/camera-3d.test.d.ts +1 -0
- package/dist/webgpu/types/camera/index.d.ts +2 -0
- package/dist/webgpu/types/compute/compute-builder.d.ts +123 -0
- package/dist/webgpu/types/compute/compute-builder.test.d.ts +1 -0
- package/dist/webgpu/types/core/constants.d.ts +59 -0
- package/dist/webgpu/types/core/constants.test.d.ts +1 -0
- package/dist/webgpu/types/core/index.d.ts +2 -0
- package/dist/webgpu/types/core/math.d.ts +37 -0
- package/dist/webgpu/types/core/types.d.ts +125 -0
- package/dist/webgpu/types/core/types.test.d.ts +1 -0
- package/dist/webgpu/types/geometry/built-in.d.ts +58 -0
- package/dist/webgpu/types/geometry/built-in.test.d.ts +1 -0
- package/dist/webgpu/types/geometry/geometry-builder.d.ts +281 -0
- package/dist/webgpu/types/geometry/geometry-builder.test.d.ts +1 -0
- package/dist/webgpu/types/geometry/index.d.ts +2 -0
- package/dist/webgpu/types/index.d.ts +32 -0
- package/dist/webgpu/types/particle/emitter.d.ts +36 -0
- package/dist/webgpu/types/shaders/index.d.ts +2 -0
- package/dist/webgpu/types/shaders/runtime-transpile.d.ts +18 -0
- package/dist/webgpu/types/shaders/sprite-2d.wgsl.d.ts +10 -0
- package/dist/webgpu/types/shaders/typegpu.d.ts +9 -0
- package/dist/webgpu/types/shaders/utils.d.ts +28 -0
- package/dist/webgpu/types/shaders/utils.test.d.ts +1 -0
- package/dist/webgpu/types/spritesheet/index.d.ts +1 -0
- package/dist/webgpu/types/spritesheet/spritesheet.d.ts +57 -0
- package/dist/webgpu/types/spritesheet/spritesheet.test.d.ts +1 -0
- package/package.json +96 -26
- package/dist/core/binary-codec/binary-codec.js +0 -354
- package/dist/core/binary-codec/index.js +0 -1
- package/dist/core/driver/driver.js +0 -47
- package/dist/core/driver/drivers/immediate.js +0 -61
- package/dist/core/driver/drivers/index.js +0 -3
- package/dist/core/driver/drivers/raf.js +0 -62
- package/dist/core/driver/drivers/timeout.js +0 -71
- package/dist/core/driver/index.js +0 -2
- package/dist/core/events/event-system.js +0 -88
- package/dist/core/events/index.js +0 -1
- package/dist/core/fixed-ticker/fixed-ticker.js +0 -105
- package/dist/core/fixed-ticker/index.js +0 -1
- package/dist/core/generate-id/generate-id.js +0 -25
- package/dist/core/generate-id/index.js +0 -1
- package/dist/core/index.js +0 -10
- package/dist/core/input/index.js +0 -2
- package/dist/core/input/manager.js +0 -211
- package/dist/core/input/sources/browser.js +0 -29
- package/dist/core/input/sources/index.js +0 -1
- package/dist/core/lerp/index.js +0 -1
- package/dist/core/lerp/lerp.js +0 -42
- package/dist/core/navmesh/index.js +0 -1
- package/dist/core/navmesh/navmesh-worker-pool.js +0 -180
- package/dist/core/navmesh/navmesh.js +0 -799
- package/dist/core/navmesh/navmesh.worker.js +0 -79
- package/dist/core/pooled-codec/index.js +0 -1
- package/dist/core/pooled-codec/pooled-codec.js +0 -410
- package/dist/core/prediction/index.js +0 -1
- package/dist/core/prediction/prediction.js +0 -99
- package/dist/core.esm.js +0 -1
- package/dist/core.js +0 -1
- package/dist/ecs/component-store.js +0 -175
- package/dist/ecs/component.js +0 -43
- package/dist/ecs/entity-handle.js +0 -515
- package/dist/ecs/example.js +0 -125
- package/dist/ecs/index.js +0 -4
- package/dist/ecs/system-builder.js +0 -249
- package/dist/ecs/world-systems.js +0 -79
- package/dist/ecs/world.js +0 -767
- package/dist/game/index.js +0 -1
- package/dist/game/loop/index.js +0 -1
- package/dist/game/loop/loop.js +0 -108
- package/dist/index.js +0 -26
- package/dist/net/adapters/browser-websocket.js +0 -74
- package/dist/net/adapters/bun-websocket.js +0 -245
- package/dist/net/buffer-pool.js +0 -89
- package/dist/net/client.js +0 -586
- package/dist/net/index.js +0 -58
- package/dist/net/server.js +0 -974
- package/dist/net/types.js +0 -31
- package/dist/net/validators.js +0 -88
- package/dist/protocol/index.js +0 -92
- package/dist/protocol/intent/define-intent.js +0 -125
- package/dist/protocol/intent/index.js +0 -91
- package/dist/protocol/intent/intent-registry.js +0 -91
- package/dist/protocol/rpc/define-rpc.js +0 -84
- package/dist/protocol/rpc/index.js +0 -3
- package/dist/protocol/rpc/rpc-registry.js +0 -159
- package/dist/protocol/rpc/rpc.js +0 -12
- package/dist/protocol/snapshot/index.js +0 -43
- package/dist/protocol/snapshot/snapshot-codec.js +0 -67
- package/dist/protocol/snapshot/snapshot-registry.js +0 -168
- package/dist/protocol/snapshot/snapshot.js +0 -30
- package/src/core/binary-codec/README.md +0 -60
- package/src/core/binary-codec/binary-codec.test.ts +0 -300
- package/src/core/binary-codec/binary-codec.ts +0 -448
- package/src/core/binary-codec/index.ts +0 -1
- package/src/core/driver/README.md +0 -97
- package/src/core/driver/driver.test.ts +0 -414
- package/src/core/driver/driver.ts +0 -71
- package/src/core/driver/drivers/immediate.ts +0 -66
- package/src/core/driver/drivers/index.ts +0 -3
- package/src/core/driver/drivers/raf.ts +0 -67
- package/src/core/driver/drivers/timeout.ts +0 -77
- package/src/core/driver/index.ts +0 -2
- package/src/core/events/README.md +0 -47
- package/src/core/events/event-system.test.ts +0 -243
- package/src/core/events/event-system.ts +0 -140
- package/src/core/events/index.ts +0 -1
- package/src/core/fixed-ticker/README.md +0 -77
- package/src/core/fixed-ticker/fixed-ticker.test.ts +0 -151
- package/src/core/fixed-ticker/fixed-ticker.ts +0 -174
- package/src/core/fixed-ticker/index.ts +0 -1
- package/src/core/generate-id/README.md +0 -18
- package/src/core/generate-id/generate-id.test.ts +0 -79
- package/src/core/generate-id/generate-id.ts +0 -37
- package/src/core/generate-id/index.ts +0 -1
- package/src/core/index.ts +0 -10
- package/src/core/input/README.md +0 -24
- package/src/core/input/index.ts +0 -2
- package/src/core/input/manager.ts +0 -259
- package/src/core/input/sources/browser.ts +0 -39
- package/src/core/input/sources/index.ts +0 -1
- package/src/core/input/types.ts +0 -40
- package/src/core/lerp/README.md +0 -79
- package/src/core/lerp/index.ts +0 -1
- package/src/core/lerp/lerp.test.ts +0 -90
- package/src/core/lerp/lerp.ts +0 -42
- package/src/core/navmesh/README.md +0 -164
- package/src/core/navmesh/index.ts +0 -1
- package/src/core/navmesh/navmesh-worker-pool.ts +0 -236
- package/src/core/navmesh/navmesh-workers.test.ts +0 -356
- package/src/core/navmesh/navmesh.test.ts +0 -344
- package/src/core/navmesh/navmesh.ts +0 -1047
- package/src/core/navmesh/navmesh.worker.ts +0 -147
- package/src/core/pooled-codec/README.md +0 -70
- package/src/core/pooled-codec/index.ts +0 -1
- package/src/core/pooled-codec/pooled-codec.test.ts +0 -862
- package/src/core/pooled-codec/pooled-codec.ts +0 -504
- package/src/core/prediction/README.md +0 -64
- package/src/core/prediction/index.ts +0 -1
- package/src/core/prediction/prediction.test.ts +0 -423
- package/src/core/prediction/prediction.ts +0 -112
- package/src/ecs/README.md +0 -427
- package/src/ecs/benchmark.test.ts +0 -1645
- package/src/ecs/component-store.ts +0 -198
- package/src/ecs/component.ts +0 -90
- package/src/ecs/entity-handle.test.ts +0 -393
- package/src/ecs/entity-handle.ts +0 -563
- package/src/ecs/example.ts +0 -152
- package/src/ecs/index.ts +0 -4
- package/src/ecs/system-builder.ts +0 -404
- package/src/ecs/world-systems.ts +0 -83
- package/src/ecs/world.test.ts +0 -310
- package/src/ecs/world.ts +0 -904
- package/src/game/index.ts +0 -1
- package/src/game/loop/README.md +0 -32
- package/src/game/loop/index.ts +0 -1
- package/src/game/loop/loop.ts +0 -236
- package/src/index.ts +0 -32
- package/src/net/README.md +0 -474
- package/src/net/adapters/browser-websocket.ts +0 -86
- package/src/net/adapters/bun-websocket.ts +0 -292
- package/src/net/buffer-pool.ts +0 -106
- package/src/net/client.test.ts +0 -807
- package/src/net/client.ts +0 -695
- package/src/net/index.ts +0 -60
- package/src/net/server.test.ts +0 -799
- package/src/net/server.ts +0 -1152
- package/src/net/types.ts +0 -228
- package/src/net/validators.ts +0 -104
- package/src/protocol/README.md +0 -469
- package/src/protocol/index.ts +0 -93
- package/src/protocol/intent/define-intent.test.ts +0 -397
- package/src/protocol/intent/define-intent.ts +0 -201
- package/src/protocol/intent/index.ts +0 -94
- package/src/protocol/intent/intent-registry.test.ts +0 -198
- package/src/protocol/intent/intent-registry.ts +0 -112
- package/src/protocol/intent/intent.ts +0 -12
- package/src/protocol/rpc/define-rpc.test.ts +0 -141
- package/src/protocol/rpc/define-rpc.ts +0 -113
- package/src/protocol/rpc/index.ts +0 -3
- package/src/protocol/rpc/rpc-registry.test.ts +0 -168
- package/src/protocol/rpc/rpc-registry.ts +0 -176
- package/src/protocol/rpc/rpc.ts +0 -37
- package/src/protocol/snapshot/index.ts +0 -45
- package/src/protocol/snapshot/snapshot-codec.test.ts +0 -138
- package/src/protocol/snapshot/snapshot-codec.ts +0 -87
- package/src/protocol/snapshot/snapshot-registry.test.ts +0 -310
- package/src/protocol/snapshot/snapshot-registry.ts +0 -201
- package/src/protocol/snapshot/snapshot.test.ts +0 -76
- package/src/protocol/snapshot/snapshot.ts +0 -41
- /package/dist/{core → types/core}/binary-codec/index.d.ts +0 -0
- /package/dist/{core → types/core}/driver/driver.d.ts +0 -0
- /package/dist/{core → types/core}/driver/drivers/immediate.d.ts +0 -0
- /package/dist/{core → types/core}/driver/drivers/index.d.ts +0 -0
- /package/dist/{core → types/core}/driver/drivers/raf.d.ts +0 -0
- /package/dist/{core → types/core}/driver/drivers/timeout.d.ts +0 -0
- /package/dist/{core → types/core}/driver/index.d.ts +0 -0
- /package/dist/{core → types/core}/events/index.d.ts +0 -0
- /package/dist/{core → types/core}/fixed-ticker/fixed-ticker.d.ts +0 -0
- /package/dist/{core → types/core}/fixed-ticker/index.d.ts +0 -0
- /package/dist/{core → types/core}/generate-id/generate-id.d.ts +0 -0
- /package/dist/{core → types/core}/generate-id/index.d.ts +0 -0
- /package/dist/{core → types/core}/input/sources/browser.d.ts +0 -0
- /package/dist/{core → types/core}/input/sources/index.d.ts +0 -0
- /package/dist/{core → types/core}/input/types.d.ts +0 -0
- /package/dist/{core → types/core}/lerp/index.d.ts +0 -0
- /package/dist/{core → types/core}/lerp/lerp.d.ts +0 -0
- /package/dist/{core → types/core}/navmesh/index.d.ts +0 -0
- /package/dist/{core → types/core}/navmesh/navmesh-worker-pool.d.ts +0 -0
- /package/dist/{core → types/core}/navmesh/navmesh.worker.d.ts +0 -0
- /package/dist/{core → types/core}/pooled-codec/index.d.ts +0 -0
- /package/dist/{core → types/core}/pooled-codec/pooled-codec.d.ts +0 -0
- /package/dist/{core → types/core}/prediction/index.d.ts +0 -0
- /package/dist/{core → types/core}/prediction/prediction.d.ts +0 -0
- /package/dist/{ecs → types/ecs}/component-store.d.ts +0 -0
- /package/dist/{ecs → types/ecs}/component.d.ts +0 -0
- /package/dist/{ecs → types/ecs}/entity-handle.d.ts +0 -0
- /package/dist/{ecs → types/ecs}/example.d.ts +0 -0
- /package/dist/{ecs → types/ecs}/index.d.ts +0 -0
- /package/dist/{ecs → types/ecs}/system-builder.d.ts +0 -0
- /package/dist/{ecs → types/ecs}/world-systems.d.ts +0 -0
- /package/dist/{game → types/game}/index.d.ts +0 -0
- /package/dist/{game → types/game}/loop/index.d.ts +0 -0
- /package/dist/{net → types/net}/adapters/browser-websocket.d.ts +0 -0
- /package/dist/{net → types/net}/adapters/bun-websocket.d.ts +0 -0
- /package/dist/{net → types/net}/buffer-pool.d.ts +0 -0
- /package/dist/{net → types/net}/client.d.ts +0 -0
- /package/dist/{net → types/net}/server.d.ts +0 -0
- /package/dist/{net → types/net}/types.d.ts +0 -0
- /package/dist/{net → types/net}/validators.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/index.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/intent/define-intent.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/intent/index.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/intent/intent-registry.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/intent/intent.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/rpc/define-rpc.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/rpc/index.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/rpc/rpc-registry.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/rpc/rpc.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/snapshot/index.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/snapshot/snapshot-codec.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/snapshot/snapshot-registry.d.ts +0 -0
- /package/dist/{protocol → types/protocol}/snapshot/snapshot.d.ts +0 -0
- /package/dist/{core/input/types.js → webgpu/types/2d/animation.test.d.ts} +0 -0
- /package/dist/{protocol/intent/intent.js → webgpu/types/2d/sprite-accessor.test.d.ts} +0 -0
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from "bun:test";
|
|
2
|
-
import { SnapshotRegistry } from "./snapshot-registry";
|
|
3
|
-
import { Snapshot } from "./snapshot";
|
|
4
|
-
|
|
5
|
-
// Mock codec for testing
|
|
6
|
-
class MockCodec<T> {
|
|
7
|
-
encode(value: T): Uint8Array {
|
|
8
|
-
const json = JSON.stringify(value);
|
|
9
|
-
return new TextEncoder().encode(json);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
decode(buf: Uint8Array): T {
|
|
13
|
-
const json = new TextDecoder().decode(buf);
|
|
14
|
-
return JSON.parse(json);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Test update types
|
|
19
|
-
interface PlayerUpdate {
|
|
20
|
-
players: Array<{ entityId: number; x: number; y: number }>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface ScoreUpdate {
|
|
24
|
-
score: number;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
interface ProjectileUpdate {
|
|
28
|
-
projectiles: Array<{ id: number; x: number; y: number }>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
type GameUpdate = PlayerUpdate & ScoreUpdate & ProjectileUpdate;
|
|
32
|
-
|
|
33
|
-
describe("SnapshotRegistry", () => {
|
|
34
|
-
let registry: SnapshotRegistry<GameUpdate>;
|
|
35
|
-
|
|
36
|
-
beforeEach(() => {
|
|
37
|
-
registry = new SnapshotRegistry<GameUpdate>();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe("register", () => {
|
|
41
|
-
it("should register a codec for a snapshot type", () => {
|
|
42
|
-
registry.register("players", new MockCodec<PlayerUpdate>());
|
|
43
|
-
expect(registry.has("players")).toBe(true);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("should throw error when registering duplicate type", () => {
|
|
47
|
-
registry.register("players", new MockCodec<PlayerUpdate>());
|
|
48
|
-
expect(() => registry.register("players", new MockCodec<PlayerUpdate>())).toThrow(
|
|
49
|
-
'Snapshot type "players" is already registered'
|
|
50
|
-
);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("should allow registering multiple types", () => {
|
|
54
|
-
registry.register("players", new MockCodec<PlayerUpdate>());
|
|
55
|
-
registry.register("score", new MockCodec<ScoreUpdate>());
|
|
56
|
-
registry.register("projectiles", new MockCodec<ProjectileUpdate>());
|
|
57
|
-
|
|
58
|
-
expect(registry.has("players")).toBe(true);
|
|
59
|
-
expect(registry.has("score")).toBe(true);
|
|
60
|
-
expect(registry.has("projectiles")).toBe(true);
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
describe("encode", () => {
|
|
65
|
-
beforeEach(() => {
|
|
66
|
-
registry.register("players", new MockCodec<PlayerUpdate>());
|
|
67
|
-
registry.register("score", new MockCodec<ScoreUpdate>());
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("should encode a snapshot with type ID", () => {
|
|
71
|
-
const snapshot: Snapshot<PlayerUpdate> = {
|
|
72
|
-
tick: 100,
|
|
73
|
-
updates: {
|
|
74
|
-
players: [
|
|
75
|
-
{ entityId: 1, x: 10, y: 20 },
|
|
76
|
-
],
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const buf = registry.encode("players", snapshot);
|
|
81
|
-
|
|
82
|
-
expect(buf).toBeInstanceOf(Uint8Array);
|
|
83
|
-
expect(buf.length).toBeGreaterThan(5); // type(1) + tick(4) + data
|
|
84
|
-
expect(buf[0]).toBe(0); // First registered type gets ID 0
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it("should encode different types with different type IDs", () => {
|
|
88
|
-
const playerSnapshot: Snapshot<PlayerUpdate> = {
|
|
89
|
-
tick: 100,
|
|
90
|
-
updates: { players: [{ entityId: 1, x: 10, y: 20 }] },
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const scoreSnapshot: Snapshot<ScoreUpdate> = {
|
|
94
|
-
tick: 101,
|
|
95
|
-
updates: { score: 50 },
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const buf1 = registry.encode("players", playerSnapshot);
|
|
99
|
-
const buf2 = registry.encode("score", scoreSnapshot);
|
|
100
|
-
|
|
101
|
-
expect(buf1[0]).toBe(0); // players = ID 0
|
|
102
|
-
expect(buf2[0]).toBe(1); // score = ID 1
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it("should throw error when encoding unregistered type", () => {
|
|
106
|
-
const snapshot: Snapshot<ProjectileUpdate> = {
|
|
107
|
-
tick: 100,
|
|
108
|
-
updates: { projectiles: [] },
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
expect(() => registry.encode("projectiles", snapshot)).toThrow(
|
|
112
|
-
'No codec registered for snapshot type "projectiles"'
|
|
113
|
-
);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it("should preserve tick number in encoding", () => {
|
|
117
|
-
const snapshot: Snapshot<ScoreUpdate> = {
|
|
118
|
-
tick: 12345,
|
|
119
|
-
updates: { score: 100 },
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const buf = registry.encode("score", snapshot);
|
|
123
|
-
|
|
124
|
-
// Tick is at bytes 1-4 (after type ID)
|
|
125
|
-
const tick = new DataView(buf.buffer, buf.byteOffset + 1).getUint32(0, true);
|
|
126
|
-
expect(tick).toBe(12345);
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
describe("decode", () => {
|
|
131
|
-
beforeEach(() => {
|
|
132
|
-
registry.register("players", new MockCodec<PlayerUpdate>());
|
|
133
|
-
registry.register("score", new MockCodec<ScoreUpdate>());
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it("should decode a snapshot and return type", () => {
|
|
137
|
-
const original: Snapshot<PlayerUpdate> = {
|
|
138
|
-
tick: 100,
|
|
139
|
-
updates: {
|
|
140
|
-
players: [
|
|
141
|
-
{ entityId: 1, x: 10, y: 20 },
|
|
142
|
-
],
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
const buf = registry.encode("players", original);
|
|
147
|
-
const { type, snapshot } = registry.decode<PlayerUpdate>(buf);
|
|
148
|
-
|
|
149
|
-
expect(type).toBe("players");
|
|
150
|
-
expect(snapshot.tick).toBe(100);
|
|
151
|
-
expect(snapshot.updates).toEqual(original.updates);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it("should decode different snapshot types correctly", () => {
|
|
155
|
-
const playerSnapshot: Snapshot<PlayerUpdate> = {
|
|
156
|
-
tick: 100,
|
|
157
|
-
updates: { players: [{ entityId: 1, x: 10, y: 20 }] },
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
const scoreSnapshot: Snapshot<ScoreUpdate> = {
|
|
161
|
-
tick: 101,
|
|
162
|
-
updates: { score: 50 },
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
const buf1 = registry.encode("players", playerSnapshot);
|
|
166
|
-
const buf2 = registry.encode("score", scoreSnapshot);
|
|
167
|
-
|
|
168
|
-
const decoded1 = registry.decode(buf1);
|
|
169
|
-
const decoded2 = registry.decode(buf2);
|
|
170
|
-
|
|
171
|
-
expect(decoded1.type).toBe("players");
|
|
172
|
-
expect(decoded1.snapshot.updates).toEqual(playerSnapshot.updates);
|
|
173
|
-
|
|
174
|
-
expect(decoded2.type).toBe("score");
|
|
175
|
-
expect(decoded2.snapshot.updates).toEqual(scoreSnapshot.updates);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it("should throw error when decoding unknown type ID", () => {
|
|
179
|
-
const buf = new Uint8Array([99, 0, 0, 0, 100]); // Unknown type ID 99
|
|
180
|
-
|
|
181
|
-
expect(() => registry.decode(buf)).toThrow("Unknown snapshot type ID: 99");
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
describe("round-trip encoding/decoding", () => {
|
|
186
|
-
beforeEach(() => {
|
|
187
|
-
registry.register("players", new MockCodec<PlayerUpdate>());
|
|
188
|
-
registry.register("score", new MockCodec<ScoreUpdate>());
|
|
189
|
-
registry.register("projectiles", new MockCodec<ProjectileUpdate>());
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("should preserve data through encode/decode cycle", () => {
|
|
193
|
-
const original: Snapshot<PlayerUpdate> = {
|
|
194
|
-
tick: 500,
|
|
195
|
-
updates: {
|
|
196
|
-
players: [
|
|
197
|
-
{ entityId: 1, x: 100, y: 200 },
|
|
198
|
-
{ entityId: 2, x: 300, y: 400 },
|
|
199
|
-
],
|
|
200
|
-
},
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
const buf = registry.encode("players", original);
|
|
204
|
-
const { type, snapshot } = registry.decode(buf);
|
|
205
|
-
|
|
206
|
-
expect(type).toBe("players");
|
|
207
|
-
expect(snapshot).toEqual(original);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
it("should handle multiple round-trips", () => {
|
|
211
|
-
const original: Snapshot<ScoreUpdate> = {
|
|
212
|
-
tick: 1000,
|
|
213
|
-
updates: { score: 99999 },
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
for (let i = 0; i < 10; i++) {
|
|
217
|
-
const buf = registry.encode("score", original);
|
|
218
|
-
const { type, snapshot } = registry.decode(buf);
|
|
219
|
-
expect(type).toBe("score");
|
|
220
|
-
expect(snapshot).toEqual(original);
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it("should handle arrays in updates", () => {
|
|
225
|
-
const original: Snapshot<ProjectileUpdate> = {
|
|
226
|
-
tick: 250,
|
|
227
|
-
updates: {
|
|
228
|
-
projectiles: [
|
|
229
|
-
{ id: 1, x: 10, y: 20 },
|
|
230
|
-
{ id: 2, x: 30, y: 40 },
|
|
231
|
-
{ id: 3, x: 50, y: 60 },
|
|
232
|
-
],
|
|
233
|
-
},
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
const buf = registry.encode("projectiles", original);
|
|
237
|
-
const { type, snapshot } = registry.decode(buf);
|
|
238
|
-
|
|
239
|
-
expect(type).toBe("projectiles");
|
|
240
|
-
expect(snapshot.updates).toEqual(original.updates);
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
describe("getTypes", () => {
|
|
245
|
-
it("should return empty array when no types registered", () => {
|
|
246
|
-
expect(registry.getTypes()).toEqual([]);
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it("should return all registered types", () => {
|
|
250
|
-
registry.register("players", new MockCodec<PlayerUpdate>());
|
|
251
|
-
registry.register("score", new MockCodec<ScoreUpdate>());
|
|
252
|
-
|
|
253
|
-
const types = registry.getTypes();
|
|
254
|
-
expect(types).toContain("players");
|
|
255
|
-
expect(types).toContain("score");
|
|
256
|
-
expect(types.length).toBe(2);
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
describe("integration scenarios", () => {
|
|
261
|
-
beforeEach(() => {
|
|
262
|
-
registry.register("players", new MockCodec<PlayerUpdate>());
|
|
263
|
-
registry.register("score", new MockCodec<ScoreUpdate>());
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
it("should allow sending only specific updates", () => {
|
|
267
|
-
// Server only sends player updates this tick
|
|
268
|
-
const playerBuf = registry.encode("players", {
|
|
269
|
-
tick: 100,
|
|
270
|
-
updates: { players: [{ entityId: 1, x: 5, y: 10 }] },
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// Next tick, only send score
|
|
274
|
-
const scoreBuf = registry.encode("score", {
|
|
275
|
-
tick: 101,
|
|
276
|
-
updates: { score: 100 },
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
// Client can decode both
|
|
280
|
-
const decoded1 = registry.decode(playerBuf);
|
|
281
|
-
const decoded2 = registry.decode(scoreBuf);
|
|
282
|
-
|
|
283
|
-
expect(decoded1.type).toBe("players");
|
|
284
|
-
expect(decoded2.type).toBe("score");
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it("should maintain type safety with unions", () => {
|
|
288
|
-
const snapshot: Snapshot<PlayerUpdate> = {
|
|
289
|
-
tick: 100,
|
|
290
|
-
updates: { players: [{ entityId: 1, x: 5, y: 10 }] },
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
const buf = registry.encode("players", snapshot);
|
|
294
|
-
const { type, snapshot: decoded } = registry.decode<GameUpdate>(buf);
|
|
295
|
-
|
|
296
|
-
if (('players' in decoded.updates)) {
|
|
297
|
-
decoded.updates.players!.forEach((p) => {
|
|
298
|
-
expect(typeof p.entityId).toBe("number");
|
|
299
|
-
expect(typeof p.x).toBe("number");
|
|
300
|
-
expect(typeof p.y).toBe("number");
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Type narrowing based on type field
|
|
305
|
-
expect(type).toBe("players");
|
|
306
|
-
expect(type in decoded.updates).toBeDefined();
|
|
307
|
-
expect(type in decoded.updates).toBe(true);
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
});
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import type { Snapshot } from "./snapshot";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Generic codec interface (users import from core/pooled-codec)
|
|
5
|
-
*/
|
|
6
|
-
interface Codec<T> {
|
|
7
|
-
encode(value: T): Uint8Array;
|
|
8
|
-
decode(buf: Uint8Array): T;
|
|
9
|
-
calculateSize?(value: T): number;
|
|
10
|
-
encodeInto?(value: T, buffer: Uint8Array, offset: number): number;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Registry for multiple snapshot types with different update schemas.
|
|
15
|
-
*
|
|
16
|
-
* This allows efficient delta encoding by only sending specific update types
|
|
17
|
-
* instead of encoding all fields (including empty/nil ones).
|
|
18
|
-
*
|
|
19
|
-
* ## Memory Efficiency
|
|
20
|
-
*
|
|
21
|
-
* The encoding path minimizes allocations:
|
|
22
|
-
* 1. PooledCodec acquires a buffer from its pool (reused across calls)
|
|
23
|
-
* 2. PooledCodec writes data directly to the buffer at sequential offsets
|
|
24
|
-
* 3. SnapshotRegistry creates ONE final buffer: [typeId(1) + tick(4) + updatesBytes]
|
|
25
|
-
* 4. Total allocations per encode: 1 pooled buffer + 1 final buffer
|
|
26
|
-
*
|
|
27
|
-
* Buffer Layout:
|
|
28
|
-
* ```
|
|
29
|
-
* ┌─────────┬────────────┬──────────────────┐
|
|
30
|
-
* │ Type ID │ Tick │ Updates (codec) │
|
|
31
|
-
* │ (u8) │ (u32) │ (variable) │
|
|
32
|
-
* │ 1 byte │ 4 bytes │ N bytes │
|
|
33
|
-
* └─────────┴────────────┴──────────────────┘
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* ```ts
|
|
38
|
-
* import { SnapshotRegistry } from './protocol/snapshot';
|
|
39
|
-
* import { PooledCodec } from './core/pooled-codec';
|
|
40
|
-
* import { BinaryPrimitives } from './core/binary-codec';
|
|
41
|
-
*
|
|
42
|
-
* // Define different update types
|
|
43
|
-
* interface PlayerUpdate {
|
|
44
|
-
* players: Array<{ entityId: number; x: number; y: number }>;
|
|
45
|
-
* }
|
|
46
|
-
*
|
|
47
|
-
* interface ScoreUpdate {
|
|
48
|
-
* score: number;
|
|
49
|
-
* }
|
|
50
|
-
*
|
|
51
|
-
* // Create registry
|
|
52
|
-
* const registry = new SnapshotRegistry<PlayerUpdate | ScoreUpdate>();
|
|
53
|
-
*
|
|
54
|
-
* // Register codecs for each update type
|
|
55
|
-
* registry.register('players', new PooledCodec({
|
|
56
|
-
* players: PooledCodec.array({
|
|
57
|
-
* entityId: BinaryPrimitives.u32,
|
|
58
|
-
* x: BinaryPrimitives.f32,
|
|
59
|
-
* y: BinaryPrimitives.f32,
|
|
60
|
-
* })
|
|
61
|
-
* }));
|
|
62
|
-
*
|
|
63
|
-
* registry.register('score', new PooledCodec({
|
|
64
|
-
* score: BinaryPrimitives.u32
|
|
65
|
-
* }));
|
|
66
|
-
*
|
|
67
|
-
* // Server: Encode specific update type
|
|
68
|
-
* const buf = registry.encode('players', {
|
|
69
|
-
* tick: 100,
|
|
70
|
-
* updates: { players: [{ entityId: 1, x: 5, y: 10 }] }
|
|
71
|
-
* });
|
|
72
|
-
*
|
|
73
|
-
* // Client: Decode (type is embedded in message)
|
|
74
|
-
* const { type, snapshot } = registry.decode(buf);
|
|
75
|
-
* applySnapshot(state, snapshot);
|
|
76
|
-
* ```
|
|
77
|
-
*/
|
|
78
|
-
export class SnapshotRegistry<T extends Object = {}> {
|
|
79
|
-
private codecs = new Map<string, Codec<any>>();
|
|
80
|
-
private typeIds = new Map<string, number>();
|
|
81
|
-
private idToType = new Map<number, string>();
|
|
82
|
-
private nextId = 0;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Register a codec for a specific update type.
|
|
86
|
-
* Call this once per update type at startup.
|
|
87
|
-
*/
|
|
88
|
-
register<U extends Partial<T>>(type: string, codec: Codec<U>): void {
|
|
89
|
-
if (this.codecs.has(type)) {
|
|
90
|
-
throw new Error(`Snapshot type "${type}" is already registered`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const typeId = this.nextId++;
|
|
94
|
-
this.codecs.set(type, codec);
|
|
95
|
-
this.typeIds.set(type, typeId);
|
|
96
|
-
this.idToType.set(typeId, type);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Encode a snapshot with a specific update type.
|
|
101
|
-
* Format: [typeId: u8][tick: u32][updates: encoded by codec]
|
|
102
|
-
*
|
|
103
|
-
* Zero-copy encoding path:
|
|
104
|
-
* - Calculate total size needed
|
|
105
|
-
* - Allocate ONE final buffer for [typeId + tick + updates]
|
|
106
|
-
* - Write directly into buffer using encodeInto (no intermediate allocations)
|
|
107
|
-
*
|
|
108
|
-
* Falls back to legacy encode() method if codec doesn't support encodeInto.
|
|
109
|
-
*/
|
|
110
|
-
encode<U extends Partial<T>>(type: string, snapshot: Snapshot<U>): Uint8Array {
|
|
111
|
-
const codec = this.codecs.get(type);
|
|
112
|
-
const typeId = this.typeIds.get(type);
|
|
113
|
-
|
|
114
|
-
if (!codec || typeId === undefined) {
|
|
115
|
-
throw new Error(`No codec registered for snapshot type "${type}"`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Use zero-copy path if available
|
|
119
|
-
if (codec.calculateSize && codec.encodeInto) {
|
|
120
|
-
// Calculate total size
|
|
121
|
-
const updatesSize = codec.calculateSize(snapshot.updates);
|
|
122
|
-
const buf = new Uint8Array(5 + updatesSize);
|
|
123
|
-
|
|
124
|
-
// Write type ID (1 byte)
|
|
125
|
-
buf[0] = typeId;
|
|
126
|
-
|
|
127
|
-
// Write tick (4 bytes, little-endian)
|
|
128
|
-
new DataView(buf.buffer).setUint32(1, snapshot.tick, true);
|
|
129
|
-
|
|
130
|
-
// Write updates directly into buffer (ZERO COPY!)
|
|
131
|
-
codec.encodeInto(snapshot.updates, buf, 5);
|
|
132
|
-
|
|
133
|
-
return buf;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Fallback to legacy path for backward compatibility
|
|
137
|
-
const updatesBytes = codec.encode(snapshot.updates);
|
|
138
|
-
const buf = new Uint8Array(1 + 4 + updatesBytes.length);
|
|
139
|
-
|
|
140
|
-
buf[0] = typeId;
|
|
141
|
-
new DataView(buf.buffer).setUint32(1, snapshot.tick, true);
|
|
142
|
-
buf.set(updatesBytes, 5);
|
|
143
|
-
|
|
144
|
-
return buf;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Decode a snapshot and return both the type and the snapshot.
|
|
149
|
-
*/
|
|
150
|
-
decode<U extends Partial<T> = Partial<T>>(buf: Uint8Array): { type: string; snapshot: Snapshot<U> } {
|
|
151
|
-
// Decode type ID (first byte)
|
|
152
|
-
const typeId = buf[0];
|
|
153
|
-
const type = this.idToType.get(typeId);
|
|
154
|
-
|
|
155
|
-
if (!type) {
|
|
156
|
-
throw new Error(`Unknown snapshot type ID: ${typeId}`);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const codec = this.codecs.get(type);
|
|
160
|
-
if (!codec) {
|
|
161
|
-
throw new Error(`No codec registered for snapshot type "${type}"`);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Decode tick (bytes 1-4)
|
|
165
|
-
const tick = new DataView(buf.buffer, buf.byteOffset + 1).getUint32(0, true);
|
|
166
|
-
|
|
167
|
-
// Decode updates (remaining bytes)
|
|
168
|
-
const updatesBytes = buf.subarray(5);
|
|
169
|
-
const updates = codec.decode(updatesBytes) as U;
|
|
170
|
-
|
|
171
|
-
return { type, snapshot: { tick, updates } };
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
has(type: string): boolean {
|
|
175
|
-
return this.codecs.has(type);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
getTypes(): string[] {
|
|
179
|
-
return Array.from(this.codecs.keys());
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Release a decoded snapshot's updates object back to the pool.
|
|
184
|
-
* Call this after you're done processing the snapshot to enable object pooling.
|
|
185
|
-
*
|
|
186
|
-
* @param type The snapshot type (same as used in decode)
|
|
187
|
-
* @param updates The updates object to release
|
|
188
|
-
*/
|
|
189
|
-
release<U extends Partial<T>>(type: string, updates: U): void {
|
|
190
|
-
const codec = this.codecs.get(type);
|
|
191
|
-
|
|
192
|
-
if (!codec) {
|
|
193
|
-
throw new Error(`No codec registered for snapshot type "${type}"`);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Only release if the codec supports pooling
|
|
197
|
-
if ('release' in codec && typeof codec.release === 'function') {
|
|
198
|
-
codec.release(updates);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "bun:test";
|
|
2
|
-
import { Snapshot, applySnapshot } from "./snapshot";
|
|
3
|
-
|
|
4
|
-
interface TestState {
|
|
5
|
-
x: number;
|
|
6
|
-
y: number;
|
|
7
|
-
health?: number;
|
|
8
|
-
nested?: {
|
|
9
|
-
a: number;
|
|
10
|
-
b?: number;
|
|
11
|
-
};
|
|
12
|
-
items?: string[];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
describe("Snapshot", () => {
|
|
16
|
-
describe("applySnapshot", () => {
|
|
17
|
-
it("should apply simple property updates", () => {
|
|
18
|
-
const state: TestState = { x: 0, y: 0 };
|
|
19
|
-
const snapshot: Snapshot<TestState> = {
|
|
20
|
-
tick: 100,
|
|
21
|
-
updates: { x: 10, y: 20 },
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
applySnapshot(state, snapshot);
|
|
25
|
-
expect(state.x).toBe(10);
|
|
26
|
-
expect(state.y).toBe(20);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("should apply partial updates without affecting other properties", () => {
|
|
30
|
-
const state: TestState = { x: 0, y: 0, health: 100 };
|
|
31
|
-
const snapshot: Snapshot<TestState> = {
|
|
32
|
-
tick: 100,
|
|
33
|
-
updates: { x: 10 },
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
applySnapshot(state, snapshot);
|
|
37
|
-
expect(state.x).toBe(10);
|
|
38
|
-
expect(state.y).toBe(0);
|
|
39
|
-
expect(state.health).toBe(100);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("should handle nested object updates", () => {
|
|
43
|
-
const state: TestState = { x: 0, y: 0, nested: { a: 1, b: 2 } };
|
|
44
|
-
const snapshot: Snapshot<TestState> = {
|
|
45
|
-
tick: 100,
|
|
46
|
-
updates: { nested: { a: 10 } },
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
applySnapshot(state, snapshot);
|
|
50
|
-
expect(state.nested?.a).toBe(10);
|
|
51
|
-
expect(state.nested?.b).toBe(2);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("should replace arrays entirely", () => {
|
|
55
|
-
const state: TestState = { x: 0, y: 0, items: ["a", "b", "c"] };
|
|
56
|
-
const snapshot: Snapshot<TestState> = {
|
|
57
|
-
tick: 100,
|
|
58
|
-
updates: { items: ["x", "y"] },
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
applySnapshot(state, snapshot);
|
|
62
|
-
expect(state.items).toEqual(["x", "y"]);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it("should handle null values", () => {
|
|
66
|
-
const state: TestState = { x: 0, y: 0, health: 100 };
|
|
67
|
-
const snapshot: Snapshot<TestState> = {
|
|
68
|
-
tick: 100,
|
|
69
|
-
updates: { health: null as any },
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
applySnapshot(state, snapshot);
|
|
73
|
-
expect(state.health).toBeNull();
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Server-authoritative snapshot with delta updates.
|
|
3
|
-
*
|
|
4
|
-
* @template T The full state type
|
|
5
|
-
*/
|
|
6
|
-
export interface Snapshot<T> {
|
|
7
|
-
/** Server tick when this snapshot was created */
|
|
8
|
-
tick: number;
|
|
9
|
-
/** Partial state updates (only what changed) */
|
|
10
|
-
updates: Partial<T>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Apply snapshot updates to state (mutating).
|
|
15
|
-
* Deep merges objects, replaces arrays.
|
|
16
|
-
*
|
|
17
|
-
* @param state State to update
|
|
18
|
-
* @param snapshot Snapshot to apply
|
|
19
|
-
*/
|
|
20
|
-
export function applySnapshot<T>(state: T, snapshot: Snapshot<T>): void {
|
|
21
|
-
deepMerge(state, snapshot.updates);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function deepMerge<T>(target: T, update: Partial<T>): void {
|
|
25
|
-
for (const key in update) {
|
|
26
|
-
if (!Object.prototype.hasOwnProperty.call(update, key)) continue;
|
|
27
|
-
|
|
28
|
-
const updateValue = update[key];
|
|
29
|
-
const targetValue = target[key];
|
|
30
|
-
|
|
31
|
-
if (updateValue === null || updateValue === undefined) {
|
|
32
|
-
target[key] = updateValue as T[Extract<keyof T, string>];
|
|
33
|
-
} else if (Array.isArray(updateValue)) {
|
|
34
|
-
target[key] = updateValue as T[Extract<keyof T, string>];
|
|
35
|
-
} else if (typeof updateValue === "object" && typeof targetValue === "object") {
|
|
36
|
-
deepMerge(targetValue as any, updateValue as any);
|
|
37
|
-
} else {
|
|
38
|
-
target[key] = updateValue as T[Extract<keyof T, string>];
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|