@downdraft/engine 0.1.0 → 0.1.2-alpha.5
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/README.md +11 -0
- package/app/src/renderer/bootstrap.ts +295 -19
- package/app/src/renderer/game-module.ts +60 -12
- package/app/src/renderer/hooks.ts +9 -1
- package/app/src/renderer/hot-reload.ts +9 -9
- package/app/src/renderer/mcp-harness.ts +2 -2
- package/app/src/renderer/standard-automation-tools.ts +104 -3
- package/app/src/shared/feature-log.ts +2 -1
- package/app/src/shared/mcp-discovery.ts +8 -3
- package/app/src/shared/mcp-proxy.ts +2 -2
- package/asset-bake/README.md +22 -0
- package/core/README.md +25 -0
- package/core/src/animation/skeleton-animator.ts +23 -5
- package/core/src/assets/manager.ts +4 -4
- package/core/src/ecs/events.ts +1 -1
- package/core/src/ecs/schedule.ts +1 -1
- package/core/src/ecs/world.ts +1 -1
- package/core/src/index.ts +3 -4
- package/core/src/library/host.ts +27 -13
- package/core/src/library/library.ts +13 -5
- package/core/src/module/cross-thread.ts +6 -0
- package/core/src/module/diagnostics.ts +10 -6
- package/core/src/module/host.ts +65 -18
- package/core/src/module/index.ts +1 -0
- package/core/src/module/module.ts +11 -5
- package/core/src/module/renderer-module.ts +15 -0
- package/core/src/physics/safety.ts +1 -1
- package/core/src/platform/bun-preload.ts +7 -2
- package/core/src/platform/glob-polyfill.ts +17 -8
- package/core/src/platform/pkg-root.ts +27 -0
- package/core/src/platform/runtime.ts +38 -0
- package/core/src/plugin/discovery.ts +1 -1
- package/core/src/plugin/extension-loaders.ts +6 -4
- package/core/src/plugin/host.ts +13 -13
- package/core/src/plugin/loader-asset.ts +5 -5
- package/core/src/plugin/loader-quickjs.ts +1 -1
- package/core/src/plugin/loader-wasm.ts +3 -3
- package/core/src/plugin/loader-worker.ts +1 -1
- package/core/src/plugin/manifest.ts +8 -3
- package/core/src/plugin/workshop.ts +3 -3
- package/core/src/profiling/index.ts +1 -1
- package/core/src/profiling/profiling-sab.ts +19 -0
- package/core/src/profiling/warnings.ts +1 -1
- package/core/src/profiling/worker-prelude.ts +1 -1
- package/core/src/render/bindless/frame-bindings.ts +1 -1
- package/core/src/render/bindless/material-manager.ts +2 -2
- package/core/src/render/bindless/texture-registry.ts +2 -2
- package/core/src/render/device.ts +5 -5
- package/core/src/render/frame-graph.ts +2 -2
- package/core/src/render/game-renderer.ts +42 -18
- package/core/src/render/hot-reload.ts +3 -3
- package/core/src/render/renderer-module-host.ts +32 -12
- package/core/src/render/shader-validator.ts +7 -7
- package/core/src/render/surface.ts +1 -1
- package/core/src/sab/errors.ts +1 -1
- package/core/src/sab/sab-polyfill.ts +1 -1
- package/core/src/save/migration-registry.ts +4 -4
- package/core/src/save/schema.ts +1 -1
- package/core/src/scene/prefab.ts +1 -1
- package/core/src/scene/scene-manager.ts +2 -2
- package/core/src/scene/scene.ts +4 -4
- package/core/src/scene/streaming.ts +2 -2
- package/core/src/scripting/hot-reload.ts +2 -2
- package/core/src/sim/hot-reload-pipeline.ts +30 -6
- package/core/src/sim/sim-state-helper.ts +1 -1
- package/core/src/sim/transient-state-registry.ts +1 -1
- package/core/src/sim/worker-loop.ts +2 -2
- package/core/src/telemetry/gpu-profiler.ts +3 -3
- package/core/src/util/index.ts +1 -1
- package/core/src/util/logger.ts +36 -5
- package/core/src/version.ts +13 -0
- package/core/src/worker/base-worker-host.ts +87 -25
- package/core/src/worker/buffer-sync.ts +1 -1
- package/core/src/worker/crash-recovery.ts +2 -2
- package/core/src/worker/instrumented-worker-host.ts +3 -3
- package/core/src/worker/rpc.ts +62 -11
- package/core/src/worker/sim-worker-base.ts +3 -8
- package/core/src/worker/task-pool.ts +2 -2
- package/dist/.dd-manifest.json +4119 -0
- package/dist/app/src/index.js +9 -0
- package/dist/app/src/renderer/bootstrap.js +446 -0
- package/dist/app/src/renderer/downdraft-base.css +93 -0
- package/dist/app/src/renderer/feature-log.js +180 -0
- package/dist/app/src/renderer/game-module.js +562 -0
- package/dist/app/src/renderer/hooks.js +82 -0
- package/dist/app/src/renderer/hot-reload.js +158 -0
- package/dist/app/src/renderer/import-cache.js +77 -0
- package/dist/app/src/renderer/index.js +149 -0
- package/dist/app/src/renderer/mcp-harness.js +112 -0
- package/dist/app/src/renderer/save-store-factory.js +180 -0
- package/dist/app/src/renderer/sim-bridge.js +138 -0
- package/dist/app/src/renderer/standard-automation-tools.js +720 -0
- package/dist/app/src/shared/feature-log.js +54 -0
- package/dist/app/src/shared/gpu-info.js +74 -0
- package/dist/app/src/shared/import-cache-store.js +123 -0
- package/dist/app/src/shared/index.js +4 -0
- package/dist/app/src/shared/mcp-discovery.js +55 -0
- package/dist/app/src/shared/mcp-proxy.js +71 -0
- package/dist/app/src/shared/types.js +13 -0
- package/dist/asset-bake/src/bake-audio.js +103 -0
- package/dist/asset-bake/src/bake-gltf.js +141 -0
- package/dist/asset-bake/src/bake.js +63 -0
- package/dist/asset-bake/src/cache.js +147 -0
- package/dist/asset-bake/src/config.js +93 -0
- package/dist/asset-bake/src/index.js +25 -0
- package/dist/core/src/animation/animation-event.js +24 -0
- package/dist/core/src/animation/bone-mask.js +103 -0
- package/dist/core/src/animation/clip.js +210 -0
- package/dist/core/src/animation/index.js +13 -0
- package/dist/core/src/animation/mixamo.js +78 -0
- package/dist/core/src/animation/morph-target.js +37 -0
- package/dist/core/src/animation/player.js +621 -0
- package/dist/core/src/animation/retarget.js +101 -0
- package/dist/core/src/animation/skeleton-animator.js +1361 -0
- package/dist/core/src/animation/skeleton.js +166 -0
- package/dist/core/src/animation/state-machine.js +252 -0
- package/dist/core/src/assets/blob-store.js +14 -0
- package/dist/core/src/assets/cache.js +168 -0
- package/dist/core/src/assets/cubemap-converter.js +129 -0
- package/dist/core/src/assets/environment-manager.js +84 -0
- package/dist/core/src/assets/import-cache.js +36 -0
- package/dist/core/src/assets/import-settings.js +34 -0
- package/dist/core/src/assets/importer.js +78 -0
- package/dist/core/src/assets/index.js +29 -0
- package/dist/core/src/assets/irradiance-generator.js +179 -0
- package/dist/core/src/assets/loader-audio.js +70 -0
- package/dist/core/src/assets/loader-cubemap.js +141 -0
- package/dist/core/src/assets/loader-dds.js +185 -0
- package/dist/core/src/assets/loader-hdr.js +430 -0
- package/dist/core/src/assets/loader-mesh.js +47 -0
- package/dist/core/src/assets/loader-shader.js +61 -0
- package/dist/core/src/assets/loader-texture.js +264 -0
- package/dist/core/src/assets/lod.js +150 -0
- package/dist/core/src/assets/manager.js +401 -0
- package/dist/core/src/assets/manifest.js +57 -0
- package/dist/core/src/assets/material-bridge.js +160 -0
- package/dist/core/src/assets/model-importer.js +32 -0
- package/dist/core/src/assets/model-normalizer.js +213 -0
- package/dist/core/src/assets/model-to-gpu.js +44 -0
- package/dist/core/src/assets/model-to-mesh.js +171 -0
- package/dist/core/src/assets/prefilter-generator.js +220 -0
- package/dist/core/src/audio/engine.js +153 -0
- package/dist/core/src/audio/interface.js +8 -0
- package/dist/core/src/audio/listener.js +19 -0
- package/dist/core/src/audio/mixer.js +124 -0
- package/dist/core/src/audio/registry.js +43 -0
- package/dist/core/src/audio/sab.js +74 -0
- package/dist/core/src/audio/source.js +60 -0
- package/dist/core/src/change-detection/atomics.js +1 -0
- package/dist/core/src/change-detection/tracker.js +26 -0
- package/dist/core/src/debug-draw/lines.js +27 -0
- package/dist/core/src/debug-draw/points.js +9 -0
- package/dist/core/src/debug-draw/queue.js +77 -0
- package/dist/core/src/debug-draw/text.js +12 -0
- package/dist/core/src/ecs/archetype.js +271 -0
- package/dist/core/src/ecs/component.js +109 -0
- package/dist/core/src/ecs/entity.js +11 -0
- package/dist/core/src/ecs/events.js +73 -0
- package/dist/core/src/ecs/hierarchy.js +104 -0
- package/dist/core/src/ecs/hmr-swap-registry.js +15 -0
- package/dist/core/src/ecs/index.js +14 -0
- package/dist/core/src/ecs/query.js +110 -0
- package/dist/core/src/ecs/resource.js +3 -0
- package/dist/core/src/ecs/schedule.js +157 -0
- package/dist/core/src/ecs/system-params.js +45 -0
- package/dist/core/src/ecs/system.js +18 -0
- package/dist/core/src/ecs/world.js +292 -0
- package/dist/core/src/index.js +191 -0
- package/dist/core/src/input/context.js +69 -0
- package/dist/core/src/input/dom-handler.js +288 -0
- package/dist/core/src/input/local-player-manager.js +145 -0
- package/dist/core/src/input/mapping.js +36 -0
- package/dist/core/src/input/multi-sab-bridge.js +224 -0
- package/dist/core/src/input/multi-state.js +48 -0
- package/dist/core/src/input/sab-bridge.js +66 -0
- package/dist/core/src/input/state.js +108 -0
- package/dist/core/src/input/ui-router.js +76 -0
- package/dist/core/src/library/host.js +291 -0
- package/dist/core/src/library/index.js +1 -0
- package/dist/core/src/library/library.js +20 -0
- package/dist/core/src/material/compiler.js +73 -0
- package/dist/core/src/material/graph-bridge.js +119 -0
- package/dist/core/src/material/index.js +6 -0
- package/dist/core/src/material/library.js +414 -0
- package/dist/core/src/material/material.js +120 -0
- package/dist/core/src/material/variants.js +37 -0
- package/dist/core/src/math/mat4.js +198 -0
- package/dist/core/src/math/perlin-noise-2d.js +66 -0
- package/dist/core/src/math/perlin-noise-3d.js +76 -0
- package/dist/core/src/math/quat.js +29 -0
- package/dist/core/src/math/rng.js +25 -0
- package/dist/core/src/math/trig.js +42 -0
- package/dist/core/src/math/value-noise.js +49 -0
- package/dist/core/src/mesh/builder.js +137 -0
- package/dist/core/src/mesh/csg.js +250 -0
- package/dist/core/src/mesh/greased-line.js +102 -0
- package/dist/core/src/mesh/mesh.js +6 -0
- package/dist/core/src/mesh/parametric.js +392 -0
- package/dist/core/src/mesh/skinning.js +30 -0
- package/dist/core/src/mesh/vertex-layout.js +65 -0
- package/dist/core/src/module/cross-thread.js +126 -0
- package/dist/core/src/module/diagnostics.js +99 -0
- package/dist/core/src/module/host.js +449 -0
- package/dist/core/src/module/index.js +6 -0
- package/dist/core/src/module/module.js +1 -0
- package/dist/core/src/module/registry.js +83 -0
- package/dist/core/src/module/renderer-module.js +13 -0
- package/dist/core/src/module/ts-loader.js +20 -0
- package/dist/core/src/particles/compute-pass.js +329 -0
- package/dist/core/src/particles/emitter.js +113 -0
- package/dist/core/src/particles/index.js +7 -0
- package/dist/core/src/particles/particle-data.js +33 -0
- package/dist/core/src/particles/render-pass.js +338 -0
- package/dist/core/src/particles/simulator.js +224 -0
- package/dist/core/src/particles/system.js +157 -0
- package/dist/core/src/physics/body.js +25 -0
- package/dist/core/src/physics/ccd-heuristic.js +46 -0
- package/dist/core/src/physics/character.js +184 -0
- package/dist/core/src/physics/collider.js +36 -0
- package/dist/core/src/physics/collision-system.js +62 -0
- package/dist/core/src/physics/events.js +74 -0
- package/dist/core/src/physics/index.js +24 -0
- package/dist/core/src/physics/interface.js +14 -0
- package/dist/core/src/physics/interpolation-buffer.js +182 -0
- package/dist/core/src/physics/lifecycle.js +66 -0
- package/dist/core/src/physics/load-shedder.js +155 -0
- package/dist/core/src/physics/physics-accumulator.js +94 -0
- package/dist/core/src/physics/physics-system.js +142 -0
- package/dist/core/src/physics/ragdoll-presets.js +248 -0
- package/dist/core/src/physics/ragdoll-system.js +193 -0
- package/dist/core/src/physics/ragdoll.js +117 -0
- package/dist/core/src/physics/raycast.js +97 -0
- package/dist/core/src/physics/realm-manager.js +431 -0
- package/dist/core/src/physics/realm-worker-pool.js +181 -0
- package/dist/core/src/physics/realm-worker.js +91 -0
- package/dist/core/src/physics/realm.js +137 -0
- package/dist/core/src/physics/registry.js +43 -0
- package/dist/core/src/physics/safety.js +211 -0
- package/dist/core/src/physics/snapshot-manager.js +118 -0
- package/dist/core/src/physics/worker-protocol.js +1 -0
- package/dist/core/src/platform/bun-preload.js +175 -0
- package/dist/core/src/platform/css-stub.js +4 -0
- package/dist/core/src/platform/glob-polyfill.js +137 -0
- package/dist/core/src/platform/hidpi.js +52 -0
- package/dist/core/src/platform/pkg-root.js +27 -0
- package/dist/core/src/platform/render-surface.js +15 -0
- package/dist/core/src/platform/rpc.js +82 -0
- package/dist/core/src/platform/runtime.js +93 -0
- package/dist/core/src/plugin/context.js +144 -0
- package/dist/core/src/plugin/diagnostics.js +20 -0
- package/dist/core/src/plugin/discovery.js +124 -0
- package/dist/core/src/plugin/extension-loaders.js +111 -0
- package/dist/core/src/plugin/host.js +542 -0
- package/dist/core/src/plugin/index.js +19 -0
- package/dist/core/src/plugin/loader-asset.js +105 -0
- package/dist/core/src/plugin/loader-quickjs.js +67 -0
- package/dist/core/src/plugin/loader-wasm.js +385 -0
- package/dist/core/src/plugin/loader-worker.js +228 -0
- package/dist/core/src/plugin/manifest.js +424 -0
- package/dist/core/src/plugin/material-registry.js +44 -0
- package/dist/core/src/plugin/mcp-tools.js +147 -0
- package/dist/core/src/plugin/permissions.js +152 -0
- package/dist/core/src/plugin/quickjs-bridge.js +219 -0
- package/dist/core/src/plugin/registry.js +92 -0
- package/dist/core/src/plugin/sandbox-shim.js +79 -0
- package/dist/core/src/plugin/sandbox-worker.js +194 -0
- package/dist/core/src/plugin/wasm-abi.js +62 -0
- package/dist/core/src/plugin/wasm-worker.js +234 -0
- package/dist/core/src/plugin/workshop.js +131 -0
- package/dist/core/src/profiling/event-loop.js +164 -0
- package/dist/core/src/profiling/index.js +23 -0
- package/dist/core/src/profiling/iops/idb-patch.js +211 -0
- package/dist/core/src/profiling/iops/opfs-patch.js +206 -0
- package/dist/core/src/profiling/profiling-sab.js +632 -0
- package/dist/core/src/profiling/task-latency.js +118 -0
- package/dist/core/src/profiling/thread-metrics.js +103 -0
- package/dist/core/src/profiling/trace-event-writer.js +165 -0
- package/dist/core/src/profiling/warnings.js +304 -0
- package/dist/core/src/profiling/worker-prelude.js +281 -0
- package/dist/core/src/render/bind-group.js +33 -0
- package/dist/core/src/render/bindless/bindless-struct.js +39 -0
- package/dist/core/src/render/bindless/bindless.wgsl.js +163 -0
- package/dist/core/src/render/bindless/frame-bindings.js +142 -0
- package/dist/core/src/render/bindless/index.js +6 -0
- package/dist/core/src/render/bindless/material-manager.js +182 -0
- package/dist/core/src/render/bindless/texture-registry.js +498 -0
- package/dist/core/src/render/buffer.js +74 -0
- package/dist/core/src/render/camera-2d.js +151 -0
- package/dist/core/src/render/camera-controller.js +370 -0
- package/dist/core/src/render/camera.js +332 -0
- package/dist/core/src/render/canvas-resize-watcher.js +36 -0
- package/dist/core/src/render/compute-kernel.js +130 -0
- package/dist/core/src/render/constants.js +2 -0
- package/dist/core/src/render/device.js +91 -0
- package/dist/core/src/render/frame-graph.js +594 -0
- package/dist/core/src/render/frustum.js +152 -0
- package/dist/core/src/render/fullscreen-vs.js +24 -0
- package/dist/core/src/render/g-buffer.js +156 -0
- package/dist/core/src/render/game-renderer.js +1165 -0
- package/dist/core/src/render/gpu-driven/cull-pass.js +352 -0
- package/dist/core/src/render/gpu-driven/hzb.js +183 -0
- package/dist/core/src/render/gpu-driven/index.js +6 -0
- package/dist/core/src/render/gpu-driven/indirect-draw-pass.js +300 -0
- package/dist/core/src/render/gpu-driven/instance-buffer.js +150 -0
- package/dist/core/src/render/gpu-driven/mesh-table.js +130 -0
- package/dist/core/src/render/gpu-driven/passes/hzb-build-pass.js +39 -0
- package/dist/core/src/render/gpu-utils.js +72 -0
- package/dist/core/src/render/hdr.js +69 -0
- package/dist/core/src/render/hot-reload.js +236 -0
- package/dist/core/src/render/ibl-bind-group.js +232 -0
- package/dist/core/src/render/ibl.js +148 -0
- package/dist/core/src/render/index.js +86 -0
- package/dist/core/src/render/input-manager.js +224 -0
- package/dist/core/src/render/lighting/area-light.js +142 -0
- package/dist/core/src/render/lighting/cluster-grid.js +255 -0
- package/dist/core/src/render/lighting/cluster-types.js +87 -0
- package/dist/core/src/render/lighting/ies-parser.js +111 -0
- package/dist/core/src/render/lighting.js +300 -0
- package/dist/core/src/render/material-types/depth.wgsl +44 -0
- package/dist/core/src/render/material-types/line.wgsl +50 -0
- package/dist/core/src/render/material-types/matcap.wgsl +51 -0
- package/dist/core/src/render/material-types/normal.wgsl +41 -0
- package/dist/core/src/render/material-types/physical.wgsl +152 -0
- package/dist/core/src/render/material-types/sprite.wgsl +46 -0
- package/dist/core/src/render/material-types/sss.wgsl +79 -0
- package/dist/core/src/render/material-types/toon.wgsl +79 -0
- package/dist/core/src/render/passes/README.md +121 -0
- package/dist/core/src/render/passes/atmosphere.js +107 -0
- package/dist/core/src/render/passes/cluster-lighting-pass.js +441 -0
- package/dist/core/src/render/passes/csm.js +338 -0
- package/dist/core/src/render/passes/cubemap-capture.js +93 -0
- package/dist/core/src/render/passes/debug-viz.js +248 -0
- package/dist/core/src/render/passes/debug.js +500 -0
- package/dist/core/src/render/passes/decal-mesh.js +86 -0
- package/dist/core/src/render/passes/decal-pass.js +344 -0
- package/dist/core/src/render/passes/deferred-lighting.js +406 -0
- package/dist/core/src/render/passes/depth-prepass.js +148 -0
- package/dist/core/src/render/passes/dome-360.js +68 -0
- package/dist/core/src/render/passes/fluid-render.js +116 -0
- package/dist/core/src/render/passes/gi-types.js +78 -0
- package/dist/core/src/render/passes/graph-compute.js +251 -0
- package/dist/core/src/render/passes/greased-line-pass.js +218 -0
- package/dist/core/src/render/passes/morph-target.js +35 -0
- package/dist/core/src/render/passes/opaque.js +966 -0
- package/dist/core/src/render/passes/point-light-shadow.js +221 -0
- package/dist/core/src/render/passes/procedural-texture.js +142 -0
- package/dist/core/src/render/passes/reflection-probe.js +100 -0
- package/dist/core/src/render/passes/rsm-pass.js +228 -0
- package/dist/core/src/render/passes/sdf-text.js +114 -0
- package/dist/core/src/render/passes/shadow-map.js +121 -0
- package/dist/core/src/render/passes/shadow.js +191 -0
- package/dist/core/src/render/passes/skinning-vs.js +102 -0
- package/dist/core/src/render/passes/skinning.js +282 -0
- package/dist/core/src/render/passes/sky-dome.js +380 -0
- package/dist/core/src/render/passes/skybox.js +146 -0
- package/dist/core/src/render/passes/spot-light-shadow.js +223 -0
- package/dist/core/src/render/passes/terrain.js +303 -0
- package/dist/core/src/render/passes/transparent.js +323 -0
- package/dist/core/src/render/passes/underwater-fog.js +173 -0
- package/dist/core/src/render/passes/video-texture.js +58 -0
- package/dist/core/src/render/passes/volumetric-pass.js +278 -0
- package/dist/core/src/render/passes/volumetric-types.js +96 -0
- package/dist/core/src/render/passes/water.js +697 -0
- package/dist/core/src/render/pbr.js +257 -0
- package/dist/core/src/render/pipeline.js +49 -0
- package/dist/core/src/render/render-pass.js +13 -0
- package/dist/core/src/render/renderer-input-bus.js +176 -0
- package/dist/core/src/render/renderer-module-host.js +539 -0
- package/dist/core/src/render/resource-tracker.js +59 -0
- package/dist/core/src/render/sab-canvas-overlay.js +83 -0
- package/dist/core/src/render/shader-validator.js +172 -0
- package/dist/core/src/render/shaders/debug/debug-line.wgsl +27 -0
- package/dist/core/src/render/shaders/debug/debug-point.wgsl +30 -0
- package/dist/core/src/render/shaders/debug/debug-text.wgsl +42 -0
- package/dist/core/src/render/shaders/debug-viz/aabb.wgsl +20 -0
- package/dist/core/src/render/shaders/debug-viz/depth.wgsl +29 -0
- package/dist/core/src/render/shaders/debug-viz/lod.wgsl +38 -0
- package/dist/core/src/render/shaders/debug-viz/normals.wgsl +30 -0
- package/dist/core/src/render/shaders/debug-viz/overdraw.wgsl +21 -0
- package/dist/core/src/render/shaders/debug-viz/tangents.wgsl +29 -0
- package/dist/core/src/render/shaders/debug-viz/wireframe.wgsl +33 -0
- package/dist/core/src/render/shaders/shadow-chunks.js +133 -0
- package/dist/core/src/render/skybox.js +123 -0
- package/dist/core/src/render/splitscreen.js +60 -0
- package/dist/core/src/render/surface.js +63 -0
- package/dist/core/src/render/tonemap.js +171 -0
- package/dist/core/src/render/tracked-render-pass.js +115 -0
- package/dist/core/src/render/viewport.js +81 -0
- package/dist/core/src/render/wgsl-hmr.js +66 -0
- package/dist/core/src/sab/core-input-channel.js +22 -0
- package/dist/core/src/sab/define.js +127 -0
- package/dist/core/src/sab/errors.js +60 -0
- package/dist/core/src/sab/game-input.js +299 -0
- package/dist/core/src/sab/gamepad-devices.js +205 -0
- package/dist/core/src/sab/grid-buffer.js +91 -0
- package/dist/core/src/sab/input.js +38 -0
- package/dist/core/src/sab/layout.js +160 -0
- package/dist/core/src/sab/multi-input-channel.js +39 -0
- package/dist/core/src/sab/record-buffer.js +130 -0
- package/dist/core/src/sab/sab-polyfill.js +47 -0
- package/dist/core/src/sab/sim-channel.js +397 -0
- package/dist/core/src/sab/slot-buffer.js +140 -0
- package/dist/core/src/sab/types.js +1 -0
- package/dist/core/src/safety/bounds.js +71 -0
- package/dist/core/src/safety/json.js +70 -0
- package/dist/core/src/safety/path.js +151 -0
- package/dist/core/src/save/binary-format.js +95 -0
- package/dist/core/src/save/game-save-system.js +101 -0
- package/dist/core/src/save/grid-save-system.js +102 -0
- package/dist/core/src/save/migrate.js +35 -0
- package/dist/core/src/save/migration-registry.js +66 -0
- package/dist/core/src/save/persist-types.js +4 -0
- package/dist/core/src/save/schema.js +36 -0
- package/dist/core/src/save/serializer.js +139 -0
- package/dist/core/src/scene/builder.js +31 -0
- package/dist/core/src/scene/camera.js +118 -0
- package/dist/core/src/scene/checkpoint.js +84 -0
- package/dist/core/src/scene/game-loop.js +155 -0
- package/dist/core/src/scene/index.js +14 -0
- package/dist/core/src/scene/layer.js +7 -0
- package/dist/core/src/scene/prefab.js +97 -0
- package/dist/core/src/scene/scene-manager.js +141 -0
- package/dist/core/src/scene/scene.js +147 -0
- package/dist/core/src/scene/sky.js +179 -0
- package/dist/core/src/scene/spatial-grid.js +140 -0
- package/dist/core/src/scene/streaming.js +247 -0
- package/dist/core/src/scene/vegetation.js +107 -0
- package/dist/core/src/scene/world.js +66 -0
- package/dist/core/src/scripting/binding.js +85 -0
- package/dist/core/src/scripting/hot-reload.js +123 -0
- package/dist/core/src/scripting/script.js +68 -0
- package/dist/core/src/sim/hot-reload-pipeline.js +65 -0
- package/dist/core/src/sim/sim-state-helper.js +40 -0
- package/dist/core/src/sim/transient-state-registry.js +63 -0
- package/dist/core/src/sim/types.js +4 -0
- package/dist/core/src/sim/worker-loop.js +168 -0
- package/dist/core/src/stores/game-store.js +81 -0
- package/dist/core/src/stores/hot-reload-store.js +19 -0
- package/dist/core/src/telemetry/collector.js +303 -0
- package/dist/core/src/telemetry/gc-controller.js +365 -0
- package/dist/core/src/telemetry/gc-profiler.js +82 -0
- package/dist/core/src/telemetry/gc-tracker.js +63 -0
- package/dist/core/src/telemetry/gpu-profiler.js +554 -0
- package/dist/core/src/telemetry/gpu-resource-tracker.js +234 -0
- package/dist/core/src/telemetry/gpu-timer-pool.js +223 -0
- package/dist/core/src/telemetry/gpu-timer.js +117 -0
- package/dist/core/src/telemetry/gpu-timestamp-gate.js +22 -0
- package/dist/core/src/telemetry/reporter.js +56 -0
- package/dist/core/src/types/engine-types.js +21 -0
- package/dist/core/src/ui-font-scale.js +111 -0
- package/dist/core/src/util/broad-phase-grid.js +77 -0
- package/dist/core/src/util/feature-log.js +176 -0
- package/dist/core/src/util/index.js +4 -0
- package/dist/core/src/util/logger.js +596 -0
- package/dist/core/src/version.js +11 -0
- package/dist/core/src/webgpu-destroy-augmentation.d.ts +25 -0
- package/dist/core/src/worker/base-worker-host.js +212 -0
- package/dist/core/src/worker/buffer-sync.js +454 -0
- package/dist/core/src/worker/crash-recovery.js +153 -0
- package/dist/core/src/worker/entity-sim-worker-host.js +128 -0
- package/dist/core/src/worker/instrumented-worker-host.js +139 -0
- package/dist/core/src/worker/rpc.js +244 -0
- package/dist/core/src/worker/sim-worker-base.js +558 -0
- package/dist/core/src/worker/sim-worker-host.js +271 -0
- package/dist/core/src/worker/task-pool.js +205 -0
- package/dist/core/src/worker/task-worker.js +77 -0
- package/dist/libraries/asset-browser/src/index.js +10 -0
- package/dist/libraries/asset-browser/src/software-thumbnails.js +940 -0
- package/dist/libraries/audio-kira/src/backend.js +405 -0
- package/dist/libraries/audio-kira/src/index.js +4 -0
- package/dist/libraries/audio-kira/src/library.js +54 -0
- package/dist/libraries/blitz-ui/src/index.js +13 -0
- package/dist/libraries/blitz-ui/src/native-module.js +162 -0
- package/dist/libraries/blitz-ui/src/native-osr-ffi.js +409 -0
- package/dist/libraries/blitz-ui/src/router.js +82 -0
- package/dist/libraries/blitz-ui/src/shaders/ui-blit.wgsl.js +32 -0
- package/dist/libraries/blitz-ui/src/ui-blit-pass.js +108 -0
- package/dist/libraries/character/src/character-animator.js +323 -0
- package/dist/libraries/character/src/customization.js +464 -0
- package/dist/libraries/character/src/index.js +19 -0
- package/dist/libraries/character/src/inspectable.js +77 -0
- package/dist/libraries/character/src/loader.js +336 -0
- package/dist/libraries/character/src/locomotion.js +84 -0
- package/dist/libraries/character/src/preview.js +280 -0
- package/dist/libraries/devtools/src/backend.js +449 -0
- package/dist/libraries/devtools/src/cdp-bridge.js +293 -0
- package/dist/libraries/devtools/src/collectors.js +318 -0
- package/dist/libraries/devtools/src/index.js +31 -0
- package/dist/libraries/devtools/src/native-providers.js +749 -0
- package/dist/libraries/devtools/src/snapshot.js +35 -0
- package/dist/libraries/devtools/src/verify.js +139 -0
- package/dist/libraries/devtools/src/web/browser.js +94 -0
- package/dist/libraries/devtools/src/web/host.js +183 -0
- package/dist/libraries/devtools/src/web/mirror.js +26 -0
- package/dist/libraries/devtools/src/web/server.js +187 -0
- package/dist/libraries/entities/src/index.js +3 -0
- package/dist/libraries/entities/src/library.js +46 -0
- package/dist/libraries/entities/src/model-renderer.js +1307 -0
- package/dist/libraries/entities/src/shaders/model.wgsl +375 -0
- package/dist/libraries/gamepad/src/feed-input.js +54 -0
- package/dist/libraries/gamepad/src/filters.js +44 -0
- package/dist/libraries/gamepad/src/glyphs.js +83 -0
- package/dist/libraries/gamepad/src/hub.js +164 -0
- package/dist/libraries/gamepad/src/index.js +10 -0
- package/dist/libraries/gamepad/src/library.js +56 -0
- package/dist/libraries/gamepad/src/source-sab.js +62 -0
- package/dist/libraries/gamepad/src/sysfs-enrich.js +125 -0
- package/dist/libraries/gaussian-splats/src/gpu-sort.js +506 -0
- package/dist/libraries/gaussian-splats/src/index.js +8 -0
- package/dist/libraries/gaussian-splats/src/library.js +44 -0
- package/dist/libraries/gaussian-splats/src/parser.js +297 -0
- package/dist/libraries/gaussian-splats/src/renderer.js +368 -0
- package/dist/libraries/gaussian-splats/src/sh-eval.js +196 -0
- package/dist/libraries/gaussian-splats/src/sorter.js +76 -0
- package/dist/libraries/gaussian-splats/src/tile-raster.js +424 -0
- package/dist/libraries/gpu-kernels/src/index.js +8 -0
- package/dist/libraries/gpu-kernels/src/kernel.js +591 -0
- package/dist/libraries/gpu-kernels/src/transpile.js +896 -0
- package/dist/libraries/html-ui-kit/src/behaviors.js +231 -0
- package/dist/libraries/html-ui-kit/src/components.js +219 -0
- package/dist/libraries/html-ui-kit/src/index.js +17 -0
- package/dist/libraries/html-ui-kit/src/nav/nav-controller.js +215 -0
- package/dist/libraries/html-ui-kit/src/nav/nav-input.js +138 -0
- package/dist/libraries/html-ui-kit/src/nav/osk.js +135 -0
- package/dist/libraries/html-ui-kit/src/nav/router.js +152 -0
- package/dist/libraries/html-ui-kit/src/nav/vcursor.js +177 -0
- package/dist/libraries/html-ui-kit/src/ten-foot.js +138 -0
- package/dist/libraries/html-ui-kit/src/theme.js +235 -0
- package/dist/libraries/inspectable/src/index.js +6 -0
- package/dist/libraries/inspectable/src/inspectable.js +205 -0
- package/dist/libraries/lighting/src/index.js +4 -0
- package/dist/libraries/lighting/src/library.js +48 -0
- package/dist/libraries/lighting/src/light-system.js +395 -0
- package/dist/libraries/lighting/src/lighting-system.js +57 -0
- package/dist/libraries/lighting/src/shaders/light-debug.wgsl +30 -0
- package/dist/libraries/marching-cubes/src/chunked-field.js +130 -0
- package/dist/libraries/marching-cubes/src/deformation.js +41 -0
- package/dist/libraries/marching-cubes/src/generator.js +356 -0
- package/dist/libraries/marching-cubes/src/index.js +13 -0
- package/dist/libraries/marching-cubes/src/library.js +54 -0
- package/dist/libraries/marching-cubes/src/lod.js +95 -0
- package/dist/libraries/marching-cubes/src/marching-tetrahedra.js +261 -0
- package/dist/libraries/marching-cubes/src/sab.js +40 -0
- package/dist/libraries/marching-cubes/src/streaming-config.js +28 -0
- package/dist/libraries/marching-cubes/src/streaming-manager.js +490 -0
- package/dist/libraries/marching-cubes/src/tables.js +314 -0
- package/dist/libraries/marching-cubes/src/types.js +1 -0
- package/dist/libraries/models/src/bake-node-transforms.js +146 -0
- package/dist/libraries/models/src/bind-unskinned-meshes.js +145 -0
- package/dist/libraries/models/src/codecs/basisu-codec.js +134 -0
- package/dist/libraries/models/src/codecs/draco-codec.js +236 -0
- package/dist/libraries/models/src/codecs/draco3dgltf.d.ts +40 -0
- package/dist/libraries/models/src/codecs/index.js +5 -0
- package/dist/libraries/models/src/codecs/meshopt-codec.js +59 -0
- package/dist/libraries/models/src/codecs/registry.js +111 -0
- package/dist/libraries/models/src/dae.js +665 -0
- package/dist/libraries/models/src/default-part-selection.js +58 -0
- package/dist/libraries/models/src/dxf.js +235 -0
- package/dist/libraries/models/src/fbx/index.js +438 -0
- package/dist/libraries/models/src/fbx/interpreter/animation.js +369 -0
- package/dist/libraries/models/src/fbx/interpreter/blend-shapes.js +283 -0
- package/dist/libraries/models/src/fbx/interpreter/connections.js +158 -0
- package/dist/libraries/models/src/fbx/interpreter/diagnostics.js +48 -0
- package/dist/libraries/models/src/fbx/interpreter/geometry.js +430 -0
- package/dist/libraries/models/src/fbx/interpreter/global-settings.js +77 -0
- package/dist/libraries/models/src/fbx/interpreter/materials.js +231 -0
- package/dist/libraries/models/src/fbx/interpreter/nodes.js +168 -0
- package/dist/libraries/models/src/fbx/interpreter/skeleton.js +454 -0
- package/dist/libraries/models/src/fbx/parsers/binary-parser.js +217 -0
- package/dist/libraries/models/src/fbx/types.js +88 -0
- package/dist/libraries/models/src/gltf-extensions.js +121 -0
- package/dist/libraries/models/src/gltf.js +724 -0
- package/dist/libraries/models/src/index.js +46 -0
- package/dist/libraries/models/src/library.js +44 -0
- package/dist/libraries/models/src/loader.js +218 -0
- package/dist/libraries/models/src/material-adapter.js +82 -0
- package/dist/libraries/models/src/mini-xml.js +145 -0
- package/dist/libraries/models/src/normalize.js +168 -0
- package/dist/libraries/models/src/obj.js +247 -0
- package/dist/libraries/models/src/off.js +94 -0
- package/dist/libraries/models/src/ply.js +329 -0
- package/dist/libraries/models/src/pose-sampler.js +183 -0
- package/dist/libraries/models/src/sidecar/blender-extras.js +32 -0
- package/dist/libraries/models/src/sidecar/ddmeta.js +98 -0
- package/dist/libraries/models/src/sidecar/godot-import.js +76 -0
- package/dist/libraries/models/src/sidecar/resolver.js +112 -0
- package/dist/libraries/models/src/sidecar/types.js +8 -0
- package/dist/libraries/models/src/sidecar/unity-meta.js +46 -0
- package/dist/libraries/models/src/skeleton-synthesis.js +122 -0
- package/dist/libraries/models/src/stl.js +129 -0
- package/dist/libraries/models/src/threeds.js +312 -0
- package/dist/libraries/models/src/threemf.js +203 -0
- package/dist/libraries/models/src/types.js +33 -0
- package/dist/libraries/models/src/vtk.js +242 -0
- package/dist/libraries/navmesh/src/crowd-system.js +207 -0
- package/dist/libraries/navmesh/src/debug-viz.js +52 -0
- package/dist/libraries/navmesh/src/index.js +7 -0
- package/dist/libraries/navmesh/src/library.js +47 -0
- package/dist/libraries/navmesh/src/navmesh-generator.js +364 -0
- package/dist/libraries/navmesh/src/navmesh.js +141 -0
- package/dist/libraries/navmesh/src/pathfinder.js +221 -0
- package/dist/libraries/navmesh/src/types.js +1 -0
- package/dist/libraries/networking/src/authority.js +107 -0
- package/dist/libraries/networking/src/connection.js +107 -0
- package/dist/libraries/networking/src/discovery.js +314 -0
- package/dist/libraries/networking/src/enhanced-replication.js +282 -0
- package/dist/libraries/networking/src/epic-adapter.js +101 -0
- package/dist/libraries/networking/src/index.js +16 -0
- package/dist/libraries/networking/src/library.js +45 -0
- package/dist/libraries/networking/src/lobby.js +84 -0
- package/dist/libraries/networking/src/platform-adapter.js +92 -0
- package/dist/libraries/networking/src/rcs-adapter.js +100 -0
- package/dist/libraries/networking/src/remote-input.js +162 -0
- package/dist/libraries/networking/src/replication.js +273 -0
- package/dist/libraries/networking/src/rpc.js +172 -0
- package/dist/libraries/networking/src/session.js +129 -0
- package/dist/libraries/networking/src/transport.js +156 -0
- package/dist/libraries/networking/src/webrtc.js +266 -0
- package/dist/libraries/pathfinding-2d/src/astar-grid.js +255 -0
- package/dist/libraries/pathfinding-2d/src/index.js +9 -0
- package/dist/libraries/persistence/src/autosave-manager.js +94 -0
- package/dist/libraries/persistence/src/binary-record-store.js +205 -0
- package/dist/libraries/persistence/src/browser.js +16 -0
- package/dist/libraries/persistence/src/file-save-store.js +507 -0
- package/dist/libraries/persistence/src/hash-utils.js +54 -0
- package/dist/libraries/persistence/src/index.js +17 -0
- package/dist/libraries/persistence/src/library.js +51 -0
- package/dist/libraries/persistence/src/mock-opfs.js +114 -0
- package/dist/libraries/persistence/src/node-fs-directory-handle.js +168 -0
- package/dist/libraries/persistence/src/opfs-save-store.js +584 -0
- package/dist/libraries/persistence/src/save-worker-proxy.js +96 -0
- package/dist/libraries/persistence/src/save-worker.js +76 -0
- package/dist/libraries/persistence/src/xxh3-ts.d.ts +10 -0
- package/dist/libraries/physics-native/src/backend.js +960 -0
- package/dist/libraries/physics-native/src/broadphase.js +79 -0
- package/dist/libraries/physics-native/src/index.js +6 -0
- package/dist/libraries/physics-native/src/library.js +57 -0
- package/dist/libraries/physics-native/src/narrowphase-shapes.js +348 -0
- package/dist/libraries/physics-native/src/narrowphase.js +60 -0
- package/dist/libraries/physics-native/src/solver.js +105 -0
- package/dist/libraries/physics-native/src/types.js +4 -0
- package/dist/libraries/physics-rapier/src/api.js +352 -0
- package/dist/libraries/physics-rapier/src/auto-backend.js +54 -0
- package/dist/libraries/physics-rapier/src/backend.js +1066 -0
- package/dist/libraries/physics-rapier/src/bulk-ops.js +46 -0
- package/dist/libraries/physics-rapier/src/ffi-backend.js +17 -0
- package/dist/libraries/physics-rapier/src/ffi-lib.js +605 -0
- package/dist/libraries/physics-rapier/src/index.js +9 -0
- package/dist/libraries/physics-rapier/src/library.js +71 -0
- package/dist/libraries/physics-rapier/src/rapier-backend.js +1102 -0
- package/dist/libraries/physics-rapier/src/realm-worker-script.js +233 -0
- package/dist/libraries/postfx/src/index.js +14 -0
- package/dist/libraries/postfx/src/library.js +207 -0
- package/dist/libraries/postfx/src/post-process-stack.js +1641 -0
- package/dist/libraries/postfx/src/shaders/post-process/afterimage.wgsl +14 -0
- package/dist/libraries/postfx/src/shaders/post-process/ascii.wgsl +24 -0
- package/dist/libraries/postfx/src/shaders/post-process/blit.wgsl +12 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-blur.wgsl +21 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-bright.wgsl +15 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-composite.wgsl +14 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-downsample.wgsl +60 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-soft.wgsl +46 -0
- package/dist/libraries/postfx/src/shaders/post-process/bloom-upsample.wgsl +51 -0
- package/dist/libraries/postfx/src/shaders/post-process/channel-mixer.wgsl +36 -0
- package/dist/libraries/postfx/src/shaders/post-process/chromatic-aberration.wgsl +37 -0
- package/dist/libraries/postfx/src/shaders/post-process/dithering.wgsl +64 -0
- package/dist/libraries/postfx/src/shaders/post-process/dof.wgsl +131 -0
- package/dist/libraries/postfx/src/shaders/post-process/edges.wgsl +45 -0
- package/dist/libraries/postfx/src/shaders/post-process/fullscreen-vs.wgsl +15 -0
- package/dist/libraries/postfx/src/shaders/post-process/fxaa.wgsl +102 -0
- package/dist/libraries/postfx/src/shaders/post-process/gaussian-blur.wgsl +37 -0
- package/dist/libraries/postfx/src/shaders/post-process/glow-blur.wgsl +33 -0
- package/dist/libraries/postfx/src/shaders/post-process/glow-composite.wgsl +25 -0
- package/dist/libraries/postfx/src/shaders/post-process/grain.wgsl +37 -0
- package/dist/libraries/postfx/src/shaders/post-process/halftone.wgsl +80 -0
- package/dist/libraries/postfx/src/shaders/post-process/highlight-blur.wgsl +33 -0
- package/dist/libraries/postfx/src/shaders/post-process/highlight-composite.wgsl +32 -0
- package/dist/libraries/postfx/src/shaders/post-process/lens-distortion.wgsl +43 -0
- package/dist/libraries/postfx/src/shaders/post-process/lens-flare.wgsl +68 -0
- package/dist/libraries/postfx/src/shaders/post-process/lut.wgsl +30 -0
- package/dist/libraries/postfx/src/shaders/post-process/motion-blur.wgsl +55 -0
- package/dist/libraries/postfx/src/shaders/post-process/occluder-chunk.wgsl +28 -0
- package/dist/libraries/postfx/src/shaders/post-process/outline.wgsl +51 -0
- package/dist/libraries/postfx/src/shaders/post-process/pixelation.wgsl +47 -0
- package/dist/libraries/postfx/src/shaders/post-process/sharpen.wgsl +32 -0
- package/dist/libraries/postfx/src/shaders/post-process/sobel.wgsl +26 -0
- package/dist/libraries/postfx/src/shaders/post-process/split-tone.wgsl +36 -0
- package/dist/libraries/postfx/src/shaders/post-process/ssao-blur.wgsl +38 -0
- package/dist/libraries/postfx/src/shaders/post-process/ssao-composite.wgsl +25 -0
- package/dist/libraries/postfx/src/shaders/post-process/ssao.wgsl +147 -0
- package/dist/libraries/postfx/src/shaders/post-process/ssr.wgsl +155 -0
- package/dist/libraries/postfx/src/shaders/post-process/taa.wgsl +98 -0
- package/dist/libraries/postfx/src/shaders/post-process/tonemap.wgsl +40 -0
- package/dist/libraries/postfx/src/shaders/post-process/watercolor.wgsl +82 -0
- package/dist/libraries/postfx/src/shaders/post-process/white-balance.wgsl +41 -0
- package/dist/libraries/recast/src/backend.js +124 -0
- package/dist/libraries/recast/src/crowd-system.js +310 -0
- package/dist/libraries/recast/src/index.js +4 -0
- package/dist/libraries/recast/src/library.js +59 -0
- package/dist/libraries/recast/src/types.js +4 -0
- package/dist/libraries/sand/src/cell.js +32 -0
- package/dist/libraries/sand/src/fields.js +27 -0
- package/dist/libraries/sand/src/fluid-grid.js +267 -0
- package/dist/libraries/sand/src/grid-dims.js +47 -0
- package/dist/libraries/sand/src/grid-sim-buffer.js +184 -0
- package/dist/libraries/sand/src/index.js +20 -0
- package/dist/libraries/sand/src/library.js +67 -0
- package/dist/libraries/sand/src/materials.js +437 -0
- package/dist/libraries/sand/src/palette.js +87 -0
- package/dist/libraries/sand/src/particles.js +163 -0
- package/dist/libraries/sand/src/render/sand-grid-pass.js +377 -0
- package/dist/libraries/sand/src/rng.js +44 -0
- package/dist/libraries/sand/src/rules/builtin-rules.js +125 -0
- package/dist/libraries/sand/src/rules/rule-compiler.js +164 -0
- package/dist/libraries/sand/src/rules/rule-engine.js +210 -0
- package/dist/libraries/sand/src/rules/rule-types.js +27 -0
- package/dist/libraries/sand/src/sand-step-pool.js +458 -0
- package/dist/libraries/sand/src/sand-step-worker.js +101 -0
- package/dist/libraries/sand/src/sand-world.js +3382 -0
- package/dist/libraries/stickman/src/index.js +7 -0
- package/dist/libraries/stickman/src/library.js +44 -0
- package/dist/libraries/stickman/src/proportions.js +40 -0
- package/dist/libraries/stickman/src/shader.js +113 -0
- package/dist/libraries/stickman/src/skeleton.js +163 -0
- package/dist/libraries/stickman/src/stickman-pass.js +210 -0
- package/dist/libraries/stickman/src/thick-line.js +120 -0
- package/dist/libraries/surface-nets/src/chunked-field.js +5 -0
- package/dist/libraries/surface-nets/src/deformation.js +29 -0
- package/dist/libraries/surface-nets/src/index.js +15 -0
- package/dist/libraries/surface-nets/src/library.js +41 -0
- package/dist/libraries/surface-nets/src/lod.js +6 -0
- package/dist/libraries/surface-nets/src/sab.js +4 -0
- package/dist/libraries/surface-nets/src/streaming-config.js +4 -0
- package/dist/libraries/surface-nets/src/streaming-manager.js +9 -0
- package/dist/libraries/surface-nets/src/surface-nets.js +361 -0
- package/dist/libraries/surface-nets/src/types.js +1 -0
- package/dist/libraries/water/src/buoyancy.js +80 -0
- package/dist/libraries/water/src/index.js +12 -0
- package/dist/libraries/water/src/library.js +65 -0
- package/dist/libraries/water/src/shore-damping.js +70 -0
- package/dist/libraries/water/src/water-buffer.js +78 -0
- package/dist/libraries/water/src/water-chunks.js +5 -0
- package/dist/libraries/water/src/water-physics.js +315 -0
- package/dist/libraries/water/src/water-renderer.js +736 -0
- package/dist/libraries/water/src/water-sab.js +138 -0
- package/dist/libraries/water/src/wave-sources.js +45 -0
- package/dist/libraries/weather/src/index.js +5 -0
- package/dist/libraries/weather/src/library.js +48 -0
- package/dist/libraries/weather/src/types.js +29 -0
- package/dist/libraries/weather/src/weather-blend.js +108 -0
- package/dist/libraries/weather/src/weather-system.js +275 -0
- package/dist/libraries/weatherfx/src/cloud-provider.js +5 -0
- package/dist/libraries/weatherfx/src/cloud-system.js +294 -0
- package/dist/libraries/weatherfx/src/index.js +4 -0
- package/dist/libraries/weatherfx/src/library.js +41 -0
- package/dist/libraries/weatherfx/src/particle-system.js +350 -0
- package/dist/libraries/weatherfx/src/shaders/cloud.wgsl +111 -0
- package/dist/libraries/weatherfx/src/shaders/particle-compute.wgsl +187 -0
- package/dist/libraries/weatherfx/src/shaders/particle-render.wgsl +95 -0
- package/dist/mcp/src/client.js +669 -0
- package/dist/mcp/src/engine-context.js +99 -0
- package/dist/mcp/src/http-transport.js +423 -0
- package/dist/mcp/src/index.js +5 -0
- package/dist/mcp/src/prompts/add-entity.js +39 -0
- package/dist/mcp/src/prompts/create-scene.js +41 -0
- package/dist/mcp/src/prompts/debug-frame.js +36 -0
- package/dist/mcp/src/prompts/index.js +10 -0
- package/dist/mcp/src/resources/asset-list.js +28 -0
- package/dist/mcp/src/resources/checkpoint-list.js +29 -0
- package/dist/mcp/src/resources/entity-state.js +45 -0
- package/dist/mcp/src/resources/gpu-info.js +90 -0
- package/dist/mcp/src/resources/index.js +51 -0
- package/dist/mcp/src/resources/performance.js +33 -0
- package/dist/mcp/src/resources/scene-tree.js +37 -0
- package/dist/mcp/src/server.js +307 -0
- package/dist/mcp/src/tools/animation.js +102 -0
- package/dist/mcp/src/tools/asset.js +146 -0
- package/dist/mcp/src/tools/audio.js +80 -0
- package/dist/mcp/src/tools/build.js +128 -0
- package/dist/mcp/src/tools/camera.js +157 -0
- package/dist/mcp/src/tools/checkpoint.js +90 -0
- package/dist/mcp/src/tools/component.js +176 -0
- package/dist/mcp/src/tools/debug.js +273 -0
- package/dist/mcp/src/tools/entity.js +309 -0
- package/dist/mcp/src/tools/inspect.js +192 -0
- package/dist/mcp/src/tools/lighting.js +239 -0
- package/dist/mcp/src/tools/material.js +225 -0
- package/dist/mcp/src/tools/mesh.js +210 -0
- package/dist/mcp/src/tools/physics.js +251 -0
- package/dist/mcp/src/tools/scene.js +139 -0
- package/dist/mcp/src/tools/script.js +114 -0
- package/dist/mcp/src/types.js +9 -0
- package/dist/mcp/src/undo-redo.js +64 -0
- package/dist/modules/camera-controls/src/index.js +116 -0
- package/dist/modules/controller-ui/src/index.js +149 -0
- package/dist/modules/devtools/src/api.js +317 -0
- package/dist/modules/devtools/src/asset-utils.js +102 -0
- package/dist/modules/devtools/src/bind-debug-store.js +34 -0
- package/dist/modules/devtools/src/blitz/host.js +391 -0
- package/dist/modules/devtools/src/blitz/module.js +65 -0
- package/dist/modules/devtools/src/blitz/panels/console.js +217 -0
- package/dist/modules/devtools/src/blitz/panels/elements.js +79 -0
- package/dist/modules/devtools/src/blitz/panels/gpu.js +61 -0
- package/dist/modules/devtools/src/blitz/panels/performance.js +113 -0
- package/dist/modules/devtools/src/blitz/panels/snapshot.js +141 -0
- package/dist/modules/devtools/src/blitz/panels/types.js +55 -0
- package/dist/modules/devtools/src/blitz/theme.js +167 -0
- package/dist/modules/devtools/src/data-bridge.js +247 -0
- package/dist/modules/devtools/src/debug-overlay.js +181 -0
- package/dist/modules/devtools/src/debug-raycast.js +296 -0
- package/dist/modules/devtools/src/debug-store.js +28 -0
- package/dist/modules/devtools/src/debug-view-descriptors.js +24 -0
- package/dist/modules/devtools/src/doctor-panel.js +163 -0
- package/dist/modules/devtools/src/gizmo-module.js +95 -0
- package/dist/modules/devtools/src/graph-model.js +387 -0
- package/dist/modules/devtools/src/grid-renderer.js +145 -0
- package/dist/modules/devtools/src/height-ruler-renderer.js +189 -0
- package/dist/modules/devtools/src/index.js +46 -0
- package/dist/modules/devtools/src/init.js +204 -0
- package/dist/modules/devtools/src/label-overlay.js +129 -0
- package/dist/modules/devtools/src/material-stats-panel.js +171 -0
- package/dist/modules/devtools/src/profiling-bridge.js +288 -0
- package/dist/modules/devtools/src/profiling-hooks.js +63 -0
- package/dist/modules/devtools/src/renderer-adapter.js +61 -0
- package/dist/modules/devtools/src/scene-inspector.js +571 -0
- package/dist/modules/devtools/src/scene-store.js +212 -0
- package/dist/modules/devtools/src/scene-sync.js +92 -0
- package/dist/modules/devtools/src/shaders/transform-gizmo.wgsl +38 -0
- package/dist/modules/devtools/src/sim-stats-panel.js +250 -0
- package/dist/modules/devtools/src/sim-stats-provider.js +73 -0
- package/dist/modules/devtools/src/skeleton-renderer.js +326 -0
- package/dist/modules/devtools/src/transform-gizmo.js +677 -0
- package/dist/modules/devtools/src/types.js +5 -0
- package/dist/modules/devtools/src/worker-expose.js +59 -0
- package/dist/modules/devtools/src/worker-sync.js +115 -0
- package/dist/modules/editor/src/commands/component.js +151 -0
- package/dist/modules/editor/src/commands/entity.js +253 -0
- package/dist/modules/editor/src/commands/hierarchy.js +79 -0
- package/dist/modules/editor/src/commands/index.js +57 -0
- package/dist/modules/editor/src/commands/prefab.js +149 -0
- package/dist/modules/editor/src/commands/registry.js +246 -0
- package/dist/modules/editor/src/commands/scene-io.js +206 -0
- package/dist/modules/editor/src/commands/selection.js +71 -0
- package/dist/modules/editor/src/commands/transform.js +88 -0
- package/dist/modules/editor/src/ddscene.js +189 -0
- package/dist/modules/editor/src/document.js +96 -0
- package/dist/modules/editor/src/editor-context.js +115 -0
- package/dist/modules/editor/src/index.js +11 -0
- package/dist/modules/editor/src/mcp.js +91 -0
- package/dist/modules/editor/src/module.js +115 -0
- package/dist/modules/editor/src/selection.js +60 -0
- package/dist/modules/editor/src/shell.js +397 -0
- package/dist/modules/editor/src/viewport.js +186 -0
- package/dist/modules/html-ui/src/composite.js +116 -0
- package/dist/modules/html-ui/src/create-html-ui.js +137 -0
- package/dist/modules/html-ui/src/doc-backend.js +518 -0
- package/dist/modules/html-ui/src/host.js +819 -0
- package/dist/modules/html-ui/src/index.js +5 -0
- package/dist/modules/html-ui/src/jsx-dev-runtime.js +9 -0
- package/dist/modules/html-ui/src/jsx-runtime.js +121 -0
- package/dist/modules/html-ui/src/protocol.js +6 -0
- package/dist/modules/html-ui/src/ui-worker.js +10 -0
- package/dist/modules/mcp/src/index.js +62 -0
- package/dist/modules/movement-2d/src/grid-character.js +345 -0
- package/dist/modules/movement-2d/src/index.js +27 -0
- package/dist/modules/movement-3d/src/character-motor.js +166 -0
- package/dist/modules/movement-3d/src/index.js +27 -0
- package/dist/modules/native-osr/src/index.js +12 -0
- package/dist/modules/native-osr/src/input-router.js +335 -0
- package/dist/modules/native-osr/src/native-osr-manager.js +210 -0
- package/dist/modules/native-osr/src/native-texture-source.js +66 -0
- package/dist/modules/native-osr/src/types.js +8 -0
- package/dist/modules/native-osr/src/world-space-ui-pass.js +313 -0
- package/dist/modules/sailing/src/index.js +39 -0
- package/dist/modules/terrain/src/index.js +44 -0
- package/dist/modules/vitals/src/index.js +25 -0
- package/dist/modules/vitals/src/vitals.js +195 -0
- package/dist/modules/xr/src/camera-rig.js +119 -0
- package/dist/modules/xr/src/debug.js +45 -0
- package/dist/modules/xr/src/frame-loop.js +139 -0
- package/dist/modules/xr/src/index.js +10 -0
- package/dist/modules/xr/src/input.js +164 -0
- package/dist/modules/xr/src/layer.js +100 -0
- package/dist/modules/xr/src/session.js +133 -0
- package/dist/modules/xr/src/sim-module.js +21 -0
- package/dist/modules/xr/src/types.js +4 -0
- package/dist/modules/xr/src/webxr.d.ts +182 -0
- package/dist/modules/xr/src/xr-module.js +134 -0
- package/dist/shader-graph/src/chunks.js +340 -0
- package/dist/shader-graph/src/compiler.js +639 -0
- package/dist/shader-graph/src/compute-compiler.js +384 -0
- package/dist/shader-graph/src/compute-graph.js +55 -0
- package/dist/shader-graph/src/compute-profiles.js +39 -0
- package/dist/shader-graph/src/graph.js +38 -0
- package/dist/shader-graph/src/index.js +15 -0
- package/dist/shader-graph/src/profiles.js +305 -0
- package/dist/shader-graph/src/validator.js +42 -0
- package/dist/shader-graph/src/wgsl-binding-validator.js +110 -0
- package/dist/shader-graph/src/wgsl-struct-validator.js +222 -0
- package/dist/shader-graph/src/wgsl-struct.js +251 -0
- package/dist/test/src/index.js +1 -0
- package/dist/test/src/vision-test.js +228 -0
- package/libraries/asset-browser/src/software-thumbnails.ts +2 -2
- package/libraries/audio-kira/src/backend.ts +2 -1
- package/libraries/blitz-ui/native/src/shell.rs +35 -1
- package/libraries/blitz-ui/native-osr/Cargo.toml +8 -0
- package/libraries/blitz-ui/native-osr/src/lib.rs +213 -22
- package/libraries/blitz-ui/native-osr/src/mutate.rs +109 -14
- package/libraries/blitz-ui/src/native-osr-ffi.ts +71 -8
- package/libraries/blitz-ui/src/router.ts +3 -1
- package/libraries/blitz-ui/src/ui-blit-pass.ts +1 -1
- package/libraries/character/src/character-animator.ts +1 -1
- package/libraries/character/src/customization.ts +513 -0
- package/libraries/character/src/index.ts +6 -0
- package/libraries/character/src/inspectable.ts +111 -0
- package/libraries/character/src/loader.ts +38 -13
- package/libraries/character/src/locomotion.ts +13 -1
- package/libraries/character/src/preview.ts +94 -24
- package/libraries/devtools/README.md +16 -18
- package/libraries/devtools/src/backend.ts +505 -0
- package/libraries/devtools/src/cdp-bridge.ts +8 -8
- package/libraries/devtools/src/collectors.ts +41 -37
- package/libraries/devtools/src/index.ts +32 -14
- package/libraries/devtools/src/native-providers.ts +20 -12
- package/libraries/devtools/src/snapshot.ts +77 -0
- package/libraries/devtools/src/web/host.ts +11 -12
- package/libraries/devtools/src/web/mirror.ts +14 -405
- package/libraries/devtools/src/web/server.ts +4 -3
- package/libraries/entities/src/model-renderer.ts +96 -23
- package/libraries/gamepad/src/library.ts +2 -1
- package/libraries/inspectable/src/index.ts +11 -0
- package/libraries/inspectable/src/inspectable.ts +277 -0
- package/libraries/marching-cubes/src/streaming-manager.ts +4 -4
- package/libraries/models/src/bind-unskinned-meshes.ts +131 -0
- package/libraries/models/src/index.ts +1 -0
- package/libraries/models/src/types.ts +22 -0
- package/libraries/persistence/src/autosave-manager.ts +1 -1
- package/libraries/persistence/src/binary-record-store.ts +1 -1
- package/libraries/persistence/src/file-save-store.ts +4 -4
- package/libraries/persistence/src/library.ts +1 -1
- package/libraries/persistence/src/opfs-save-store.ts +5 -5
- package/libraries/persistence/src/save-worker.ts +13 -14
- package/libraries/physics-rapier/src/ffi-lib.ts +2 -1
- package/libraries/postfx/src/post-process-stack.ts +1 -1
- package/libraries/sand/src/sand-step-pool.ts +5 -0
- package/libraries/water/src/water-renderer.ts +1 -1
- package/libraries/weatherfx/src/cloud-system.ts +3 -3
- package/mcp/README.md +20 -0
- package/mcp/src/client.ts +75 -22
- package/mcp/src/undo-redo.ts +2 -2
- package/modules/devtools/src/blitz/host.ts +430 -0
- package/modules/devtools/src/blitz/module.ts +101 -0
- package/modules/devtools/src/blitz/panels/console.ts +223 -0
- package/modules/devtools/src/blitz/panels/elements.ts +92 -0
- package/modules/devtools/src/blitz/panels/gpu.ts +70 -0
- package/modules/devtools/src/blitz/panels/performance.ts +120 -0
- package/modules/devtools/src/blitz/panels/snapshot.ts +152 -0
- package/modules/devtools/src/blitz/panels/types.ts +120 -0
- package/modules/devtools/src/blitz/theme.ts +168 -0
- package/modules/devtools/src/data-bridge.ts +1 -1
- package/modules/devtools/src/index.ts +6 -0
- package/modules/devtools/src/profiling-bridge.ts +17 -13
- package/modules/devtools/src/profiling-hooks.ts +22 -13
- package/modules/devtools/src/scene-inspector.ts +1 -1
- package/modules/devtools/src/worker-sync.ts +9 -1
- package/modules/editor/src/commands/registry.ts +2 -2
- package/modules/editor/src/module.ts +1 -1
- package/modules/html-ui/src/composite.ts +1 -1
- package/modules/html-ui/src/create-html-ui.ts +21 -9
- package/modules/html-ui/src/doc-backend.ts +189 -10
- package/modules/html-ui/src/host.ts +354 -40
- package/modules/html-ui/src/index.ts +1 -1
- package/modules/html-ui/src/jsx-runtime.ts +1 -1
- package/modules/html-ui/src/protocol.ts +53 -6
- package/modules/mcp/README.md +6 -0
- package/modules/mcp/src/index.ts +70 -3
- package/modules/movement-3d/src/character-motor.ts +83 -10
- package/package.json +838 -165
- package/shader-graph/README.md +25 -0
- package/test/README.md +16 -0
- package/libraries/blitz-ui/native-osr-spike.ts +0 -70
- package/libraries/devtools/native/Cargo.toml +0 -12
- package/libraries/devtools/native/src/lib.rs +0 -1646
- package/libraries/devtools/native/src/panels/console.rs +0 -338
- package/libraries/devtools/native/src/panels/dom_tree.rs +0 -47
- package/libraries/devtools/native/src/panels/generic.rs +0 -317
- package/libraries/devtools/native/src/panels/gpu.rs +0 -107
- package/libraries/devtools/native/src/panels/input.rs +0 -88
- package/libraries/devtools/native/src/panels/mod.rs +0 -154
- package/libraries/devtools/native/src/panels/perf_metrics.rs +0 -91
- package/libraries/devtools/native/src/panels/perf_recorder.rs +0 -158
- package/libraries/devtools/native/src/panels/scene.rs +0 -72
- package/libraries/devtools/native/src/state.rs +0 -394
- package/libraries/devtools/src/egui-ffi.ts +0 -804
- package/libraries/devtools/src/egui-renderer.ts +0 -407
- package/libraries/devtools/src/host.ts +0 -363
- package/libraries/devtools/src/mirror.ts +0 -794
- package/libraries/models/test-fixtures/fbx/LICENSE-notice.txt +0 -24
- package/libraries/models/test-fixtures/fbx/README.md +0 -46
- 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/physics-native/src/ffi-spike-worker.ts +0 -71
- package/libraries/physics-rapier/bench/ffi-bench.ts +0 -79
- package/libraries/physics-rapier/bench/wasm-baseline.ts +0 -90
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// BaseWorkerHost — shared boilerplate for main-thread worker host classes.
|
|
3
|
+
//
|
|
4
|
+
// Each game's XxxWorkerHost re-implemented the same ~80 lines: SAB allocation,
|
|
5
|
+
// wrap(), onerror, onEvents("ready"), stop(), ready tracking, proxy management.
|
|
6
|
+
// This base class centralizes that boilerplate. Subclasses provide:
|
|
7
|
+
// - createWorker(): MUST return `new Worker(new URL("./xxx-worker.ts", import.meta.url), { type: "module" })`
|
|
8
|
+
// - onInit(): call the worker's init RPC with the SAB + game-specific args
|
|
9
|
+
// - onEvent(): override for game-specific events (defaults to ready tracking)
|
|
10
|
+
// - getSyncConfig(): optional — buffer sync regions for SAB polyfill (mobile)
|
|
11
|
+
//
|
|
12
|
+
// CRITICAL: Vite's static analysis requires `new Worker(new URL(..., import.meta.url))`
|
|
13
|
+
// to appear literally in the source at the call site. It CANNOT be moved into
|
|
14
|
+
// this base class. Subclasses MUST implement createWorker() with the inline
|
|
15
|
+
// pattern. Assigning the URL to a variable first breaks production builds
|
|
16
|
+
// (Vite emits the worker as a raw unbundled asset with unresolved bare imports).
|
|
17
|
+
//
|
|
18
|
+
// SAB polyfill: when SharedArrayBuffer is unavailable, the
|
|
19
|
+
// base class creates a BufferSyncHost that syncs input regions to the worker
|
|
20
|
+
// via requestAnimationFrame + postMessage (transfer). The worker side syncs
|
|
21
|
+
// sim data back after each tick batch. See buffer-sync.ts + sab-polyfill.ts.
|
|
22
|
+
// Subclasses override getSyncConfig() to declare which regions each side writes.
|
|
23
|
+
// ============================================================================
|
|
24
|
+
import { usingRealSAB } from "../sab/sab-polyfill.js";
|
|
25
|
+
import { createLogger } from "../util/logger.js";
|
|
26
|
+
import { wrap } from "./rpc.js";
|
|
27
|
+
const log = createLogger();
|
|
28
|
+
export class BaseWorkerHost {
|
|
29
|
+
sab;
|
|
30
|
+
proxy = null;
|
|
31
|
+
worker = null;
|
|
32
|
+
ready = false;
|
|
33
|
+
unsubEvents = null;
|
|
34
|
+
syncHost = null;
|
|
35
|
+
lifecycleLock = null;
|
|
36
|
+
constructor(sab) {
|
|
37
|
+
this.sab = sab;
|
|
38
|
+
}
|
|
39
|
+
/** The SharedArrayBuffer shared with the worker. */
|
|
40
|
+
getSimBuffer() {
|
|
41
|
+
return this.sab;
|
|
42
|
+
}
|
|
43
|
+
/** True after the worker has reported the "ready" event. */
|
|
44
|
+
isReady() {
|
|
45
|
+
return this.ready;
|
|
46
|
+
}
|
|
47
|
+
/** The typed RPC proxy. Returns null before start() or after stop(). */
|
|
48
|
+
getProxy() {
|
|
49
|
+
return this.proxy;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Serialize start()/stop() — a hot-reload save→stop→start cycle racing a
|
|
53
|
+
* second caller (overlapping swap events, session teardown) must not
|
|
54
|
+
* interleave worker/proxy swaps, or workers get orphaned mid-flight.
|
|
55
|
+
* FIFO mutex; uncontended calls invoke fn synchronously so start() wires
|
|
56
|
+
* the worker in the caller's own tick (post-await subscribers rely on it).
|
|
57
|
+
*/
|
|
58
|
+
serialized(fn) {
|
|
59
|
+
let release;
|
|
60
|
+
const mine = new Promise((r) => (release = r));
|
|
61
|
+
const prev = this.lifecycleLock;
|
|
62
|
+
this.lifecycleLock = mine;
|
|
63
|
+
const settle = () => {
|
|
64
|
+
if (this.lifecycleLock === mine)
|
|
65
|
+
this.lifecycleLock = null;
|
|
66
|
+
release();
|
|
67
|
+
};
|
|
68
|
+
if (!prev) {
|
|
69
|
+
const result = Promise.resolve(fn());
|
|
70
|
+
void result.finally(settle);
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
return prev.then(async () => {
|
|
74
|
+
try {
|
|
75
|
+
return await fn();
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
settle();
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Spawn the worker and call its init RPC.
|
|
84
|
+
*
|
|
85
|
+
* Subclasses MUST implement createWorker() with the inline
|
|
86
|
+
* `new Worker(new URL("./xxx-worker.ts", import.meta.url), { type: "module" })`
|
|
87
|
+
* pattern. See the file-level comment for why.
|
|
88
|
+
*
|
|
89
|
+
* When SAB is unavailable, a BufferSyncHost is created
|
|
90
|
+
* to sync input regions to the worker via rAF + postMessage. Subclasses
|
|
91
|
+
* override getSyncConfig() to declare the region layout.
|
|
92
|
+
*/
|
|
93
|
+
async start() {
|
|
94
|
+
return this.serialized(async () => {
|
|
95
|
+
// Re-entrant start while a worker is live (overlapping hot reloads,
|
|
96
|
+
// teardown racing a respawn) must not orphan the old worker.
|
|
97
|
+
if (this.worker || this.proxy)
|
|
98
|
+
await this.stopInner();
|
|
99
|
+
this.worker = this.createWorker();
|
|
100
|
+
// A live worker must never be the only handle pinning the process —
|
|
101
|
+
// window-close teardown stops it explicitly (sim.stop()), but a worker
|
|
102
|
+
// that slips through (error path, missing stop impl) shouldn't hold
|
|
103
|
+
// the runtime open forever. No-op where unref doesn't exist (Deno).
|
|
104
|
+
this.worker.unref?.();
|
|
105
|
+
// 120s rather than the 30s default: in dev, vite's cold transform of a
|
|
106
|
+
// large worker module can exceed 30s, killing init with a spurious
|
|
107
|
+
// timeout while the worker is still legitimately loading.
|
|
108
|
+
this.proxy = wrap(this.worker, { timeoutMs: 120_000 });
|
|
109
|
+
// Tag the Worker with its RPC proxy so external force-terminates (dev
|
|
110
|
+
// session teardown) reject pending calls instead of leaving them to
|
|
111
|
+
// hang until their timeout — a hanging caller pins the dying session.
|
|
112
|
+
this.worker.__ddWorkerProxy = this.proxy;
|
|
113
|
+
this.worker.onerror = (e) => {
|
|
114
|
+
this.onError(e);
|
|
115
|
+
};
|
|
116
|
+
this.unsubEvents = this.proxy.onEvents((kind, data) => {
|
|
117
|
+
this.onEvent(kind, data);
|
|
118
|
+
});
|
|
119
|
+
// SAB polyfill: start buffer sync host before onInit so input sync begins
|
|
120
|
+
// as soon as the worker is ready. The host uses rAF to sync input regions.
|
|
121
|
+
if (!usingRealSAB && this.getSyncConfig()) {
|
|
122
|
+
const { BufferSyncHost: BSH } = await import("./buffer-sync.js");
|
|
123
|
+
this.syncHost = new BSH(this.worker, this.getSyncConfig());
|
|
124
|
+
this.syncHost.start();
|
|
125
|
+
}
|
|
126
|
+
// Hook for subclasses to run setup before onInit (e.g. attaching profiling SAB).
|
|
127
|
+
await this.beforeInit();
|
|
128
|
+
await this.onInit();
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Shut down the worker: call shutdown() RPC, terminate, clean up.
|
|
133
|
+
* Safe to call multiple times.
|
|
134
|
+
* Alias for stop() — some games call shutdown(), others stop().
|
|
135
|
+
*/
|
|
136
|
+
async shutdown() {
|
|
137
|
+
return this.stop();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Shut down the worker: call shutdown() RPC, terminate, clean up.
|
|
141
|
+
* Safe to call multiple times.
|
|
142
|
+
*/
|
|
143
|
+
async stop() {
|
|
144
|
+
return this.serialized(() => this.stopInner());
|
|
145
|
+
}
|
|
146
|
+
async stopInner() {
|
|
147
|
+
this.syncHost?.stop();
|
|
148
|
+
this.syncHost = null;
|
|
149
|
+
if (this.proxy) {
|
|
150
|
+
try {
|
|
151
|
+
// Bounded graceful shutdown — a wedged worker must not hang stop()
|
|
152
|
+
// (and through it, hot-reload pipelines and session teardown).
|
|
153
|
+
let timer;
|
|
154
|
+
try {
|
|
155
|
+
await Promise.race([
|
|
156
|
+
this.proxy.proxy.shutdown(),
|
|
157
|
+
new Promise((_, rej) => {
|
|
158
|
+
timer = setTimeout(() => rej(new Error("shutdown RPC timed out")), 2_000);
|
|
159
|
+
}),
|
|
160
|
+
]);
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
clearTimeout(timer);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// Worker may already be dead
|
|
168
|
+
}
|
|
169
|
+
this.proxy.terminate();
|
|
170
|
+
}
|
|
171
|
+
this.unsubEvents?.();
|
|
172
|
+
this.unsubEvents = null;
|
|
173
|
+
this.proxy = null;
|
|
174
|
+
this.worker = null;
|
|
175
|
+
this.ready = false;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Override to run setup before onInit(). Called after the worker is spawned
|
|
179
|
+
* and the proxy is set up, but before onInit(). InstrumentedWorkerHost uses
|
|
180
|
+
* this to attach the ProfilingSAB + patch prototypes before user code runs.
|
|
181
|
+
* Default: no-op.
|
|
182
|
+
*/
|
|
183
|
+
beforeInit() {
|
|
184
|
+
return Promise.resolve();
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Override to declare buffer sync regions for the SAB polyfill (mobile).
|
|
188
|
+
* Return null/undefined to skip sync (e.g. if the host doesn't use SAB).
|
|
189
|
+
* The config should declare which regions the MAIN thread writes (input)
|
|
190
|
+
* vs which the WORKER writes (sim data, stats, board). See buffer-sync.ts.
|
|
191
|
+
* Default: null (no sync — used when SAB is available or host doesn't need sync).
|
|
192
|
+
*/
|
|
193
|
+
getSyncConfig() {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Override for game-specific event handling.
|
|
198
|
+
* Default: sets ready=true on "ready" event.
|
|
199
|
+
*/
|
|
200
|
+
onEvent(kind, _data) {
|
|
201
|
+
if (kind === "ready") {
|
|
202
|
+
this.ready = true;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Override for custom error handling.
|
|
207
|
+
* Default: logs to console with the class name.
|
|
208
|
+
*/
|
|
209
|
+
onError(e) {
|
|
210
|
+
log.error(this.constructor.name, `Worker error: ${e.message}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// buffer-sync — copy-based buffer synchronization for the SAB polyfill
|
|
3
|
+
// ============================================================================
|
|
4
|
+
//
|
|
5
|
+
// When SharedArrayBuffer is polyfilled, each thread has its
|
|
6
|
+
// own ArrayBuffer instance. This module synchronizes them via postMessage at
|
|
7
|
+
// tick/frame boundaries:
|
|
8
|
+
//
|
|
9
|
+
// Main → Worker (input): driven by requestAnimationFrame, copies only the
|
|
10
|
+
// input region(s) the main thread writes, transfers the ArrayBuffer.
|
|
11
|
+
// Worker → Main (sim): event-driven (after each tick batch), copies only
|
|
12
|
+
// the regions the worker writes, transfers the ArrayBuffer.
|
|
13
|
+
//
|
|
14
|
+
// Optimizations:
|
|
15
|
+
// - Region-aware: only the declared write regions are copied, not the full
|
|
16
|
+
// buffer. For sandjongg's embedded input (64 bytes), main→worker copies
|
|
17
|
+
// 64 bytes, not the full 1.3MB.
|
|
18
|
+
// - Sequence-number gating: if a buffer has a sequence field, the sync is
|
|
19
|
+
// skipped when the sequence hasn't changed since the last sync. Eliminates
|
|
20
|
+
// all copy overhead when the sim is paused.
|
|
21
|
+
// - Transferable ArrayBuffers: postMessage with a transfer list avoids the
|
|
22
|
+
// structured-clone copy (transfer is zero-copy). Net: 1 copy (slice)
|
|
23
|
+
// instead of 2 (slice + structured clone).
|
|
24
|
+
//
|
|
25
|
+
// Single-writer constraint:
|
|
26
|
+
// Each buffer region must have exactly one writer. If both sides write to
|
|
27
|
+
// the same region, the sync will overwrite one side's writes with stale data
|
|
28
|
+
// from the other. The region declarations (writeRegions/readRegions) enforce
|
|
29
|
+
// this — the sync manager only copies declared write regions.
|
|
30
|
+
//
|
|
31
|
+
import { createLogger } from "../util/logger.js";
|
|
32
|
+
const log = createLogger();
|
|
33
|
+
/** Check if a message is a buffer-sync message. */
|
|
34
|
+
export function isBufferSyncMessage(msg) {
|
|
35
|
+
return typeof msg === "object" && msg !== null && "__bufferSync" in msg;
|
|
36
|
+
}
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Main-thread side
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Profiling support (lightweight, no deps)
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
/** Sync profiling is opt-in: `__DOWNDRAFT_PROFILE_SYNC__` global or
|
|
44
|
+
* `DOWNDRAFT_PROFILE_SYNC=1` env. When off, no samples are recorded and no
|
|
45
|
+
* console output is produced (previously it logged every 5s in production). */
|
|
46
|
+
function syncProfilingEnabled() {
|
|
47
|
+
const g = globalThis;
|
|
48
|
+
if (g.__DOWNDRAFT_PROFILE_SYNC__ === true)
|
|
49
|
+
return true;
|
|
50
|
+
try {
|
|
51
|
+
return g.process?.env
|
|
52
|
+
?.DOWNDRAFT_PROFILE_SYNC === "1";
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Accumulates timing samples and logs a summary every N calls. */
|
|
59
|
+
class SyncProfiler {
|
|
60
|
+
samples = [];
|
|
61
|
+
logTimer = 0;
|
|
62
|
+
logInterval;
|
|
63
|
+
enabled = syncProfilingEnabled();
|
|
64
|
+
constructor(logIntervalMs = 5000) {
|
|
65
|
+
this.logInterval = logIntervalMs;
|
|
66
|
+
}
|
|
67
|
+
/** Record a timed operation. Call begin() before, end() after. */
|
|
68
|
+
begin() { return this.enabled ? performance.now() : 0; }
|
|
69
|
+
end(label, start, bytes) {
|
|
70
|
+
if (!this.enabled)
|
|
71
|
+
return;
|
|
72
|
+
const ms = performance.now() - start;
|
|
73
|
+
this.samples.push({ label, ms, bytes });
|
|
74
|
+
const now = performance.now();
|
|
75
|
+
if (now - this.logTimer >= this.logInterval) {
|
|
76
|
+
this.logTimer = now;
|
|
77
|
+
this.flush();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
flush() {
|
|
81
|
+
if (this.samples.length === 0)
|
|
82
|
+
return;
|
|
83
|
+
const byLabel = {};
|
|
84
|
+
this.samples.forEach((s) => {
|
|
85
|
+
const e = byLabel[s.label] ?? (byLabel[s.label] = { count: 0, totalMs: 0, totalBytes: 0, maxMs: 0 });
|
|
86
|
+
e.count++;
|
|
87
|
+
e.totalMs += s.ms;
|
|
88
|
+
e.totalBytes += s.bytes;
|
|
89
|
+
if (s.ms > e.maxMs)
|
|
90
|
+
e.maxMs = s.ms;
|
|
91
|
+
});
|
|
92
|
+
const lines = [];
|
|
93
|
+
for (const [label, e] of Object.entries(byLabel)) {
|
|
94
|
+
const avgMs = (e.totalMs / e.count).toFixed(2);
|
|
95
|
+
const maxMs = e.maxMs.toFixed(2);
|
|
96
|
+
const totalKB = (e.totalBytes / 1024).toFixed(0);
|
|
97
|
+
const avgKB = (e.totalBytes / e.count / 1024).toFixed(1);
|
|
98
|
+
lines.push(` ${label}: ${e.count}x avg=${avgMs}ms max=${maxMs}ms avgSize=${avgKB}KB total=${totalKB}KB`);
|
|
99
|
+
}
|
|
100
|
+
log.warn("buffer-sync", `Profiling: ${this.samples.length} samples over last ${this.logInterval}ms:\n${lines.join("\n")}`);
|
|
101
|
+
this.samples = [];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Main-thread buffer sync manager.
|
|
106
|
+
*
|
|
107
|
+
* Sends input regions to the worker on requestAnimationFrame, and receives
|
|
108
|
+
* sim data regions from the worker via onMessage. Uses rAF (not setInterval)
|
|
109
|
+
* to adapt to the display refresh rate and pause when the tab is hidden.
|
|
110
|
+
*/
|
|
111
|
+
export class BufferSyncHost {
|
|
112
|
+
worker;
|
|
113
|
+
config;
|
|
114
|
+
rafId = 0;
|
|
115
|
+
/** Per-region last-synced sequence: buffer name → region name → seq.
|
|
116
|
+
* Tracked per region (not per buffer) so throttled regions aren't starved
|
|
117
|
+
* when another region's sync consumes the buffer-level seq. */
|
|
118
|
+
lastRegionSeqs = {};
|
|
119
|
+
frameCount = 0;
|
|
120
|
+
profiler = new SyncProfiler(5000);
|
|
121
|
+
messageHandler = null;
|
|
122
|
+
constructor(worker, config) {
|
|
123
|
+
this.worker = worker;
|
|
124
|
+
this.config = config;
|
|
125
|
+
}
|
|
126
|
+
start() {
|
|
127
|
+
if (!this.messageHandler) {
|
|
128
|
+
this.messageHandler = (e) => this.onMessage(e.data);
|
|
129
|
+
this.worker.addEventListener("message", this.messageHandler);
|
|
130
|
+
}
|
|
131
|
+
cancelAnimationFrame(this.rafId); // guard against double-start
|
|
132
|
+
this.syncInput(); // start rAF loop
|
|
133
|
+
}
|
|
134
|
+
stop() {
|
|
135
|
+
cancelAnimationFrame(this.rafId);
|
|
136
|
+
if (this.messageHandler) {
|
|
137
|
+
this.worker.removeEventListener("message", this.messageHandler);
|
|
138
|
+
this.messageHandler = null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Sync input regions to the worker. Called on each rAF frame.
|
|
143
|
+
* Copies only the writeRegions of each buffer, transfers the ArrayBuffers.
|
|
144
|
+
* Regions with syncInterval > 1 are only synced every N frames (throttled).
|
|
145
|
+
*/
|
|
146
|
+
syncInput = () => {
|
|
147
|
+
const transfers = [];
|
|
148
|
+
const regions = {};
|
|
149
|
+
this.frameCount++;
|
|
150
|
+
let totalBytes = 0;
|
|
151
|
+
const pStart = this.profiler.begin();
|
|
152
|
+
for (const [name, buf] of Object.entries(this.config.buffers)) {
|
|
153
|
+
const regionDef = this.config.regions[name];
|
|
154
|
+
if (!regionDef || regionDef.writeRegions.length === 0)
|
|
155
|
+
continue;
|
|
156
|
+
// Sequence gating is per-region (see below) — read the current seq once.
|
|
157
|
+
const seqField = this.config.seqFields?.[name];
|
|
158
|
+
const seq = seqField ? new Int32Array(buf, seqField.offset, 1)[0] : 0;
|
|
159
|
+
const copies = [];
|
|
160
|
+
for (let _i = 0, _it = regionDef.writeRegions, _n = _it.length; _i < _n; _i++) {
|
|
161
|
+
const r = _it[_i];
|
|
162
|
+
// Throttle: skip regions with syncInterval > 1 on most frames.
|
|
163
|
+
// Only sync them every syncInterval frames.
|
|
164
|
+
if (r.syncInterval && r.syncInterval > 1) {
|
|
165
|
+
if (this.frameCount % r.syncInterval !== 0)
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
// Per-region sequence gating: skip this region if its last-synced
|
|
169
|
+
// seq matches the buffer's current seq. Per-region tracking (rather
|
|
170
|
+
// than per-buffer) is required because interval-throttled regions
|
|
171
|
+
// would otherwise never sync — a seq change consumed by a non-
|
|
172
|
+
// throttled region would gate the throttled one out forever.
|
|
173
|
+
if (seqField) {
|
|
174
|
+
const lastSeqs = (this.lastRegionSeqs[name] ??= {});
|
|
175
|
+
if (lastSeqs[r.name] === seq)
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
const src = new Uint8Array(buf, r.offset, r.length);
|
|
179
|
+
// skipIfAllZero: don't send zero-filled regions (e.g. input with
|
|
180
|
+
// ACTION=0 after clearAfterSend). This prevents overwriting the
|
|
181
|
+
// worker's pending input with zeros before it processes the input.
|
|
182
|
+
if (r.skipIfAllZero) {
|
|
183
|
+
let allZero = true;
|
|
184
|
+
for (let i = 0; i < src.length; i++) {
|
|
185
|
+
if (src[i] !== 0) {
|
|
186
|
+
allZero = false;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (allZero)
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const copy = new ArrayBuffer(r.length);
|
|
194
|
+
new Uint8Array(copy).set(src);
|
|
195
|
+
copies.push({ offset: r.offset, data: copy });
|
|
196
|
+
transfers.push(copy);
|
|
197
|
+
totalBytes += r.length;
|
|
198
|
+
// Clear-after-send: zero the local region so we don't re-send stale
|
|
199
|
+
// data on the next frame. Used for input regions (hand-off pattern).
|
|
200
|
+
if (r.clearAfterSend) {
|
|
201
|
+
new Uint8Array(buf, r.offset, r.length).fill(0);
|
|
202
|
+
}
|
|
203
|
+
if (seqField) {
|
|
204
|
+
this.lastRegionSeqs[name][r.name] = seq;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (copies.length > 0)
|
|
208
|
+
regions[name] = copies;
|
|
209
|
+
}
|
|
210
|
+
if (Object.keys(regions).length > 0) {
|
|
211
|
+
const postStart = performance.now();
|
|
212
|
+
this.worker.postMessage({ __bufferSync: true, regions }, transfers);
|
|
213
|
+
this.profiler.end("host→worker postMessage", postStart, totalBytes);
|
|
214
|
+
}
|
|
215
|
+
this.profiler.end("host→worker total", pStart, totalBytes);
|
|
216
|
+
this.rafId = requestAnimationFrame(this.syncInput);
|
|
217
|
+
};
|
|
218
|
+
/** In-flight chunked transfers, keyed by batch id. Parts are applied
|
|
219
|
+
* atomically once the batch completes — see BufferSyncMessage.batch. */
|
|
220
|
+
pendingBatches = new Map();
|
|
221
|
+
lastBatchSeen = -1;
|
|
222
|
+
applyRegions(regions) {
|
|
223
|
+
let totalBytes = 0;
|
|
224
|
+
for (const [name, regionList] of Object.entries(regions)) {
|
|
225
|
+
const local = this.config.buffers[name];
|
|
226
|
+
if (!local)
|
|
227
|
+
continue;
|
|
228
|
+
regionList.forEach(({ offset, data }) => {
|
|
229
|
+
new Uint8Array(local, offset, data.byteLength).set(new Uint8Array(data));
|
|
230
|
+
totalBytes += data.byteLength;
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
return totalBytes;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Receive sim data regions from the worker. Copies only the readRegions
|
|
237
|
+
* (regions the other side writes) into the local buffer.
|
|
238
|
+
*/
|
|
239
|
+
onMessage(msg) {
|
|
240
|
+
if (!isBufferSyncMessage(msg))
|
|
241
|
+
return;
|
|
242
|
+
const pStart = this.profiler.begin();
|
|
243
|
+
let totalBytes = 0;
|
|
244
|
+
if (msg.batch) {
|
|
245
|
+
const { id, index, total } = msg.batch;
|
|
246
|
+
// Part of a batch already completed (or evicted) — a duplicate or a
|
|
247
|
+
// straggler from before a worker restart; applying it would tear.
|
|
248
|
+
if (id <= this.lastBatchSeen && !this.pendingBatches.has(id))
|
|
249
|
+
return;
|
|
250
|
+
let b = this.pendingBatches.get(id);
|
|
251
|
+
if (!b) {
|
|
252
|
+
b = { parts: new Array(total), received: 0 };
|
|
253
|
+
this.pendingBatches.set(id, b);
|
|
254
|
+
// Bound the map: a batch that never completes (worker died
|
|
255
|
+
// mid-transfer) must not leak entries forever.
|
|
256
|
+
if (this.pendingBatches.size > 8) {
|
|
257
|
+
const oldest = this.pendingBatches.keys().next().value;
|
|
258
|
+
this.pendingBatches.delete(oldest);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
b.parts[index] = msg.regions;
|
|
262
|
+
b.received++;
|
|
263
|
+
if (b.received < total)
|
|
264
|
+
return; // wait for the rest — no tearing
|
|
265
|
+
this.pendingBatches.delete(id);
|
|
266
|
+
this.lastBatchSeen = id;
|
|
267
|
+
b.parts.forEach((part) => {
|
|
268
|
+
if (part)
|
|
269
|
+
totalBytes += this.applyRegions(part);
|
|
270
|
+
});
|
|
271
|
+
this.profiler.end("worker→host onMessage", pStart, totalBytes);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
totalBytes = this.applyRegions(msg.regions);
|
|
275
|
+
this.profiler.end("worker→host onMessage", pStart, totalBytes);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
// Worker-thread side
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
/**
|
|
282
|
+
* Worker-thread buffer sync manager.
|
|
283
|
+
*
|
|
284
|
+
* Sends sim data regions to the main thread after each tick batch (event-
|
|
285
|
+
* driven, no polling), and receives input regions from the main thread via
|
|
286
|
+
* onMessage.
|
|
287
|
+
*/
|
|
288
|
+
export class BufferSyncWorker {
|
|
289
|
+
config;
|
|
290
|
+
/** Per-region last-synced sequence: buffer name → region name → seq.
|
|
291
|
+
* Tracked per region (not per buffer) so a filtered syncToMain() call
|
|
292
|
+
* can't consume the buffer seq and starve regions it filtered out —
|
|
293
|
+
* e.g. the fast/slow region pattern in sim-worker-base, where a
|
|
294
|
+
* fast-region sync followed by a full sync must still send slow regions. */
|
|
295
|
+
lastRegionSeqs = {};
|
|
296
|
+
profiler = new SyncProfiler(5000);
|
|
297
|
+
onAfterReceive = null;
|
|
298
|
+
/** Monotonic id for chunked (multi-message) transfers — the host applies
|
|
299
|
+
* a batch atomically once all parts arrive. */
|
|
300
|
+
batchCounter = 0;
|
|
301
|
+
constructor(config) {
|
|
302
|
+
this.config = config;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Start listening for sync messages from the main thread.
|
|
306
|
+
* @param onAfterReceive - Optional callback fired after each received
|
|
307
|
+
* message is processed. Use this to trigger event-driven work (e.g.
|
|
308
|
+
* the grid builder calls build() here instead of polling on a timer,
|
|
309
|
+
* which avoids timer throttling in workers on some hosts).
|
|
310
|
+
*/
|
|
311
|
+
start(onAfterReceive) {
|
|
312
|
+
this.onAfterReceive = onAfterReceive ?? null;
|
|
313
|
+
self.addEventListener("message", (e) => {
|
|
314
|
+
this.onMessage(e.data);
|
|
315
|
+
this.onAfterReceive?.();
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Post written regions to the main thread. Called after each tick batch.
|
|
320
|
+
* Copies only the writeRegions of each buffer, transfers the ArrayBuffers.
|
|
321
|
+
* Skips buffers whose sequence hasn't changed (if seqFields declared).
|
|
322
|
+
*
|
|
323
|
+
* @param regionNames - If provided, only sync write regions whose `name`
|
|
324
|
+
* matches one of the given names. This enables throttled sync: sync small
|
|
325
|
+
* "fast" regions (header, entities) every tick, and large "slow" regions
|
|
326
|
+
* (grid data, render buffers) every N ticks. If omitted, sync all regions.
|
|
327
|
+
*/
|
|
328
|
+
syncToMain(regionNames) {
|
|
329
|
+
const transfers = [];
|
|
330
|
+
const regions = {};
|
|
331
|
+
const filter = regionNames ? new Set(regionNames) : null;
|
|
332
|
+
const pStart = this.profiler.begin();
|
|
333
|
+
let totalBytes = 0;
|
|
334
|
+
for (const [name, buf] of Object.entries(this.config.buffers)) {
|
|
335
|
+
const regionDef = this.config.regions[name];
|
|
336
|
+
if (!regionDef || regionDef.writeRegions.length === 0)
|
|
337
|
+
continue;
|
|
338
|
+
// Sequence gating is per-region (see below) — read the current seq once.
|
|
339
|
+
const seqField = this.config.seqFields?.[name];
|
|
340
|
+
const seq = seqField ? new Int32Array(buf, seqField.offset, 1)[0] : 0;
|
|
341
|
+
const copies = [];
|
|
342
|
+
for (let _i = 0, _it = regionDef.writeRegions, _n = _it.length; _i < _n; _i++) {
|
|
343
|
+
const r = _it[_i];
|
|
344
|
+
// Region name filter: skip regions not in the filter set.
|
|
345
|
+
if (filter && !filter.has(r.name))
|
|
346
|
+
continue;
|
|
347
|
+
// Per-region sequence gating: skip if this region's last-synced seq
|
|
348
|
+
// matches the current buffer seq. Regions excluded by `filter` are
|
|
349
|
+
// checked before this point, so a filtered call never consumes seq
|
|
350
|
+
// for regions it didn't send.
|
|
351
|
+
if (seqField) {
|
|
352
|
+
const lastSeqs = (this.lastRegionSeqs[name] ??= {});
|
|
353
|
+
if (lastSeqs[r.name] === seq)
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
// Dynamic length: read actual length from a field in the buffer.
|
|
357
|
+
let len = r.length;
|
|
358
|
+
if (r.lengthFieldOffset !== undefined && r.lengthMultiplier) {
|
|
359
|
+
const count = new Uint32Array(buf, r.lengthFieldOffset, 1)[0];
|
|
360
|
+
len = Math.min(r.length, count * r.lengthMultiplier);
|
|
361
|
+
}
|
|
362
|
+
// Chunked transfer: if the region is large, split into chunks
|
|
363
|
+
// and send with setTimeout between them so the main thread
|
|
364
|
+
// can process rAF/render between chunks. This prevents 100-900ms
|
|
365
|
+
// main-thread blocks where SAB is unavailable
|
|
366
|
+
// and postMessage structured clone is ~10MB/s).
|
|
367
|
+
const CHUNK_SIZE = 64 * 1024; // 64KB per chunk — small enough to avoid >50ms blocks
|
|
368
|
+
if (len > CHUNK_SIZE) {
|
|
369
|
+
const numChunks = Math.ceil(len / CHUNK_SIZE);
|
|
370
|
+
for (let i = 0; i < numChunks; i++) {
|
|
371
|
+
const chunkStart = i * CHUNK_SIZE;
|
|
372
|
+
const chunkLen = Math.min(CHUNK_SIZE, len - chunkStart);
|
|
373
|
+
const chunkCopy = new ArrayBuffer(chunkLen);
|
|
374
|
+
new Uint8Array(chunkCopy).set(new Uint8Array(buf, r.offset + chunkStart, chunkLen));
|
|
375
|
+
copies.push({ offset: r.offset + chunkStart, data: chunkCopy });
|
|
376
|
+
transfers.push(chunkCopy);
|
|
377
|
+
totalBytes += chunkLen;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
const copy = new ArrayBuffer(len);
|
|
382
|
+
new Uint8Array(copy).set(new Uint8Array(buf, r.offset, len));
|
|
383
|
+
copies.push({ offset: r.offset, data: copy });
|
|
384
|
+
transfers.push(copy);
|
|
385
|
+
totalBytes += len;
|
|
386
|
+
}
|
|
387
|
+
if (seqField) {
|
|
388
|
+
this.lastRegionSeqs[name][r.name] = seq;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (copies.length > 0)
|
|
392
|
+
regions[name] = copies;
|
|
393
|
+
}
|
|
394
|
+
if (Object.keys(regions).length > 0) {
|
|
395
|
+
const label = regionNames ? `worker→host syncToMain(${regionNames.join(",")})` : "worker→host syncToMain(all)";
|
|
396
|
+
// Send all chunks in a single postMessage. The host's onMessage
|
|
397
|
+
// handler copies each chunk to the correct offset in the local buffer.
|
|
398
|
+
// We don't use setTimeout between chunks because the postMessage
|
|
399
|
+
// itself is the blocking operation on the main thread — splitting
|
|
400
|
+
// into multiple postMessage calls with setTimeout would allow the
|
|
401
|
+
// main thread to render between them.
|
|
402
|
+
const allCopies = Object.values(regions).flat();
|
|
403
|
+
if (allCopies.length > 1 && totalBytes > 256 * 1024) {
|
|
404
|
+
// Large transfer: send chunks with setTimeout between them so the
|
|
405
|
+
// main thread can render between chunks. Each message carries batch
|
|
406
|
+
// metadata — the receiver buffers parts and applies them atomically
|
|
407
|
+
// once all arrive, so the buffer never renders partially-updated.
|
|
408
|
+
// Precompute chunk→buffer ownership once (was O(chunks×regions) before).
|
|
409
|
+
const chunkOwner = [];
|
|
410
|
+
for (const [name, regionList] of Object.entries(regions)) {
|
|
411
|
+
for (let i = 0; i < regionList.length; i++)
|
|
412
|
+
chunkOwner.push(name);
|
|
413
|
+
}
|
|
414
|
+
const batchId = ++this.batchCounter;
|
|
415
|
+
const total = allCopies.length;
|
|
416
|
+
let chunkIdx = 0;
|
|
417
|
+
const sendNextChunk = () => {
|
|
418
|
+
if (chunkIdx >= total)
|
|
419
|
+
return;
|
|
420
|
+
const copy = allCopies[chunkIdx];
|
|
421
|
+
const batchRegions = {};
|
|
422
|
+
batchRegions[chunkOwner[chunkIdx]] = [copy];
|
|
423
|
+
chunkIdx++;
|
|
424
|
+
self.postMessage({ __bufferSync: true, regions: batchRegions, batch: { id: batchId, index: chunkIdx - 1, total } }, [copy.data]);
|
|
425
|
+
if (chunkIdx < total) {
|
|
426
|
+
setTimeout(sendNextChunk, 16); // 16ms delay lets main thread render between chunks
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
sendNextChunk();
|
|
430
|
+
this.profiler.end(label, pStart, totalBytes);
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
self.postMessage({ __bufferSync: true, regions }, transfers);
|
|
434
|
+
this.profiler.end(label, pStart, totalBytes);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Receive input regions from the main thread. Copies only the readRegions
|
|
440
|
+
* (regions the other side writes) into the local buffer.
|
|
441
|
+
*/
|
|
442
|
+
onMessage(msg) {
|
|
443
|
+
if (!isBufferSyncMessage(msg))
|
|
444
|
+
return;
|
|
445
|
+
for (const [name, regionList] of Object.entries(msg.regions)) {
|
|
446
|
+
const local = this.config.buffers[name];
|
|
447
|
+
if (!local)
|
|
448
|
+
continue;
|
|
449
|
+
regionList.forEach(({ offset, data }) => {
|
|
450
|
+
new Uint8Array(local, offset, data.byteLength).set(new Uint8Array(data));
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|