@downdraft/engine 0.0.0 → 0.1.1
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 +33 -0
- package/app/src/index.ts +10 -0
- package/app/src/renderer/bootstrap.ts +271 -0
- package/app/src/renderer/downdraft-base.css +93 -0
- package/app/src/renderer/feature-log.ts +200 -0
- package/app/src/renderer/game-module.ts +923 -0
- package/app/src/renderer/hooks.ts +88 -0
- package/app/src/renderer/hot-reload.ts +178 -0
- package/app/src/renderer/import-cache.ts +88 -0
- package/app/src/renderer/index.ts +206 -0
- package/app/src/renderer/mcp-harness.ts +144 -0
- package/app/src/renderer/save-store-factory.ts +239 -0
- package/app/src/renderer/sim-bridge.ts +183 -0
- package/app/src/renderer/standard-automation-tools.ts +771 -0
- package/app/src/shared/feature-log.ts +71 -0
- package/app/src/shared/gpu-info.ts +82 -0
- package/app/src/shared/import-cache-store.ts +142 -0
- package/app/src/shared/index.ts +6 -0
- package/app/src/shared/mcp-discovery.ts +47 -0
- package/app/src/shared/mcp-proxy.ts +82 -0
- package/app/src/shared/types.ts +324 -0
- package/asset-bake/src/bake-audio.ts +119 -0
- package/asset-bake/src/bake-gltf.ts +172 -0
- package/asset-bake/src/bake.ts +78 -0
- package/asset-bake/src/cache.ts +188 -0
- package/asset-bake/src/config.ts +186 -0
- package/asset-bake/src/index.ts +36 -0
- package/core/src/animation/animation-event.ts +41 -0
- package/core/src/animation/bone-mask.ts +122 -0
- package/core/src/animation/clip.ts +252 -0
- package/core/src/animation/index.ts +22 -0
- package/core/src/animation/mixamo.ts +113 -0
- package/core/src/animation/morph-target.ts +69 -0
- package/core/src/animation/player.ts +697 -0
- package/core/src/animation/retarget.ts +158 -0
- package/core/src/animation/skeleton-animator.ts +1399 -0
- package/core/src/animation/skeleton.ts +214 -0
- package/core/src/animation/state-machine.ts +280 -0
- package/core/src/assets/blob-store.ts +66 -0
- package/core/src/assets/cache.ts +186 -0
- package/core/src/assets/cubemap-converter.ts +155 -0
- package/core/src/assets/environment-manager.ts +121 -0
- package/core/src/assets/import-cache.ts +65 -0
- package/core/src/assets/import-settings.ts +72 -0
- package/core/src/assets/importer.ts +108 -0
- package/core/src/assets/index.ts +74 -0
- package/core/src/assets/irradiance-generator.ts +198 -0
- package/core/src/assets/loader-audio.ts +86 -0
- package/core/src/assets/loader-cubemap.ts +211 -0
- package/core/src/assets/loader-dds.ts +236 -0
- package/core/src/assets/loader-hdr.ts +474 -0
- package/core/src/assets/loader-mesh.ts +143 -0
- package/core/src/assets/loader-shader.ts +73 -0
- package/core/src/assets/loader-texture.ts +349 -0
- package/core/src/assets/lod.ts +198 -0
- package/core/src/assets/manager.ts +480 -0
- package/core/src/assets/manifest.ts +81 -0
- package/core/src/assets/material-bridge.ts +186 -0
- package/core/src/assets/model-importer.ts +72 -0
- package/core/src/assets/model-normalizer.ts +248 -0
- package/core/src/assets/model-to-gpu.ts +70 -0
- package/core/src/assets/model-to-mesh.ts +237 -0
- package/core/src/assets/prefilter-generator.ts +250 -0
- package/core/src/audio/engine.ts +177 -0
- package/core/src/audio/interface.ts +130 -0
- package/core/src/audio/listener.ts +32 -0
- package/core/src/audio/mixer.ts +141 -0
- package/core/src/audio/registry.ts +52 -0
- package/core/src/audio/sab.ts +87 -0
- package/core/src/audio/source.ts +89 -0
- package/core/src/change-detection/atomics.ts +1 -0
- package/core/src/change-detection/tracker.ts +47 -0
- package/core/src/debug-draw/lines.ts +64 -0
- package/core/src/debug-draw/points.ts +17 -0
- package/core/src/debug-draw/queue.ts +124 -0
- package/core/src/debug-draw/text.ts +25 -0
- package/core/src/ecs/archetype.ts +323 -0
- package/core/src/ecs/component.ts +188 -0
- package/core/src/ecs/entity.ts +25 -0
- package/core/src/ecs/events.ts +93 -0
- package/core/src/ecs/hierarchy.ts +124 -0
- package/core/src/ecs/hmr-swap-registry.ts +22 -0
- package/core/src/ecs/index.ts +25 -0
- package/core/src/ecs/query.ts +141 -0
- package/core/src/ecs/resource.ts +8 -0
- package/core/src/ecs/schedule.ts +181 -0
- package/core/src/ecs/system-params.ts +99 -0
- package/core/src/ecs/system.ts +42 -0
- package/core/src/ecs/world.ts +348 -0
- package/core/src/index.ts +352 -0
- package/core/src/input/context.ts +73 -0
- package/core/src/input/dom-handler.ts +380 -0
- package/core/src/input/local-player-manager.ts +218 -0
- package/core/src/input/mapping.ts +40 -0
- package/core/src/input/multi-sab-bridge.ts +276 -0
- package/core/src/input/multi-state.ts +54 -0
- package/core/src/input/sab-bridge.ts +71 -0
- package/core/src/input/state.ts +132 -0
- package/core/src/input/ui-router.ts +87 -0
- package/core/src/library/host.ts +317 -0
- package/core/src/library/index.ts +16 -0
- package/core/src/library/library.ts +292 -0
- package/core/src/material/compiler.ts +80 -0
- package/core/src/material/graph-bridge.ts +172 -0
- package/core/src/material/index.ts +9 -0
- package/core/src/material/library.ts +442 -0
- package/core/src/material/material.ts +156 -0
- package/core/src/material/variants.ts +61 -0
- package/core/src/math/mat4.ts +202 -0
- package/core/src/math/perlin-noise-2d.ts +77 -0
- package/core/src/math/perlin-noise-3d.ts +110 -0
- package/core/src/math/quat.ts +33 -0
- package/core/src/math/rng.ts +29 -0
- package/core/src/math/trig.ts +47 -0
- package/core/src/math/value-noise.ts +67 -0
- package/core/src/mesh/builder.ts +177 -0
- package/core/src/mesh/csg.ts +312 -0
- package/core/src/mesh/greased-line.ts +145 -0
- package/core/src/mesh/mesh.ts +17 -0
- package/core/src/mesh/parametric.ts +501 -0
- package/core/src/mesh/skinning.ts +67 -0
- package/core/src/mesh/vertex-layout.ts +91 -0
- package/core/src/module/cross-thread.ts +163 -0
- package/core/src/module/diagnostics.ts +123 -0
- package/core/src/module/host.ts +451 -0
- package/core/src/module/index.ts +22 -0
- package/core/src/module/module.ts +109 -0
- package/core/src/module/registry.ts +94 -0
- package/core/src/module/renderer-module.ts +247 -0
- package/core/src/module/ts-loader.ts +26 -0
- package/core/src/particles/compute-pass.ts +378 -0
- package/core/src/particles/emitter.ts +156 -0
- package/core/src/particles/index.ts +11 -0
- package/core/src/particles/particle-data.ts +47 -0
- package/core/src/particles/render-pass.ts +365 -0
- package/core/src/particles/simulator.ts +264 -0
- package/core/src/particles/system.ts +193 -0
- package/core/src/physics/body.ts +59 -0
- package/core/src/physics/ccd-heuristic.ts +55 -0
- package/core/src/physics/character.ts +282 -0
- package/core/src/physics/collider.ts +55 -0
- package/core/src/physics/collision-system.ts +91 -0
- package/core/src/physics/events.ts +133 -0
- package/core/src/physics/index.ts +34 -0
- package/core/src/physics/interface.ts +473 -0
- package/core/src/physics/interpolation-buffer.ts +192 -0
- package/core/src/physics/lifecycle.ts +87 -0
- package/core/src/physics/load-shedder.ts +164 -0
- package/core/src/physics/physics-accumulator.ts +101 -0
- package/core/src/physics/physics-system.ts +240 -0
- package/core/src/physics/ragdoll-presets.ts +272 -0
- package/core/src/physics/ragdoll-system.ts +220 -0
- package/core/src/physics/ragdoll.ts +182 -0
- package/core/src/physics/raycast.ts +143 -0
- package/core/src/physics/realm-manager.ts +499 -0
- package/core/src/physics/realm-worker-pool.ts +191 -0
- package/core/src/physics/realm-worker.ts +102 -0
- package/core/src/physics/realm.ts +189 -0
- package/core/src/physics/registry.ts +52 -0
- package/core/src/physics/safety.ts +247 -0
- package/core/src/physics/snapshot-manager.ts +141 -0
- package/core/src/physics/worker-protocol.ts +30 -0
- package/core/src/platform/bun-preload.ts +169 -0
- package/core/src/platform/css-stub.ts +4 -0
- package/core/src/platform/glob-polyfill.ts +124 -0
- package/core/src/platform/hidpi.ts +57 -0
- package/core/src/platform/render-surface.ts +77 -0
- package/core/src/platform/rpc.ts +98 -0
- package/core/src/platform/runtime.ts +132 -0
- package/core/src/plugin/context.ts +364 -0
- package/core/src/plugin/diagnostics.ts +61 -0
- package/core/src/plugin/discovery.ts +186 -0
- package/core/src/plugin/extension-loaders.ts +172 -0
- package/core/src/plugin/host.ts +659 -0
- package/core/src/plugin/index.ts +106 -0
- package/core/src/plugin/loader-asset.ts +124 -0
- package/core/src/plugin/loader-quickjs.ts +84 -0
- package/core/src/plugin/loader-wasm.ts +411 -0
- package/core/src/plugin/loader-worker.ts +261 -0
- package/core/src/plugin/manifest.ts +653 -0
- package/core/src/plugin/material-registry.ts +65 -0
- package/core/src/plugin/mcp-tools.ts +165 -0
- package/core/src/plugin/permissions.ts +175 -0
- package/core/src/plugin/quickjs-bridge.ts +294 -0
- package/core/src/plugin/registry.ts +107 -0
- package/core/src/plugin/sandbox-shim.ts +86 -0
- package/core/src/plugin/sandbox-worker.ts +215 -0
- package/core/src/plugin/wasm-abi.ts +152 -0
- package/core/src/plugin/wasm-worker.ts +229 -0
- package/core/src/plugin/workshop.ts +169 -0
- package/core/src/profiling/event-loop.ts +180 -0
- package/core/src/profiling/index.ts +69 -0
- package/core/src/profiling/iops/idb-patch.ts +242 -0
- package/core/src/profiling/iops/opfs-patch.ts +276 -0
- package/core/src/profiling/profiling-sab.ts +839 -0
- package/core/src/profiling/task-latency.ts +134 -0
- package/core/src/profiling/thread-metrics.ts +126 -0
- package/core/src/profiling/trace-event-writer.ts +205 -0
- package/core/src/profiling/warnings.ts +423 -0
- package/core/src/profiling/worker-prelude.ts +376 -0
- package/core/src/render/bind-group.ts +38 -0
- package/core/src/render/bindless/bindless-struct.ts +42 -0
- package/core/src/render/bindless/bindless.wgsl.ts +167 -0
- package/core/src/render/bindless/frame-bindings.ts +176 -0
- package/core/src/render/bindless/index.ts +10 -0
- package/core/src/render/bindless/material-manager.ts +257 -0
- package/core/src/render/bindless/texture-registry.ts +609 -0
- package/core/src/render/buffer.ts +82 -0
- package/core/src/render/camera-2d.ts +217 -0
- package/core/src/render/camera-controller.ts +440 -0
- package/core/src/render/camera.ts +409 -0
- package/core/src/render/canvas-resize-watcher.ts +46 -0
- package/core/src/render/compute-kernel.ts +172 -0
- package/core/src/render/constants.ts +2 -0
- package/core/src/render/device.ts +111 -0
- package/core/src/render/frame-graph.ts +768 -0
- package/core/src/render/frustum.ts +185 -0
- package/core/src/render/fullscreen-vs.ts +25 -0
- package/core/src/render/g-buffer.ts +186 -0
- package/core/src/render/game-renderer.ts +1452 -0
- package/core/src/render/gpu-driven/cull-pass.ts +394 -0
- package/core/src/render/gpu-driven/hzb.ts +215 -0
- package/core/src/render/gpu-driven/index.ts +7 -0
- package/core/src/render/gpu-driven/indirect-draw-pass.ts +324 -0
- package/core/src/render/gpu-driven/instance-buffer.ts +178 -0
- package/core/src/render/gpu-driven/mesh-table.ts +175 -0
- package/core/src/render/gpu-driven/passes/hzb-build-pass.ts +47 -0
- package/core/src/render/gpu-utils.ts +96 -0
- package/core/src/render/hdr.ts +88 -0
- package/core/src/render/hot-reload.ts +295 -0
- package/core/src/render/ibl-bind-group.ts +266 -0
- package/core/src/render/ibl.ts +180 -0
- package/core/src/render/index.ts +163 -0
- package/core/src/render/input-manager.ts +259 -0
- package/core/src/render/lighting/area-light.ts +196 -0
- package/core/src/render/lighting/cluster-grid.ts +288 -0
- package/core/src/render/lighting/cluster-types.ts +193 -0
- package/core/src/render/lighting/ies-parser.ts +162 -0
- package/core/src/render/lighting.ts +454 -0
- package/core/src/render/material-types/depth.wgsl +44 -0
- package/core/src/render/material-types/line.wgsl +50 -0
- package/core/src/render/material-types/matcap.wgsl +51 -0
- package/core/src/render/material-types/normal.wgsl +41 -0
- package/core/src/render/material-types/physical.wgsl +152 -0
- package/core/src/render/material-types/sprite.wgsl +46 -0
- package/core/src/render/material-types/sss.wgsl +79 -0
- package/core/src/render/material-types/toon.wgsl +79 -0
- package/core/src/render/passes/README.md +121 -0
- package/core/src/render/passes/atmosphere.ts +152 -0
- package/core/src/render/passes/cluster-lighting-pass.ts +476 -0
- package/core/src/render/passes/csm.ts +408 -0
- package/core/src/render/passes/cubemap-capture.ts +114 -0
- package/core/src/render/passes/debug-viz.ts +278 -0
- package/core/src/render/passes/debug.ts +538 -0
- package/core/src/render/passes/decal-mesh.ts +111 -0
- package/core/src/render/passes/decal-pass.ts +377 -0
- package/core/src/render/passes/deferred-lighting.ts +434 -0
- package/core/src/render/passes/depth-prepass.ts +163 -0
- package/core/src/render/passes/dome-360.ts +83 -0
- package/core/src/render/passes/fluid-render.ts +137 -0
- package/core/src/render/passes/gi-types.ts +118 -0
- package/core/src/render/passes/graph-compute.ts +300 -0
- package/core/src/render/passes/greased-line-pass.ts +232 -0
- package/core/src/render/passes/morph-target.ts +40 -0
- package/core/src/render/passes/opaque.ts +1028 -0
- package/core/src/render/passes/point-light-shadow.ts +266 -0
- package/core/src/render/passes/procedural-texture.ts +185 -0
- package/core/src/render/passes/reflection-probe.ts +140 -0
- package/core/src/render/passes/rsm-pass.ts +248 -0
- package/core/src/render/passes/sdf-text.ts +155 -0
- package/core/src/render/passes/shadow-map.ts +163 -0
- package/core/src/render/passes/shadow.ts +220 -0
- package/core/src/render/passes/skinning-vs.ts +121 -0
- package/core/src/render/passes/skinning.ts +326 -0
- package/core/src/render/passes/sky-dome.ts +404 -0
- package/core/src/render/passes/skybox.ts +162 -0
- package/core/src/render/passes/spot-light-shadow.ts +273 -0
- package/core/src/render/passes/terrain.ts +326 -0
- package/core/src/render/passes/transparent.ts +353 -0
- package/core/src/render/passes/underwater-fog.ts +185 -0
- package/core/src/render/passes/video-texture.ts +79 -0
- package/core/src/render/passes/volumetric-pass.ts +312 -0
- package/core/src/render/passes/volumetric-types.ts +171 -0
- package/core/src/render/passes/water.ts +753 -0
- package/core/src/render/pbr.ts +296 -0
- package/core/src/render/pipeline.ts +52 -0
- package/core/src/render/render-pass.ts +30 -0
- package/core/src/render/renderer-input-bus.ts +220 -0
- package/core/src/render/renderer-module-host.ts +623 -0
- package/core/src/render/resource-tracker.ts +67 -0
- package/core/src/render/sab-canvas-overlay.ts +122 -0
- package/core/src/render/shader-validator.ts +200 -0
- package/core/src/render/shaders/debug/debug-line.wgsl +27 -0
- package/core/src/render/shaders/debug/debug-point.wgsl +30 -0
- package/core/src/render/shaders/debug/debug-text.wgsl +42 -0
- package/core/src/render/shaders/debug-viz/aabb.wgsl +20 -0
- package/core/src/render/shaders/debug-viz/depth.wgsl +29 -0
- package/core/src/render/shaders/debug-viz/lod.wgsl +38 -0
- package/core/src/render/shaders/debug-viz/normals.wgsl +30 -0
- package/core/src/render/shaders/debug-viz/overdraw.wgsl +21 -0
- package/core/src/render/shaders/debug-viz/tangents.wgsl +29 -0
- package/core/src/render/shaders/debug-viz/wireframe.wgsl +33 -0
- package/core/src/render/shaders/shadow-chunks.ts +135 -0
- package/core/src/render/skybox.ts +146 -0
- package/core/src/render/splitscreen.ts +85 -0
- package/core/src/render/surface.ts +78 -0
- package/core/src/render/tonemap.ts +180 -0
- package/core/src/render/tracked-render-pass.ts +158 -0
- package/core/src/render/viewport.ts +109 -0
- package/core/src/render/wgsl-hmr.ts +70 -0
- package/core/src/sab/core-input-channel.ts +23 -0
- package/core/src/sab/define.ts +239 -0
- package/core/src/sab/errors.ts +76 -0
- package/core/src/sab/game-input.ts +343 -0
- package/core/src/sab/gamepad-devices.ts +259 -0
- package/core/src/sab/grid-buffer.ts +117 -0
- package/core/src/sab/input.ts +55 -0
- package/core/src/sab/layout.ts +219 -0
- package/core/src/sab/multi-input-channel.ts +50 -0
- package/core/src/sab/record-buffer.ts +155 -0
- package/core/src/sab/sab-polyfill.ts +56 -0
- package/core/src/sab/sim-channel.ts +453 -0
- package/core/src/sab/slot-buffer.ts +190 -0
- package/core/src/sab/types.ts +158 -0
- package/core/src/safety/bounds.ts +76 -0
- package/core/src/safety/json.ts +80 -0
- package/core/src/safety/path.ts +167 -0
- package/core/src/save/binary-format.ts +117 -0
- package/core/src/save/game-save-system.ts +161 -0
- package/core/src/save/grid-save-system.ts +158 -0
- package/core/src/save/migrate.ts +44 -0
- package/core/src/save/migration-registry.ts +94 -0
- package/core/src/save/persist-types.ts +208 -0
- package/core/src/save/schema.ts +46 -0
- package/core/src/save/serializer.ts +180 -0
- package/core/src/scene/builder.ts +65 -0
- package/core/src/scene/camera.ts +142 -0
- package/core/src/scene/checkpoint.ts +109 -0
- package/core/src/scene/game-loop.ts +198 -0
- package/core/src/scene/index.ts +24 -0
- package/core/src/scene/layer.ts +6 -0
- package/core/src/scene/prefab.ts +145 -0
- package/core/src/scene/scene-manager.ts +157 -0
- package/core/src/scene/scene.ts +192 -0
- package/core/src/scene/sky.ts +256 -0
- package/core/src/scene/spatial-grid.ts +176 -0
- package/core/src/scene/streaming.ts +304 -0
- package/core/src/scene/vegetation.ts +163 -0
- package/core/src/scene/world.ts +89 -0
- package/core/src/scripting/binding.ts +129 -0
- package/core/src/scripting/hot-reload.ts +144 -0
- package/core/src/scripting/script.ts +99 -0
- package/core/src/sim/hot-reload-pipeline.ts +49 -0
- package/core/src/sim/sim-state-helper.ts +47 -0
- package/core/src/sim/transient-state-registry.ts +77 -0
- package/core/src/sim/types.ts +113 -0
- package/core/src/sim/worker-loop.ts +222 -0
- package/core/src/stores/game-store.ts +158 -0
- package/core/src/stores/hot-reload-store.ts +44 -0
- package/core/src/telemetry/collector.ts +410 -0
- package/core/src/telemetry/gc-controller.ts +453 -0
- package/core/src/telemetry/gc-profiler.ts +126 -0
- package/core/src/telemetry/gc-tracker.ts +69 -0
- package/core/src/telemetry/gpu-profiler.ts +703 -0
- package/core/src/telemetry/gpu-resource-tracker.ts +285 -0
- package/core/src/telemetry/gpu-timer-pool.ts +234 -0
- package/core/src/telemetry/gpu-timer.ts +123 -0
- package/core/src/telemetry/gpu-timestamp-gate.ts +21 -0
- package/core/src/telemetry/reporter.ts +62 -0
- package/core/src/types/engine-types.ts +129 -0
- package/core/src/ui-font-scale.ts +112 -0
- package/core/src/util/broad-phase-grid.ts +82 -0
- package/core/src/util/feature-log.ts +220 -0
- package/core/src/util/index.ts +17 -0
- package/core/src/util/logger.ts +604 -0
- package/core/src/webgpu-destroy-augmentation.d.ts +25 -0
- package/core/src/worker/base-worker-host.ts +183 -0
- package/core/src/worker/buffer-sync.ts +550 -0
- package/core/src/worker/crash-recovery.ts +201 -0
- package/core/src/worker/entity-sim-worker-host.ts +190 -0
- package/core/src/worker/instrumented-worker-host.ts +171 -0
- package/core/src/worker/rpc.ts +253 -0
- package/core/src/worker/sim-worker-base.ts +913 -0
- package/core/src/worker/sim-worker-host.ts +358 -0
- package/core/src/worker/task-pool.ts +256 -0
- package/core/src/worker/task-worker.ts +83 -0
- package/libraries/asset-browser/src/index.ts +11 -0
- package/libraries/asset-browser/src/software-thumbnails.ts +949 -0
- package/libraries/audio-kira/README.md +17 -0
- package/libraries/audio-kira/native/Cargo.toml +14 -0
- package/libraries/audio-kira/native/src/engine.rs +27 -0
- package/libraries/audio-kira/native/src/lib.rs +185 -0
- package/libraries/audio-kira/native/src/mixer.rs +11 -0
- package/libraries/audio-kira/native/src/source.rs +80 -0
- package/libraries/audio-kira/src/backend.ts +469 -0
- package/libraries/audio-kira/src/index.ts +8 -0
- package/libraries/audio-kira/src/library.ts +82 -0
- package/libraries/blitz-ui/native/Cargo.toml +33 -0
- package/libraries/blitz-ui/native/assets/DejaVuSans.woff2 +0 -0
- package/libraries/blitz-ui/native/src/bridge.rs +100 -0
- package/libraries/blitz-ui/native/src/fonts.rs +20 -0
- package/libraries/blitz-ui/native/src/input.rs +80 -0
- package/libraries/blitz-ui/native/src/lib.rs +96 -0
- package/libraries/blitz-ui/native/src/shell.rs +301 -0
- package/libraries/blitz-ui/native-osr/Cargo.toml +24 -0
- package/libraries/blitz-ui/native-osr/src/events.rs +237 -0
- package/libraries/blitz-ui/native-osr/src/lib.rs +846 -0
- package/libraries/blitz-ui/native-osr/src/mutate.rs +385 -0
- package/libraries/blitz-ui/native-osr/src/resources.rs +45 -0
- package/libraries/blitz-ui/native-osr-spike.ts +70 -0
- package/libraries/blitz-ui/src/index.ts +15 -0
- package/libraries/blitz-ui/src/native-module.ts +221 -0
- package/libraries/blitz-ui/src/native-osr-ffi.ts +423 -0
- package/libraries/blitz-ui/src/router.ts +101 -0
- package/libraries/blitz-ui/src/shaders/ui-blit.wgsl.ts +35 -0
- package/libraries/blitz-ui/src/ui-blit-pass.ts +116 -0
- package/libraries/character/README.md +25 -0
- package/libraries/character/src/character-animator.ts +374 -0
- package/libraries/character/src/index.ts +24 -0
- package/libraries/character/src/loader.ts +375 -0
- package/libraries/character/src/locomotion.ts +124 -0
- package/libraries/character/src/preview.ts +287 -0
- package/libraries/devtools/README.md +51 -0
- package/libraries/devtools/native/Cargo.toml +12 -0
- package/libraries/devtools/native/src/lib.rs +1646 -0
- package/libraries/devtools/native/src/panels/console.rs +338 -0
- package/libraries/devtools/native/src/panels/dom_tree.rs +47 -0
- package/libraries/devtools/native/src/panels/generic.rs +317 -0
- package/libraries/devtools/native/src/panels/gpu.rs +107 -0
- package/libraries/devtools/native/src/panels/input.rs +88 -0
- package/libraries/devtools/native/src/panels/mod.rs +154 -0
- package/libraries/devtools/native/src/panels/perf_metrics.rs +91 -0
- package/libraries/devtools/native/src/panels/perf_recorder.rs +158 -0
- package/libraries/devtools/native/src/panels/scene.rs +72 -0
- package/libraries/devtools/native/src/state.rs +394 -0
- package/libraries/devtools/src/cdp-bridge.ts +349 -0
- package/libraries/devtools/src/collectors.ts +346 -0
- package/libraries/devtools/src/egui-ffi.ts +804 -0
- package/libraries/devtools/src/egui-renderer.ts +407 -0
- package/libraries/devtools/src/host.ts +363 -0
- package/libraries/devtools/src/index.ts +40 -0
- package/libraries/devtools/src/mirror.ts +794 -0
- package/libraries/devtools/src/native-providers.ts +744 -0
- package/libraries/devtools/src/verify.ts +167 -0
- package/libraries/devtools/src/web/browser.ts +102 -0
- package/libraries/devtools/src/web/host.ts +212 -0
- package/libraries/devtools/src/web/mirror.ts +430 -0
- package/libraries/devtools/src/web/server.ts +198 -0
- package/libraries/entities/README.md +17 -0
- package/libraries/entities/src/index.ts +4 -0
- package/libraries/entities/src/library.ts +64 -0
- package/libraries/entities/src/model-renderer.ts +1345 -0
- package/libraries/entities/src/shaders/model.wgsl +375 -0
- package/libraries/gamepad/src/feed-input.ts +83 -0
- package/libraries/gamepad/src/filters.ts +49 -0
- package/libraries/gamepad/src/glyphs.ts +93 -0
- package/libraries/gamepad/src/hub.ts +206 -0
- package/libraries/gamepad/src/index.ts +22 -0
- package/libraries/gamepad/src/library.ts +68 -0
- package/libraries/gamepad/src/source-sab.ts +70 -0
- package/libraries/gamepad/src/sysfs-enrich.ts +138 -0
- package/libraries/gaussian-splats/README.md +25 -0
- package/libraries/gaussian-splats/src/gpu-sort.ts +595 -0
- package/libraries/gaussian-splats/src/index.ts +31 -0
- package/libraries/gaussian-splats/src/library.ts +60 -0
- package/libraries/gaussian-splats/src/parser.ts +382 -0
- package/libraries/gaussian-splats/src/renderer.ts +427 -0
- package/libraries/gaussian-splats/src/sh-eval.ts +211 -0
- package/libraries/gaussian-splats/src/sorter.ts +110 -0
- package/libraries/gaussian-splats/src/tile-raster.ts +473 -0
- package/libraries/gpu-kernels/README.md +154 -0
- package/libraries/gpu-kernels/src/index.ts +11 -0
- package/libraries/gpu-kernels/src/kernel.ts +696 -0
- package/libraries/gpu-kernels/src/transpile.ts +958 -0
- package/libraries/html-ui-kit/src/behaviors.ts +250 -0
- package/libraries/html-ui-kit/src/components.ts +309 -0
- package/libraries/html-ui-kit/src/index.ts +30 -0
- package/libraries/html-ui-kit/src/nav/nav-controller.ts +238 -0
- package/libraries/html-ui-kit/src/nav/nav-input.ts +145 -0
- package/libraries/html-ui-kit/src/nav/osk.ts +153 -0
- package/libraries/html-ui-kit/src/nav/router.ts +167 -0
- package/libraries/html-ui-kit/src/nav/vcursor.ts +203 -0
- package/libraries/html-ui-kit/src/ten-foot.ts +182 -0
- package/libraries/html-ui-kit/src/theme.ts +238 -0
- package/libraries/lighting/README.md +20 -0
- package/libraries/lighting/src/index.ts +5 -0
- package/libraries/lighting/src/library.ts +66 -0
- package/libraries/lighting/src/light-system.ts +452 -0
- package/libraries/lighting/src/lighting-system.ts +68 -0
- package/libraries/lighting/src/shaders/light-debug.wgsl +30 -0
- package/libraries/marching-cubes/README.md +25 -0
- package/libraries/marching-cubes/src/chunked-field.ts +177 -0
- package/libraries/marching-cubes/src/deformation.ts +63 -0
- package/libraries/marching-cubes/src/generator.ts +407 -0
- package/libraries/marching-cubes/src/index.ts +32 -0
- package/libraries/marching-cubes/src/library.ts +80 -0
- package/libraries/marching-cubes/src/lod.ts +122 -0
- package/libraries/marching-cubes/src/marching-tetrahedra.ts +252 -0
- package/libraries/marching-cubes/src/sab.ts +45 -0
- package/libraries/marching-cubes/src/streaming-config.ts +48 -0
- package/libraries/marching-cubes/src/streaming-manager.ts +686 -0
- package/libraries/marching-cubes/src/tables.ts +323 -0
- package/libraries/marching-cubes/src/types.ts +18 -0
- package/libraries/models/README.md +25 -0
- package/libraries/models/src/bake-node-transforms.ts +171 -0
- package/libraries/models/src/codecs/basisu-codec.ts +180 -0
- package/libraries/models/src/codecs/draco-codec.ts +372 -0
- package/libraries/models/src/codecs/draco3dgltf.d.ts +40 -0
- package/libraries/models/src/codecs/index.ts +22 -0
- package/libraries/models/src/codecs/meshopt-codec.ts +91 -0
- package/libraries/models/src/codecs/registry.ts +221 -0
- package/libraries/models/src/dae.ts +753 -0
- package/libraries/models/src/default-part-selection.ts +56 -0
- package/libraries/models/src/dxf.ts +200 -0
- package/libraries/models/src/fbx/index.ts +457 -0
- package/libraries/models/src/fbx/interpreter/animation.ts +431 -0
- package/libraries/models/src/fbx/interpreter/blend-shapes.ts +323 -0
- package/libraries/models/src/fbx/interpreter/connections.ts +166 -0
- package/libraries/models/src/fbx/interpreter/diagnostics.ts +65 -0
- package/libraries/models/src/fbx/interpreter/geometry.ts +535 -0
- package/libraries/models/src/fbx/interpreter/global-settings.ts +92 -0
- package/libraries/models/src/fbx/interpreter/materials.ts +265 -0
- package/libraries/models/src/fbx/interpreter/nodes.ts +197 -0
- package/libraries/models/src/fbx/interpreter/skeleton.ts +476 -0
- package/libraries/models/src/fbx/parsers/binary-parser.ts +244 -0
- package/libraries/models/src/fbx/types.ts +119 -0
- package/libraries/models/src/gltf-extensions.ts +196 -0
- package/libraries/models/src/gltf.ts +935 -0
- package/libraries/models/src/index.ts +87 -0
- package/libraries/models/src/library.ts +75 -0
- package/libraries/models/src/loader.ts +265 -0
- package/libraries/models/src/material-adapter.ts +108 -0
- package/libraries/models/src/mini-xml.ts +174 -0
- package/libraries/models/src/normalize.ts +216 -0
- package/libraries/models/src/obj.ts +264 -0
- package/libraries/models/src/off.ts +95 -0
- package/libraries/models/src/ply.ts +348 -0
- package/libraries/models/src/pose-sampler.ts +219 -0
- package/libraries/models/src/sidecar/blender-extras.ts +37 -0
- package/libraries/models/src/sidecar/ddmeta.ts +114 -0
- package/libraries/models/src/sidecar/godot-import.ts +86 -0
- package/libraries/models/src/sidecar/resolver.ts +145 -0
- package/libraries/models/src/sidecar/types.ts +11 -0
- package/libraries/models/src/sidecar/unity-meta.ts +61 -0
- package/libraries/models/src/skeleton-synthesis.ts +132 -0
- package/libraries/models/src/stl.ts +149 -0
- package/libraries/models/src/threeds.ts +363 -0
- package/libraries/models/src/threemf.ts +201 -0
- package/libraries/models/src/types.ts +188 -0
- package/libraries/models/src/vtk.ts +218 -0
- package/libraries/models/test-fixtures/fbx/LICENSE-notice.txt +24 -0
- package/libraries/models/test-fixtures/fbx/README.md +46 -0
- package/libraries/models/test-fixtures/fbx/m01_cube_phong.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m02_geo_ngons.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m03_normals.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m04_material_properties.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m05_external_diffuse.png +0 -0
- package/libraries/models/test-fixtures/fbx/m05_textures.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m06_uv_transform.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m07_multimaterial.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m08_transforms.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m09_skinning.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m10_morph.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m11_node_anim.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m12_skeletal_anim.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m13_morph_anim.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m14_multiclip.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m15_camera_lights.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m16_axis_yup.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m16_axis_zup.fbx +0 -0
- package/libraries/models/test-fixtures/fbx/m16_units_254.fbx +0 -0
- package/libraries/navmesh/README.md +23 -0
- package/libraries/navmesh/src/crowd-system.ts +240 -0
- package/libraries/navmesh/src/debug-viz.ts +74 -0
- package/libraries/navmesh/src/index.ts +15 -0
- package/libraries/navmesh/src/library.ts +64 -0
- package/libraries/navmesh/src/navmesh-generator.ts +407 -0
- package/libraries/navmesh/src/navmesh.ts +159 -0
- package/libraries/navmesh/src/pathfinder.ts +252 -0
- package/libraries/navmesh/src/types.ts +63 -0
- package/libraries/networking/README.md +25 -0
- package/libraries/networking/src/authority.ts +121 -0
- package/libraries/networking/src/connection.ts +139 -0
- package/libraries/networking/src/discovery.ts +373 -0
- package/libraries/networking/src/enhanced-replication.ts +355 -0
- package/libraries/networking/src/epic-adapter.ts +129 -0
- package/libraries/networking/src/index.ts +45 -0
- package/libraries/networking/src/library.ts +69 -0
- package/libraries/networking/src/lobby.ts +108 -0
- package/libraries/networking/src/platform-adapter.ts +163 -0
- package/libraries/networking/src/rcs-adapter.ts +127 -0
- package/libraries/networking/src/remote-input.ts +188 -0
- package/libraries/networking/src/replication.ts +327 -0
- package/libraries/networking/src/rpc.ts +188 -0
- package/libraries/networking/src/session.ts +173 -0
- package/libraries/networking/src/transport.ts +201 -0
- package/libraries/networking/src/webrtc.ts +323 -0
- package/libraries/pathfinding-2d/README.md +15 -0
- package/libraries/pathfinding-2d/src/astar-grid.ts +312 -0
- package/libraries/pathfinding-2d/src/index.ts +11 -0
- package/libraries/persistence/README.md +25 -0
- package/libraries/persistence/src/autosave-manager.ts +112 -0
- package/libraries/persistence/src/binary-record-store.ts +244 -0
- package/libraries/persistence/src/browser.ts +51 -0
- package/libraries/persistence/src/file-save-store.ts +553 -0
- package/libraries/persistence/src/hash-utils.ts +59 -0
- package/libraries/persistence/src/index.ts +57 -0
- package/libraries/persistence/src/library.ts +74 -0
- package/libraries/persistence/src/mock-opfs.ts +141 -0
- package/libraries/persistence/src/node-fs-directory-handle.ts +161 -0
- package/libraries/persistence/src/opfs-save-store.ts +745 -0
- package/libraries/persistence/src/save-worker-proxy.ts +127 -0
- package/libraries/persistence/src/save-worker.ts +99 -0
- package/libraries/persistence/src/xxh3-ts.d.ts +10 -0
- package/libraries/physics-native/README.md +21 -0
- package/libraries/physics-native/native/Cargo.toml +11 -0
- package/libraries/physics-native/native/src/body.rs +403 -0
- package/libraries/physics-native/native/src/character.rs +226 -0
- package/libraries/physics-native/native/src/collider.rs +299 -0
- package/libraries/physics-native/native/src/joint.rs +81 -0
- package/libraries/physics-native/native/src/lib.rs +830 -0
- package/libraries/physics-native/native/src/query.rs +261 -0
- package/libraries/physics-native/native/src/realm.rs +33 -0
- package/libraries/physics-native/native/src/step.rs +54 -0
- package/libraries/physics-native/native/src/world.rs +148 -0
- package/libraries/physics-native/src/backend.ts +1046 -0
- package/libraries/physics-native/src/broadphase.ts +101 -0
- package/libraries/physics-native/src/ffi-spike-worker.ts +71 -0
- package/libraries/physics-native/src/index.ts +11 -0
- package/libraries/physics-native/src/library.ts +79 -0
- package/libraries/physics-native/src/narrowphase-shapes.ts +420 -0
- package/libraries/physics-native/src/narrowphase.ts +123 -0
- package/libraries/physics-native/src/solver.ts +141 -0
- package/libraries/physics-native/src/types.ts +76 -0
- package/libraries/physics-rapier/README.md +21 -0
- package/libraries/physics-rapier/bench/ffi-bench.ts +79 -0
- package/libraries/physics-rapier/bench/wasm-baseline.ts +90 -0
- package/libraries/physics-rapier/src/api.ts +452 -0
- package/libraries/physics-rapier/src/auto-backend.ts +59 -0
- package/libraries/physics-rapier/src/backend.ts +1207 -0
- package/libraries/physics-rapier/src/bulk-ops.ts +68 -0
- package/libraries/physics-rapier/src/ffi-backend.ts +21 -0
- package/libraries/physics-rapier/src/ffi-lib.ts +597 -0
- package/libraries/physics-rapier/src/index.ts +12 -0
- package/libraries/physics-rapier/src/library.ts +107 -0
- package/libraries/physics-rapier/src/rapier-backend.ts +1052 -0
- package/libraries/physics-rapier/src/realm-worker-script.ts +237 -0
- package/libraries/postfx/README.md +17 -0
- package/libraries/postfx/src/index.ts +19 -0
- package/libraries/postfx/src/library.ts +337 -0
- package/libraries/postfx/src/post-process-stack.ts +1752 -0
- package/libraries/postfx/src/shaders/post-process/afterimage.wgsl +14 -0
- package/libraries/postfx/src/shaders/post-process/ascii.wgsl +24 -0
- package/libraries/postfx/src/shaders/post-process/blit.wgsl +12 -0
- package/libraries/postfx/src/shaders/post-process/bloom-blur.wgsl +21 -0
- package/libraries/postfx/src/shaders/post-process/bloom-bright.wgsl +15 -0
- package/libraries/postfx/src/shaders/post-process/bloom-composite.wgsl +14 -0
- package/libraries/postfx/src/shaders/post-process/bloom-downsample.wgsl +60 -0
- package/libraries/postfx/src/shaders/post-process/bloom-soft.wgsl +46 -0
- package/libraries/postfx/src/shaders/post-process/bloom-upsample.wgsl +51 -0
- package/libraries/postfx/src/shaders/post-process/channel-mixer.wgsl +36 -0
- package/libraries/postfx/src/shaders/post-process/chromatic-aberration.wgsl +37 -0
- package/libraries/postfx/src/shaders/post-process/dithering.wgsl +64 -0
- package/libraries/postfx/src/shaders/post-process/dof.wgsl +131 -0
- package/libraries/postfx/src/shaders/post-process/edges.wgsl +45 -0
- package/libraries/postfx/src/shaders/post-process/fullscreen-vs.wgsl +15 -0
- package/libraries/postfx/src/shaders/post-process/fxaa.wgsl +102 -0
- package/libraries/postfx/src/shaders/post-process/gaussian-blur.wgsl +37 -0
- package/libraries/postfx/src/shaders/post-process/glow-blur.wgsl +33 -0
- package/libraries/postfx/src/shaders/post-process/glow-composite.wgsl +25 -0
- package/libraries/postfx/src/shaders/post-process/grain.wgsl +37 -0
- package/libraries/postfx/src/shaders/post-process/halftone.wgsl +80 -0
- package/libraries/postfx/src/shaders/post-process/highlight-blur.wgsl +33 -0
- package/libraries/postfx/src/shaders/post-process/highlight-composite.wgsl +32 -0
- package/libraries/postfx/src/shaders/post-process/lens-distortion.wgsl +43 -0
- package/libraries/postfx/src/shaders/post-process/lens-flare.wgsl +68 -0
- package/libraries/postfx/src/shaders/post-process/lut.wgsl +30 -0
- package/libraries/postfx/src/shaders/post-process/motion-blur.wgsl +55 -0
- package/libraries/postfx/src/shaders/post-process/occluder-chunk.wgsl +28 -0
- package/libraries/postfx/src/shaders/post-process/outline.wgsl +51 -0
- package/libraries/postfx/src/shaders/post-process/pixelation.wgsl +47 -0
- package/libraries/postfx/src/shaders/post-process/sharpen.wgsl +32 -0
- package/libraries/postfx/src/shaders/post-process/sobel.wgsl +26 -0
- package/libraries/postfx/src/shaders/post-process/split-tone.wgsl +36 -0
- package/libraries/postfx/src/shaders/post-process/ssao-blur.wgsl +38 -0
- package/libraries/postfx/src/shaders/post-process/ssao-composite.wgsl +25 -0
- package/libraries/postfx/src/shaders/post-process/ssao.wgsl +147 -0
- package/libraries/postfx/src/shaders/post-process/ssr.wgsl +155 -0
- package/libraries/postfx/src/shaders/post-process/taa.wgsl +98 -0
- package/libraries/postfx/src/shaders/post-process/tonemap.wgsl +40 -0
- package/libraries/postfx/src/shaders/post-process/watercolor.wgsl +82 -0
- package/libraries/postfx/src/shaders/post-process/white-balance.wgsl +41 -0
- package/libraries/recast/README.md +21 -0
- package/libraries/recast/src/backend.ts +150 -0
- package/libraries/recast/src/crowd-system.ts +352 -0
- package/libraries/recast/src/index.ts +12 -0
- package/libraries/recast/src/library.ts +91 -0
- package/libraries/recast/src/types.ts +86 -0
- package/libraries/sand/README.md +25 -0
- package/libraries/sand/src/cell.ts +43 -0
- package/libraries/sand/src/fields.ts +29 -0
- package/libraries/sand/src/fluid-grid.ts +261 -0
- package/libraries/sand/src/grid-dims.ts +74 -0
- package/libraries/sand/src/grid-sim-buffer.ts +271 -0
- package/libraries/sand/src/index.ts +81 -0
- package/libraries/sand/src/library.ts +92 -0
- package/libraries/sand/src/materials.ts +492 -0
- package/libraries/sand/src/palette.ts +93 -0
- package/libraries/sand/src/particles.ts +185 -0
- package/libraries/sand/src/render/sand-grid-pass.ts +430 -0
- package/libraries/sand/src/rng.ts +51 -0
- package/libraries/sand/src/rules/builtin-rules.ts +132 -0
- package/libraries/sand/src/rules/rule-compiler.ts +162 -0
- package/libraries/sand/src/rules/rule-engine.ts +231 -0
- package/libraries/sand/src/rules/rule-types.ts +87 -0
- package/libraries/sand/src/sand-step-pool.ts +484 -0
- package/libraries/sand/src/sand-step-worker.ts +97 -0
- package/libraries/sand/src/sand-world.ts +3227 -0
- package/libraries/stickman/README.md +25 -0
- package/libraries/stickman/src/index.ts +25 -0
- package/libraries/stickman/src/library.ts +61 -0
- package/libraries/stickman/src/proportions.ts +45 -0
- package/libraries/stickman/src/shader.ts +117 -0
- package/libraries/stickman/src/skeleton.ts +197 -0
- package/libraries/stickman/src/stickman-pass.ts +255 -0
- package/libraries/stickman/src/thick-line.ts +123 -0
- package/libraries/surface-nets/README.md +25 -0
- package/libraries/surface-nets/src/chunked-field.ts +14 -0
- package/libraries/surface-nets/src/deformation.ts +45 -0
- package/libraries/surface-nets/src/index.ts +36 -0
- package/libraries/surface-nets/src/library.ts +59 -0
- package/libraries/surface-nets/src/lod.ts +7 -0
- package/libraries/surface-nets/src/sab.ts +4 -0
- package/libraries/surface-nets/src/streaming-config.ts +5 -0
- package/libraries/surface-nets/src/streaming-manager.ts +15 -0
- package/libraries/surface-nets/src/surface-nets.ts +334 -0
- package/libraries/surface-nets/src/types.ts +23 -0
- package/libraries/water/README.md +25 -0
- package/libraries/water/src/buoyancy.ts +103 -0
- package/libraries/water/src/index.ts +43 -0
- package/libraries/water/src/library.ts +85 -0
- package/libraries/water/src/shore-damping.ts +93 -0
- package/libraries/water/src/water-buffer.ts +89 -0
- package/libraries/water/src/water-chunks.ts +13 -0
- package/libraries/water/src/water-physics.ts +376 -0
- package/libraries/water/src/water-renderer.ts +809 -0
- package/libraries/water/src/water-sab.ts +161 -0
- package/libraries/water/src/wave-sources.ts +84 -0
- package/libraries/weather/README.md +20 -0
- package/libraries/weather/src/index.ts +9 -0
- package/libraries/weather/src/library.ts +72 -0
- package/libraries/weather/src/types.ts +64 -0
- package/libraries/weather/src/weather-blend.ts +112 -0
- package/libraries/weather/src/weather-system.ts +271 -0
- package/libraries/weatherfx/README.md +24 -0
- package/libraries/weatherfx/src/cloud-provider.ts +31 -0
- package/libraries/weatherfx/src/cloud-system.ts +372 -0
- package/libraries/weatherfx/src/index.ts +9 -0
- package/libraries/weatherfx/src/library.ts +58 -0
- package/libraries/weatherfx/src/particle-system.ts +434 -0
- package/libraries/weatherfx/src/shaders/cloud.wgsl +111 -0
- package/libraries/weatherfx/src/shaders/particle-compute.wgsl +187 -0
- package/libraries/weatherfx/src/shaders/particle-render.wgsl +95 -0
- package/lint-plugin.mjs +41 -0
- package/mcp/src/client.ts +703 -0
- package/mcp/src/engine-context.ts +186 -0
- package/mcp/src/http-transport.ts +471 -0
- package/mcp/src/index.ts +13 -0
- package/mcp/src/prompts/add-entity.ts +42 -0
- package/mcp/src/prompts/create-scene.ts +44 -0
- package/mcp/src/prompts/debug-frame.ts +39 -0
- package/mcp/src/prompts/index.ts +12 -0
- package/mcp/src/resources/asset-list.ts +32 -0
- package/mcp/src/resources/checkpoint-list.ts +33 -0
- package/mcp/src/resources/entity-state.ts +55 -0
- package/mcp/src/resources/gpu-info.ts +103 -0
- package/mcp/src/resources/index.ts +57 -0
- package/mcp/src/resources/performance.ts +37 -0
- package/mcp/src/resources/scene-tree.ts +43 -0
- package/mcp/src/server.ts +375 -0
- package/mcp/src/tools/animation.ts +118 -0
- package/mcp/src/tools/asset.ts +161 -0
- package/mcp/src/tools/audio.ts +96 -0
- package/mcp/src/tools/build.ts +143 -0
- package/mcp/src/tools/camera.ts +167 -0
- package/mcp/src/tools/checkpoint.ts +100 -0
- package/mcp/src/tools/component.ts +199 -0
- package/mcp/src/tools/debug.ts +300 -0
- package/mcp/src/tools/entity.ts +361 -0
- package/mcp/src/tools/inspect.ts +210 -0
- package/mcp/src/tools/lighting.ts +263 -0
- package/mcp/src/tools/material.ts +243 -0
- package/mcp/src/tools/mesh.ts +239 -0
- package/mcp/src/tools/physics.ts +266 -0
- package/mcp/src/tools/scene.ts +153 -0
- package/mcp/src/tools/script.ts +122 -0
- package/mcp/src/types.ts +92 -0
- package/mcp/src/undo-redo.ts +77 -0
- package/modules/camera-controls/README.md +20 -0
- package/modules/camera-controls/src/index.ts +161 -0
- package/modules/controller-ui/src/index.ts +164 -0
- package/modules/devtools/README.md +25 -0
- package/modules/devtools/src/api.ts +461 -0
- package/modules/devtools/src/asset-utils.ts +105 -0
- package/modules/devtools/src/bind-debug-store.ts +48 -0
- package/modules/devtools/src/data-bridge.ts +286 -0
- package/modules/devtools/src/debug-overlay.ts +238 -0
- package/modules/devtools/src/debug-raycast.ts +328 -0
- package/modules/devtools/src/debug-store.ts +92 -0
- package/modules/devtools/src/debug-view-descriptors.ts +59 -0
- package/modules/devtools/src/doctor-panel.ts +182 -0
- package/modules/devtools/src/gizmo-module.ts +136 -0
- package/modules/devtools/src/graph-model.ts +509 -0
- package/modules/devtools/src/grid-renderer.ts +157 -0
- package/modules/devtools/src/height-ruler-renderer.ts +216 -0
- package/modules/devtools/src/index.ts +81 -0
- package/modules/devtools/src/init.ts +261 -0
- package/modules/devtools/src/label-overlay.ts +154 -0
- package/modules/devtools/src/material-stats-panel.ts +188 -0
- package/modules/devtools/src/profiling-bridge.ts +377 -0
- package/modules/devtools/src/profiling-hooks.ts +98 -0
- package/modules/devtools/src/renderer-adapter.ts +76 -0
- package/modules/devtools/src/scene-inspector.ts +637 -0
- package/modules/devtools/src/scene-store.ts +320 -0
- package/modules/devtools/src/scene-sync.ts +116 -0
- package/modules/devtools/src/shaders/transform-gizmo.wgsl +38 -0
- package/modules/devtools/src/sim-stats-panel.ts +272 -0
- package/modules/devtools/src/sim-stats-provider.ts +105 -0
- package/modules/devtools/src/skeleton-renderer.ts +351 -0
- package/modules/devtools/src/transform-gizmo.ts +928 -0
- package/modules/devtools/src/types.ts +290 -0
- package/modules/devtools/src/worker-expose.ts +67 -0
- package/modules/devtools/src/worker-sync.ts +137 -0
- package/modules/editor/src/commands/component.ts +156 -0
- package/modules/editor/src/commands/entity.ts +287 -0
- package/modules/editor/src/commands/hierarchy.ts +83 -0
- package/modules/editor/src/commands/index.ts +61 -0
- package/modules/editor/src/commands/prefab.ts +163 -0
- package/modules/editor/src/commands/registry.ts +331 -0
- package/modules/editor/src/commands/scene-io.ts +211 -0
- package/modules/editor/src/commands/selection.ts +73 -0
- package/modules/editor/src/commands/transform.ts +91 -0
- package/modules/editor/src/ddscene.ts +267 -0
- package/modules/editor/src/document.ts +123 -0
- package/modules/editor/src/editor-context.ts +172 -0
- package/modules/editor/src/index.ts +41 -0
- package/modules/editor/src/mcp.ts +103 -0
- package/modules/editor/src/module.ts +148 -0
- package/modules/editor/src/selection.ts +70 -0
- package/modules/editor/src/shell.ts +456 -0
- package/modules/editor/src/viewport.ts +199 -0
- package/modules/html-ui/src/composite.ts +135 -0
- package/modules/html-ui/src/create-html-ui.ts +188 -0
- package/modules/html-ui/src/doc-backend.ts +343 -0
- package/modules/html-ui/src/host.ts +646 -0
- package/modules/html-ui/src/index.ts +13 -0
- package/modules/html-ui/src/jsx-dev-runtime.ts +12 -0
- package/modules/html-ui/src/jsx-runtime.ts +126 -0
- package/modules/html-ui/src/protocol.ts +88 -0
- package/modules/html-ui/src/ui-worker.ts +16 -0
- package/modules/mcp/README.md +18 -0
- package/modules/mcp/src/index.ts +27 -0
- package/modules/movement-2d/README.md +19 -0
- package/modules/movement-2d/src/grid-character.ts +455 -0
- package/modules/movement-2d/src/index.ts +45 -0
- package/modules/movement-3d/README.md +21 -0
- package/modules/movement-3d/src/character-motor.ts +230 -0
- package/modules/movement-3d/src/index.ts +46 -0
- package/modules/native-osr/src/index.ts +22 -0
- package/modules/native-osr/src/input-router.ts +401 -0
- package/modules/native-osr/src/native-osr-manager.ts +247 -0
- package/modules/native-osr/src/native-texture-source.ts +86 -0
- package/modules/native-osr/src/types.ts +112 -0
- package/modules/native-osr/src/world-space-ui-pass.ts +351 -0
- package/modules/sailing/README.md +18 -0
- package/modules/sailing/src/index.ts +51 -0
- package/modules/terrain/README.md +18 -0
- package/modules/terrain/src/index.ts +78 -0
- package/modules/vitals/README.md +17 -0
- package/modules/vitals/src/index.ts +43 -0
- package/modules/vitals/src/vitals.ts +265 -0
- package/modules/xr/README.md +25 -0
- package/modules/xr/src/camera-rig.ts +146 -0
- package/modules/xr/src/debug.ts +59 -0
- package/modules/xr/src/frame-loop.ts +197 -0
- package/modules/xr/src/index.ts +16 -0
- package/modules/xr/src/input.ts +208 -0
- package/modules/xr/src/layer.ts +140 -0
- package/modules/xr/src/session.ts +156 -0
- package/modules/xr/src/sim-module.ts +23 -0
- package/modules/xr/src/types.ts +32 -0
- package/modules/xr/src/webxr.d.ts +182 -0
- package/modules/xr/src/xr-module.ts +179 -0
- package/package.json +232 -3
- package/shader-graph/src/chunks.ts +349 -0
- package/shader-graph/src/compiler.ts +732 -0
- package/shader-graph/src/compute-compiler.ts +453 -0
- package/shader-graph/src/compute-graph.ts +112 -0
- package/shader-graph/src/compute-profiles.ts +54 -0
- package/shader-graph/src/graph.ts +52 -0
- package/shader-graph/src/index.ts +53 -0
- package/shader-graph/src/profiles.ts +407 -0
- package/shader-graph/src/validator.ts +48 -0
- package/shader-graph/src/wgsl-binding-validator.ts +143 -0
- package/shader-graph/src/wgsl-struct-validator.ts +245 -0
- package/shader-graph/src/wgsl-struct.ts +397 -0
- package/test/src/index.ts +7 -0
- package/test/src/vision-test.ts +369 -0
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// FileSaveStore — filesystem-based ISaveStore implementation
|
|
3
|
+
// ============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Saves are written as binary files with an uncompressed header (magic,
|
|
6
|
+
// format version, engine version, timestamp, entity/player counts, XXH128
|
|
7
|
+
// hash, uncompressed body length) followed by a zstd-compressed JSON body.
|
|
8
|
+
//
|
|
9
|
+
// On save, the previous file is rotated to `.bak`. On load failure (hash
|
|
10
|
+
// mismatch, parse error, migration error), the `.bak` is tried as fallback.
|
|
11
|
+
//
|
|
12
|
+
// Forward incompatibility: saves from a newer engine version are refused.
|
|
13
|
+
// Consumers should implement version backups for unstable releases.
|
|
14
|
+
|
|
15
|
+
import { safeJsonParse } from "@downdraft/engine";
|
|
16
|
+
import {
|
|
17
|
+
encodeHeader,
|
|
18
|
+
engineVersionString,
|
|
19
|
+
HEADER_SIZE,
|
|
20
|
+
packEngineVersion,
|
|
21
|
+
readHeaderFromFile,
|
|
22
|
+
SAVE_FORMAT_VERSION,
|
|
23
|
+
SAVE_MAGIC,
|
|
24
|
+
type SaveHeader
|
|
25
|
+
} from "@downdraft/engine/save/binary-format";
|
|
26
|
+
import { MigrationRegistryImpl } from "@downdraft/engine/save/migration-registry";
|
|
27
|
+
import type {
|
|
28
|
+
IMigrationRegistry,
|
|
29
|
+
ISaveStore,
|
|
30
|
+
LoadOptions,
|
|
31
|
+
LoadResult,
|
|
32
|
+
SaveGenerationInfo,
|
|
33
|
+
SaveOptions,
|
|
34
|
+
SaveResult,
|
|
35
|
+
SaveSlotInfo,
|
|
36
|
+
SaveState,
|
|
37
|
+
SaveWarning
|
|
38
|
+
} from "@downdraft/engine/save/persist-types";
|
|
39
|
+
import { createLogger } from "@downdraft/engine/util/logger";
|
|
40
|
+
import { promises as fs } from "node:fs";
|
|
41
|
+
import { join } from "node:path";
|
|
42
|
+
|
|
43
|
+
const log = createLogger("info");
|
|
44
|
+
|
|
45
|
+
const SAVE_EXT = ".ddsave";
|
|
46
|
+
const BACKUP_EXT = ".ddsave.bak";
|
|
47
|
+
const THUMB_EXT = ".thumb";
|
|
48
|
+
const PROPS_EXT = ".props.json";
|
|
49
|
+
const BLOBS_DIR_SUFFIX = ".blobs";
|
|
50
|
+
|
|
51
|
+
// zstd-wasm init() is NOT idempotent — a second call re-instantiates the
|
|
52
|
+
// wasm module while Module.HEAP8 still points at the old memory, silently
|
|
53
|
+
// corrupting every subsequent decompress. Guard it at module level so all
|
|
54
|
+
// FileSaveStore instances (and the services worker's) share one init.
|
|
55
|
+
let zstdInitPromise: Promise<void> | null = null;
|
|
56
|
+
function ensureZstdGlobal(): Promise<void> {
|
|
57
|
+
if (!zstdInitPromise) {
|
|
58
|
+
zstdInitPromise = (async () => {
|
|
59
|
+
const { init } = await import("@bokuweb/zstd-wasm");
|
|
60
|
+
await init();
|
|
61
|
+
})();
|
|
62
|
+
// Don't cache a rejection forever — a transient failure (missing wasm
|
|
63
|
+
// asset, fs hiccup) would otherwise permanently break all saves.
|
|
64
|
+
zstdInitPromise.catch(() => { zstdInitPromise = null; });
|
|
65
|
+
}
|
|
66
|
+
return zstdInitPromise;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface FileSaveStoreOptions {
|
|
70
|
+
/** Directory to store save files (typically app.getPath("userData") + "/saves") */
|
|
71
|
+
saveDir: string;
|
|
72
|
+
/** Current engine/game version string (e.g. "0.1.0") */
|
|
73
|
+
engineVersion: string;
|
|
74
|
+
/** Migration registry (optional — a new one is created if not provided) */
|
|
75
|
+
migrationRegistry?: IMigrationRegistry;
|
|
76
|
+
/** Optional compression provider (for testing or custom compression) */
|
|
77
|
+
compress?: (data: Uint8Array) => Uint8Array;
|
|
78
|
+
/** Optional decompression provider (for testing or custom compression) */
|
|
79
|
+
decompress?: (data: Uint8Array, originalSize: number) => Uint8Array;
|
|
80
|
+
/** Optional hash provider (for testing or custom hashing) */
|
|
81
|
+
hash128?: (data: Uint8Array) => Uint8Array;
|
|
82
|
+
/** Skip migration step on load — pass through components unchanged (for pure storage layers) */
|
|
83
|
+
skipMigrations?: boolean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export class FileSaveStore implements ISaveStore {
|
|
87
|
+
private saveDir: string;
|
|
88
|
+
private engineVersionPacked: number;
|
|
89
|
+
private migrations: IMigrationRegistry;
|
|
90
|
+
private warningCallbacks: Array<(w: SaveWarning) => void> = [];
|
|
91
|
+
private zstdReady: Promise<void> | null = null;
|
|
92
|
+
private _compress: ((data: Uint8Array) => Uint8Array) | null = null;
|
|
93
|
+
private _decompress: ((data: Uint8Array, originalSize: number) => Uint8Array) | null = null;
|
|
94
|
+
private _hash128: ((data: Uint8Array) => Uint8Array) | null = null;
|
|
95
|
+
private _skipMigrations: boolean = false;
|
|
96
|
+
|
|
97
|
+
constructor(opts: FileSaveStoreOptions) {
|
|
98
|
+
this.saveDir = opts.saveDir;
|
|
99
|
+
const parts = opts.engineVersion.split(".").map(Number);
|
|
100
|
+
this.engineVersionPacked = packEngineVersion(parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0);
|
|
101
|
+
this.migrations = opts.migrationRegistry ?? new MigrationRegistryImpl();
|
|
102
|
+
this._compress = opts.compress ?? null;
|
|
103
|
+
this._decompress = opts.decompress ?? null;
|
|
104
|
+
this._hash128 = opts.hash128 ?? null;
|
|
105
|
+
this._skipMigrations = opts.skipMigrations ?? false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
getMigrationRegistry(): IMigrationRegistry {
|
|
109
|
+
return this.migrations;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
onWarning(cb: (warning: SaveWarning) => void): () => void {
|
|
113
|
+
this.warningCallbacks.push(cb);
|
|
114
|
+
return () => {
|
|
115
|
+
const idx = this.warningCallbacks.indexOf(cb);
|
|
116
|
+
if (idx >= 0) this.warningCallbacks.splice(idx, 1);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private warn(warning: SaveWarning): void {
|
|
121
|
+
this.warningCallbacks.forEach((cb) => {
|
|
122
|
+
try {
|
|
123
|
+
cb(warning);
|
|
124
|
+
} catch {
|
|
125
|
+
// ignore callback errors
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private async ensureZstd(): Promise<void> {
|
|
131
|
+
if (!this.zstdReady) this.zstdReady = ensureZstdGlobal();
|
|
132
|
+
return this.zstdReady;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private async computeHash(data: Uint8Array): Promise<Uint8Array> {
|
|
136
|
+
// True XXH3-128 hash (16 bytes) — no longer padded h64.
|
|
137
|
+
const { xxh3_128 } = await import("./hash-utils");
|
|
138
|
+
return xxh3_128(data);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private async compressBytes(data: Uint8Array): Promise<Uint8Array> {
|
|
142
|
+
await this.ensureZstd();
|
|
143
|
+
const { compress } = await import("@bokuweb/zstd-wasm");
|
|
144
|
+
return compress(data);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private async decompressBytes(data: Uint8Array, originalSize: number): Promise<Uint8Array> {
|
|
148
|
+
await this.ensureZstd();
|
|
149
|
+
const { decompress } = await import("@bokuweb/zstd-wasm");
|
|
150
|
+
return decompress(data);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Saves are serialized — concurrent save() calls (e.g. an autosave tick
|
|
154
|
+
// racing a sim-emitted 'saved' event forwarded through the bridge) share
|
|
155
|
+
// the same .tmp path and would otherwise rename-fail with ENOENT.
|
|
156
|
+
private saveQueue: Promise<unknown> = Promise.resolve();
|
|
157
|
+
|
|
158
|
+
async save(slot: string, state: SaveState, opts?: SaveOptions): Promise<SaveResult> {
|
|
159
|
+
const run = this.saveQueue.then(() => this.doSave(slot, state, opts));
|
|
160
|
+
this.saveQueue = run.catch(() => { /* error reported via SaveResult */ });
|
|
161
|
+
return run;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private async doSave(slot: string, state: SaveState, opts?: SaveOptions): Promise<SaveResult> {
|
|
165
|
+
try {
|
|
166
|
+
await fs.mkdir(this.saveDir, { recursive: true });
|
|
167
|
+
const bodyJson = JSON.stringify(state.components);
|
|
168
|
+
const bodyBytes = new TextEncoder().encode(bodyJson);
|
|
169
|
+
|
|
170
|
+
const hashBytes = this._hash128 ? this._hash128(bodyBytes) : await this.computeHash(bodyBytes);
|
|
171
|
+
const compressed = this._compress ? this._compress(bodyBytes) : await this.compressBytes(bodyBytes);
|
|
172
|
+
|
|
173
|
+
const header: SaveHeader = {
|
|
174
|
+
magic: SAVE_MAGIC,
|
|
175
|
+
formatVersion: SAVE_FORMAT_VERSION,
|
|
176
|
+
engineVersionPacked: this.engineVersionPacked,
|
|
177
|
+
timestamp: state.meta.timestamp,
|
|
178
|
+
entityCount: state.meta.entityCount,
|
|
179
|
+
playerCount: state.meta.playerCount,
|
|
180
|
+
bodyHash: hashBytes,
|
|
181
|
+
uncompressedBodyLength: bodyBytes.length,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const headerBuf = encodeHeader(header);
|
|
185
|
+
const filePath = this.slotPath(slot);
|
|
186
|
+
const bakPath = filePath + ".bak";
|
|
187
|
+
const tmpPath = filePath + ".tmp";
|
|
188
|
+
|
|
189
|
+
const blobsDir = this.blobsDirPath(slot);
|
|
190
|
+
const bakBlobsDir = blobsDir + ".bak";
|
|
191
|
+
const tmpBlobsDir = blobsDir + ".tmp";
|
|
192
|
+
|
|
193
|
+
// Phase 1: Write everything to temp locations first.
|
|
194
|
+
// If the process crashes here, the old save is still intact.
|
|
195
|
+
// Clean up any stale temp blobs dir from a crashed previous save so its
|
|
196
|
+
// leftover files don't get renamed into the final blobs dir.
|
|
197
|
+
try { await fs.rm(tmpBlobsDir, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
198
|
+
const fileBuf = new Uint8Array(headerBuf.byteLength + compressed.length);
|
|
199
|
+
fileBuf.set(new Uint8Array(headerBuf), 0);
|
|
200
|
+
fileBuf.set(compressed, headerBuf.byteLength);
|
|
201
|
+
await fs.writeFile(tmpPath, fileBuf);
|
|
202
|
+
|
|
203
|
+
// Write blobs to temp dir
|
|
204
|
+
let blobBytes = 0;
|
|
205
|
+
if (opts?.blobs && Object.keys(opts.blobs).length > 0) {
|
|
206
|
+
await fs.mkdir(tmpBlobsDir, { recursive: true });
|
|
207
|
+
for (let _i = 0, _it = Object.entries(opts.blobs) as Array<[string, ArrayBuffer]>, _n = _it.length; _i < _n; _i++) { const [key, buf] = _it[_i];
|
|
208
|
+
const safeKey = key.replace(/[^a-zA-Z0-9_\-]/g, "_");
|
|
209
|
+
await fs.writeFile(join(tmpBlobsDir, safeKey), new Uint8Array(buf));
|
|
210
|
+
blobBytes += buf.byteLength;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Phase 2: All writes succeeded — now rotate old → .bak, then rename .tmp → final.
|
|
215
|
+
// This minimizes the crash-corruption window: the old save is only rotated
|
|
216
|
+
// after the new save is fully written to .tmp.
|
|
217
|
+
try {
|
|
218
|
+
await fs.access(filePath);
|
|
219
|
+
await fs.rename(filePath, bakPath);
|
|
220
|
+
} catch {
|
|
221
|
+
// No existing file — fine
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
await fs.access(blobsDir);
|
|
225
|
+
// Remove a stale .bak blobs dir first: renaming a directory onto an
|
|
226
|
+
// existing non-empty directory fails with ENOTEMPTY on Linux, which
|
|
227
|
+
// would leave blobsDir in place and cause the .tmp → final rename
|
|
228
|
+
// below to fail with ENOTEMPTY as well.
|
|
229
|
+
try { await fs.rm(bakBlobsDir, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
230
|
+
await fs.rename(blobsDir, bakBlobsDir);
|
|
231
|
+
} catch {
|
|
232
|
+
// No existing blobs dir — fine
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Atomic rename: .tmp → final
|
|
236
|
+
await fs.rename(tmpPath, filePath);
|
|
237
|
+
// Rename temp blobs dir → final
|
|
238
|
+
if (opts?.blobs && Object.keys(opts.blobs).length > 0) {
|
|
239
|
+
await fs.rename(tmpBlobsDir, blobsDir);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Write thumbnail if provided (not part of the atomic commit — thumbnail is non-critical)
|
|
243
|
+
if (opts?.thumbnail) {
|
|
244
|
+
const thumbData = opts.thumbnail instanceof Uint8Array ? opts.thumbnail : new Uint8Array(opts.thumbnail);
|
|
245
|
+
await fs.writeFile(this.thumbPath(slot), thumbData);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Write properties if provided (not part of the atomic commit — properties are non-critical)
|
|
249
|
+
if (opts?.properties) {
|
|
250
|
+
await fs.writeFile(this.propsPath(slot), JSON.stringify(opts.properties, null, 2));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
log.debug("FileSaveStore", `Saved slot '${slot}' (${fileBuf.length + blobBytes} bytes)`);
|
|
254
|
+
return { success: true, bytes: fileBuf.length + blobBytes, gen: 1 };
|
|
255
|
+
} catch (err) {
|
|
256
|
+
log.error("FileSaveStore", `Save failed for slot '${slot}': ${err}`);
|
|
257
|
+
return { success: false, bytes: 0 };
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async load(slot: string, opts?: LoadOptions): Promise<LoadResult> {
|
|
262
|
+
const filePath = this.slotPath(slot);
|
|
263
|
+
const bakPath = filePath + ".bak";
|
|
264
|
+
const includeBlobs = opts?.includeBlobs ?? true;
|
|
265
|
+
|
|
266
|
+
const result = await this.loadFromFile(filePath, slot, includeBlobs);
|
|
267
|
+
if (result.state) return result;
|
|
268
|
+
|
|
269
|
+
// Try backup
|
|
270
|
+
const bakResult = await this.loadFromFile(bakPath, slot, includeBlobs);
|
|
271
|
+
if (bakResult.state) {
|
|
272
|
+
this.warn({
|
|
273
|
+
kind: "backup_loaded",
|
|
274
|
+
slot,
|
|
275
|
+
message: `Primary save failed, loaded backup for slot '${slot}'`,
|
|
276
|
+
});
|
|
277
|
+
return bakResult;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
this.warn({
|
|
281
|
+
kind: "no_saves_found",
|
|
282
|
+
slot,
|
|
283
|
+
message: `No valid save found for slot '${slot}'`,
|
|
284
|
+
});
|
|
285
|
+
return { state: null };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
private async loadFromFile(filePath: string, slot: string, includeBlobs: boolean): Promise<LoadResult> {
|
|
289
|
+
try {
|
|
290
|
+
const fileBuf = await fs.readFile(filePath);
|
|
291
|
+
// fs.readFile returns a Buffer that may be a view into a shared pool —
|
|
292
|
+
// .buffer alone ignores byteOffset and reads garbage. Slice first.
|
|
293
|
+
const fileBytes = fileBuf.buffer.slice(fileBuf.byteOffset, fileBuf.byteOffset + fileBuf.byteLength);
|
|
294
|
+
const header = readHeaderFromFile(fileBytes);
|
|
295
|
+
if (!header) {
|
|
296
|
+
this.warn({ kind: "corruption", slot, message: `Invalid header in ${filePath}` });
|
|
297
|
+
return { state: null };
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Forward incompatibility check
|
|
301
|
+
if (header.engineVersionPacked > this.engineVersionPacked) {
|
|
302
|
+
const saveVer = engineVersionString(header.engineVersionPacked);
|
|
303
|
+
this.warn({
|
|
304
|
+
kind: "forward_incompatible",
|
|
305
|
+
slot,
|
|
306
|
+
message: `Save version ${saveVer} > engine version — refusing to load`,
|
|
307
|
+
});
|
|
308
|
+
return { state: null };
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const compressedBody = new Uint8Array(fileBytes, HEADER_SIZE);
|
|
312
|
+
const decompressed = this._decompress
|
|
313
|
+
? this._decompress(compressedBody, header.uncompressedBodyLength)
|
|
314
|
+
: await this.decompressBytes(compressedBody, header.uncompressedBodyLength);
|
|
315
|
+
|
|
316
|
+
// Verify hash
|
|
317
|
+
const computedHash = this._hash128 ? this._hash128(decompressed) : await this.computeHash(decompressed);
|
|
318
|
+
if (!this.hashEqual(computedHash, header.bodyHash)) {
|
|
319
|
+
this.warn({ kind: "corruption", slot, message: `Hash mismatch in ${filePath}` });
|
|
320
|
+
return { state: null };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const bodyJson = new TextDecoder().decode(decompressed);
|
|
324
|
+
const components = safeJsonParse<Record<string, { v: number; data: unknown }>>(bodyJson);
|
|
325
|
+
|
|
326
|
+
// Run migrations per component (or pass through if skipped)
|
|
327
|
+
const migrated: Record<string, { v: number; data: unknown }> = {};
|
|
328
|
+
const abandoned: Record<string, unknown> = {};
|
|
329
|
+
|
|
330
|
+
for (const [name, section] of Object.entries(components)) {
|
|
331
|
+
if (this._skipMigrations) {
|
|
332
|
+
migrated[name] = { v: section.v, data: section.data };
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
const result = this.migrations.migrate(name, section.data, section.v);
|
|
336
|
+
if (result) {
|
|
337
|
+
migrated[name] = { v: result.version, data: result.data };
|
|
338
|
+
} else {
|
|
339
|
+
// Mark as abandoned — keep data but don't load it
|
|
340
|
+
abandoned[name] = section.data;
|
|
341
|
+
this.warn({
|
|
342
|
+
kind: "abandoned_data",
|
|
343
|
+
slot,
|
|
344
|
+
component: name,
|
|
345
|
+
message: `Component '${name}' could not be migrated from v${section.v}`,
|
|
346
|
+
abandonedData: section.data,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const state: SaveState = {
|
|
352
|
+
components: migrated,
|
|
353
|
+
meta: {
|
|
354
|
+
engineVersion: engineVersionString(header.engineVersionPacked),
|
|
355
|
+
timestamp: header.timestamp,
|
|
356
|
+
entityCount: header.entityCount,
|
|
357
|
+
playerCount: header.playerCount,
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
log.info("FileSaveStore", `Loaded slot '${slot}'`);
|
|
362
|
+
// Load blobs if requested
|
|
363
|
+
let blobs: Record<string, ArrayBuffer> | undefined;
|
|
364
|
+
if (includeBlobs) {
|
|
365
|
+
blobs = await this.loadBlobs(slot);
|
|
366
|
+
if (blobs && Object.keys(blobs).length === 0) blobs = undefined;
|
|
367
|
+
}
|
|
368
|
+
return { state, blobs, gen: 1 };
|
|
369
|
+
} catch (err) {
|
|
370
|
+
// File doesn't exist or other error — return null silently
|
|
371
|
+
return { state: null };
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
private async loadBlobs(slot: string): Promise<Record<string, ArrayBuffer> | undefined> {
|
|
376
|
+
try {
|
|
377
|
+
const blobsDir = this.blobsDirPath(slot);
|
|
378
|
+
const files = await fs.readdir(blobsDir);
|
|
379
|
+
const blobs: Record<string, ArrayBuffer> = {};
|
|
380
|
+
for (let _i = 0, _it = files, _n = _it.length; _i < _n; _i++) { const file = _it[_i];
|
|
381
|
+
const buf = await fs.readFile(join(blobsDir, file));
|
|
382
|
+
blobs[file] = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
383
|
+
}
|
|
384
|
+
return blobs;
|
|
385
|
+
} catch {
|
|
386
|
+
return undefined;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
async listSaves(): Promise<SaveSlotInfo[]> {
|
|
391
|
+
try {
|
|
392
|
+
const files = await fs.readdir(this.saveDir);
|
|
393
|
+
const saves: SaveSlotInfo[] = [];
|
|
394
|
+
|
|
395
|
+
for (let _i = 0, _it = files, _n = _it.length; _i < _n; _i++) { const file = _it[_i];
|
|
396
|
+
if (!file.endsWith(SAVE_EXT)) continue;
|
|
397
|
+
const filePath = join(this.saveDir, file);
|
|
398
|
+
const stat = await fs.stat(filePath);
|
|
399
|
+
const fileBuf = await fs.readFile(filePath);
|
|
400
|
+
const header = readHeaderFromFile(
|
|
401
|
+
fileBuf.buffer.slice(fileBuf.byteOffset, fileBuf.byteOffset + fileBuf.byteLength));
|
|
402
|
+
if (!header) continue;
|
|
403
|
+
|
|
404
|
+
const slotName = file.replace(SAVE_EXT, "");
|
|
405
|
+
const hasThumbnail = await this.fileExists(this.thumbPath(slotName));
|
|
406
|
+
const properties = await this.readProps(slotName);
|
|
407
|
+
|
|
408
|
+
saves.push({
|
|
409
|
+
slot: slotName,
|
|
410
|
+
timestamp: header.timestamp,
|
|
411
|
+
entityCount: header.entityCount,
|
|
412
|
+
playerCount: header.playerCount,
|
|
413
|
+
engineVersion: engineVersionString(header.engineVersionPacked),
|
|
414
|
+
fileSize: stat.size,
|
|
415
|
+
currentGen: 1,
|
|
416
|
+
generationCount: 1,
|
|
417
|
+
hasThumbnail,
|
|
418
|
+
properties: Object.keys(properties).length > 0 ? properties : undefined,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
saves.sort((a, b) => b.timestamp - a.timestamp);
|
|
423
|
+
return saves;
|
|
424
|
+
} catch {
|
|
425
|
+
return [];
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
async listGenerations(slot: string): Promise<SaveGenerationInfo[]> {
|
|
430
|
+
try {
|
|
431
|
+
const filePath = this.slotPath(slot);
|
|
432
|
+
const fileBuf = await fs.readFile(filePath);
|
|
433
|
+
const header = readHeaderFromFile(
|
|
434
|
+
fileBuf.buffer.slice(fileBuf.byteOffset, fileBuf.byteOffset + fileBuf.byteLength));
|
|
435
|
+
if (!header) return [];
|
|
436
|
+
const stat = await fs.stat(filePath);
|
|
437
|
+
return [{
|
|
438
|
+
gen: 1,
|
|
439
|
+
timestamp: header.timestamp,
|
|
440
|
+
engineVersion: engineVersionString(header.engineVersionPacked),
|
|
441
|
+
entityCount: header.entityCount,
|
|
442
|
+
playerCount: header.playerCount,
|
|
443
|
+
bodySize: stat.size,
|
|
444
|
+
blobCount: 0,
|
|
445
|
+
}];
|
|
446
|
+
} catch {
|
|
447
|
+
return [];
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
async deleteGeneration(slot: string, _gen: number): Promise<boolean> {
|
|
452
|
+
// FileSaveStore only has one "generation" — deleting it deletes the slot
|
|
453
|
+
if (_gen !== 1) return false;
|
|
454
|
+
return this.deleteSave(slot);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
async setThumbnail(slot: string, data: ArrayBuffer | Uint8Array): Promise<void> {
|
|
458
|
+
const thumbData = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
459
|
+
await fs.writeFile(this.thumbPath(slot), thumbData);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
async getThumbnail(slot: string): Promise<ArrayBuffer | null> {
|
|
463
|
+
try {
|
|
464
|
+
const buf = await fs.readFile(this.thumbPath(slot));
|
|
465
|
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
466
|
+
} catch {
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
async setProperties(slot: string, props: Record<string, unknown>): Promise<void> {
|
|
472
|
+
const existing = await this.readProps(slot);
|
|
473
|
+
const merged = { ...existing, ...props };
|
|
474
|
+
await fs.writeFile(this.propsPath(slot), JSON.stringify(merged, null, 2));
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
async getProperties(slot: string): Promise<Record<string, unknown>> {
|
|
478
|
+
return this.readProps(slot);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
private async readProps(slot: string): Promise<Record<string, unknown>> {
|
|
482
|
+
try {
|
|
483
|
+
const text = await fs.readFile(this.propsPath(slot), "utf-8");
|
|
484
|
+
return safeJsonParse<Record<string, unknown>>(text);
|
|
485
|
+
} catch {
|
|
486
|
+
return {};
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
private async fileExists(path: string): Promise<boolean> {
|
|
491
|
+
try { await fs.access(path); return true; } catch { return false; }
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
async deleteSave(slot: string): Promise<boolean> {
|
|
495
|
+
const filePath = this.slotPath(slot);
|
|
496
|
+
const bakPath = filePath + ".bak";
|
|
497
|
+
const tmpPath = filePath + ".tmp";
|
|
498
|
+
let deleted = false;
|
|
499
|
+
try {
|
|
500
|
+
await fs.unlink(filePath);
|
|
501
|
+
deleted = true;
|
|
502
|
+
} catch {
|
|
503
|
+
// ignore
|
|
504
|
+
}
|
|
505
|
+
try {
|
|
506
|
+
await fs.unlink(bakPath);
|
|
507
|
+
deleted = true;
|
|
508
|
+
} catch {
|
|
509
|
+
// ignore
|
|
510
|
+
}
|
|
511
|
+
try {
|
|
512
|
+
await fs.unlink(tmpPath);
|
|
513
|
+
} catch {
|
|
514
|
+
// ignore — orphaned temp from a crashed save
|
|
515
|
+
}
|
|
516
|
+
// Clean up blobs, thumbnail, properties, and orphaned temp files
|
|
517
|
+
try { await fs.rm(this.blobsDirPath(slot), { recursive: true, force: true }); } catch {}
|
|
518
|
+
try { await fs.rm(this.blobsDirPath(slot) + ".bak", { recursive: true, force: true }); } catch {}
|
|
519
|
+
try { await fs.rm(this.blobsDirPath(slot) + ".tmp", { recursive: true, force: true }); } catch {}
|
|
520
|
+
try { await fs.unlink(this.thumbPath(slot)); } catch {}
|
|
521
|
+
try { await fs.unlink(this.propsPath(slot)); } catch {}
|
|
522
|
+
return deleted;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
private slotPath(slot: string): string {
|
|
526
|
+
// Sanitize slot name to prevent path traversal
|
|
527
|
+
const safe = slot.replace(/[^a-zA-Z0-9_\-]/g, "_");
|
|
528
|
+
return join(this.saveDir, safe + SAVE_EXT);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
private blobsDirPath(slot: string): string {
|
|
532
|
+
const safe = slot.replace(/[^a-zA-Z0-9_\-]/g, "_");
|
|
533
|
+
return join(this.saveDir, safe + BLOBS_DIR_SUFFIX);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
private thumbPath(slot: string): string {
|
|
537
|
+
const safe = slot.replace(/[^a-zA-Z0-9_\-]/g, "_");
|
|
538
|
+
return join(this.saveDir, safe + THUMB_EXT);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
private propsPath(slot: string): string {
|
|
542
|
+
const safe = slot.replace(/[^a-zA-Z0-9_\-]/g, "_");
|
|
543
|
+
return join(this.saveDir, safe + PROPS_EXT);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
private hashEqual(a: Uint8Array, b: Uint8Array): boolean {
|
|
547
|
+
if (a.length !== b.length) return false;
|
|
548
|
+
for (let i = 0; i < a.length; i++) {
|
|
549
|
+
if (a[i] !== b[i]) return false;
|
|
550
|
+
}
|
|
551
|
+
return true;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Hash utilities — true XXH3-128 hashing for save integrity
|
|
3
|
+
// ============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Uses xxh3-ts (pure TypeScript, no native deps) to compute a true 128-bit
|
|
6
|
+
// XXH3 hash. The result is returned as a 16-byte Uint8Array (little-endian),
|
|
7
|
+
// matching the binary format header's XXH128 field.
|
|
8
|
+
//
|
|
9
|
+
// All three save stores (File, OPFS, IndexedDB) share this utility as the
|
|
10
|
+
// default hash implementation. The `hash128` injection option remains for
|
|
11
|
+
// testing or custom hash providers.
|
|
12
|
+
//
|
|
13
|
+
// NOTE: xxh3-ts ships CJS .js files (with require()). A static import lets
|
|
14
|
+
// Vite pre-bundle the CJS→ESM conversion. A dynamic import with a variable
|
|
15
|
+
// name (the previous approach) broke Vite's pre-bundling — the browser got
|
|
16
|
+
// raw CJS with require() calls that fail at runtime, which blocked
|
|
17
|
+
// `loadWorld()` during renderer init and left the canvas black.
|
|
18
|
+
// See ./xxh3-ts.d.ts for the type override that avoids a TS 5.9+
|
|
19
|
+
// BigUint64Array incompatibility in the package's .ts source.
|
|
20
|
+
//
|
|
21
|
+
|
|
22
|
+
import { Buffer } from "buffer";
|
|
23
|
+
import * as xxh3ns from "xxh3-ts";
|
|
24
|
+
|
|
25
|
+
// The bare "xxh3-ts" specifier resolves to the real CJS package under Vite,
|
|
26
|
+
// Bun and Node, but tsconfig `paths` (and the generated deno.json import
|
|
27
|
+
// map) alias it to the type-only ./xxh3-ts.d.ts — tsx and Deno honor the
|
|
28
|
+
// alias at runtime and load the .d.ts, yielding an empty module. Fall back
|
|
29
|
+
// to a require() of the deep /index.js subpath, which the alias doesn't
|
|
30
|
+
// cover (only ever reached on tsx/Deno; the static import always provides
|
|
31
|
+
// the export in Vite/Bun/Node contexts).
|
|
32
|
+
let XXH3_128: ((data: Buffer) => bigint) | undefined =
|
|
33
|
+
(xxh3ns as any).XXH3_128 ?? (xxh3ns as any).default?.XXH3_128;
|
|
34
|
+
|
|
35
|
+
async function getXXH3(): Promise<(data: Buffer) => bigint> {
|
|
36
|
+
if (!XXH3_128) {
|
|
37
|
+
const { createRequire } = await import("node:module");
|
|
38
|
+
const f = createRequire(import.meta.url)("xxh3-ts/index.js").XXH3_128;
|
|
39
|
+
XXH3_128 = f;
|
|
40
|
+
return f;
|
|
41
|
+
}
|
|
42
|
+
return XXH3_128;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Compute a true XXH3-128 hash of the input data.
|
|
47
|
+
* Returns a 16-byte Uint8Array (little-endian: low 64 bits at offset 0, high 64 bits at offset 8).
|
|
48
|
+
*/
|
|
49
|
+
export async function xxh3_128(data: Uint8Array): Promise<Uint8Array> {
|
|
50
|
+
// Buffer.from(uint8array) works in both Node.js (native Buffer) and browser (polyfill).
|
|
51
|
+
const buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
52
|
+
const hash = (await getXXH3())(buf);
|
|
53
|
+
const result = new Uint8Array(16);
|
|
54
|
+
const view = new DataView(result.buffer);
|
|
55
|
+
// Low 64 bits at offset 0, high 64 bits at offset 8 (little-endian).
|
|
56
|
+
view.setBigUint64(0, hash & 0xFFFFFFFFFFFFFFFFn, true);
|
|
57
|
+
view.setBigUint64(8, (hash >> 64n) & 0xFFFFFFFFFFFFFFFFn, true);
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// @downdraft/engine/libraries/persistence — versioned, compressed save system
|
|
3
|
+
// ============================================================================
|
|
4
|
+
//
|
|
5
|
+
// This barrel re-exports everything including FileSaveStore (Node-only).
|
|
6
|
+
// For browser/renderer code that cannot import node:fs/node:path, import from
|
|
7
|
+
// @downdraft/engine/libraries/persistence/browser instead.
|
|
8
|
+
|
|
9
|
+
export { FileSaveStore } from "./file-save-store";
|
|
10
|
+
export type { FileSaveStoreOptions } from "./file-save-store";
|
|
11
|
+
|
|
12
|
+
export { createNodeFsDirectoryHandle } from "./node-fs-directory-handle";
|
|
13
|
+
|
|
14
|
+
export { AutosaveManager } from "./autosave-manager";
|
|
15
|
+
export type { AutosaveManagerOptions } from "./autosave-manager";
|
|
16
|
+
|
|
17
|
+
export { OpfsSaveStore } from "./opfs-save-store";
|
|
18
|
+
export type { OpfsSaveStoreOptions } from "./opfs-save-store";
|
|
19
|
+
|
|
20
|
+
export { BinaryRecordStore, createBinaryRecordStore } from "./binary-record-store";
|
|
21
|
+
export type { BinaryRecordStoreOptions, IBinaryRecordStore } from "./binary-record-store";
|
|
22
|
+
|
|
23
|
+
export { SaveWorkerProxy } from "./save-worker-proxy";
|
|
24
|
+
export type { SaveWorkerProxyOptions } from "./save-worker-proxy";
|
|
25
|
+
|
|
26
|
+
export type { SaveWorkerApi } from "./save-worker";
|
|
27
|
+
|
|
28
|
+
// Re-export core types for convenience
|
|
29
|
+
export {
|
|
30
|
+
decodeHeader, encodeHeader, engineVersionString, HEADER_SIZE, MigrationRegistryImpl,
|
|
31
|
+
packEngineVersion, readHeaderFromFile, SAVE_FORMAT_VERSION, SAVE_MAGIC, unpackEngineVersion, XXH128_SIZE
|
|
32
|
+
} from "@downdraft/engine/index";
|
|
33
|
+
|
|
34
|
+
export type {
|
|
35
|
+
ComponentMigration,
|
|
36
|
+
ComponentSection,
|
|
37
|
+
IMigrationRegistry,
|
|
38
|
+
IRendererStateProvider,
|
|
39
|
+
ISaveStore,
|
|
40
|
+
LoadOptions,
|
|
41
|
+
LoadResult,
|
|
42
|
+
SaveGenerationInfo,
|
|
43
|
+
SaveHeader,
|
|
44
|
+
SaveMeta,
|
|
45
|
+
SaveOptions,
|
|
46
|
+
SaveResult,
|
|
47
|
+
SaveSlotInfo,
|
|
48
|
+
SaveState,
|
|
49
|
+
SaveStateBuilder,
|
|
50
|
+
SaveWarning,
|
|
51
|
+
SaveWarningKind
|
|
52
|
+
} from "@downdraft/engine/index";
|
|
53
|
+
|
|
54
|
+
// Declarative library descriptor
|
|
55
|
+
export { PersistenceLib, PersistenceTok } from "./library";
|
|
56
|
+
export type { PersistenceLibConfig } from "./library";
|
|
57
|
+
|