@vgai/engine 0.5.0 → 0.5.2
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/package.json +1 -1
- package/schemas/engine-capabilities.json +4 -4
- package/schemas/vgai-game.schema.json +2 -2
- package/src/adapter/authoring.ts +42 -0
- package/src/adapter/index.ts +3 -0
- package/src/adapter/ingest/overlay-apply.ts +50 -6
- package/src/adapter/ingest/scene-capture.ts +51 -2
- package/src/adapter/vgai-scene-game-adapter.ts +24 -0
- package/src/manifest/schema.ts +7 -3
- package/src/runtime/create-runtime.ts +97 -0
- package/src/runtime/game.ts +11 -1
- package/src/scene/asset-ref-check.ts +1 -1
- package/src/scene/scene-loader.ts +2 -2
- package/src/scene/user-data.ts +18 -0
- package/src/world3d-react/behavior.tsx +19 -11
- package/src/world3d-react/r3f-adapter.tsx +8 -0
- package/dist/adapter/adapter-surface.d.ts +0 -30
- package/dist/adapter/adapter-surface.d.ts.map +0 -1
- package/dist/adapter/adapter-surface.js +0 -18
- package/dist/adapter/authoring.d.ts +0 -461
- package/dist/adapter/authoring.d.ts.map +0 -1
- package/dist/adapter/authoring.js +0 -22
- package/dist/adapter/colyseus-networking-adapter.d.ts +0 -43
- package/dist/adapter/colyseus-networking-adapter.d.ts.map +0 -1
- package/dist/adapter/colyseus-networking-adapter.js +0 -38
- package/dist/adapter/first-party-systems.d.ts +0 -38
- package/dist/adapter/first-party-systems.d.ts.map +0 -1
- package/dist/adapter/first-party-systems.js +0 -77
- package/dist/adapter/game-adapter.d.ts +0 -133
- package/dist/adapter/game-adapter.d.ts.map +0 -1
- package/dist/adapter/game-adapter.js +0 -10
- package/dist/adapter/host-context.d.ts +0 -71
- package/dist/adapter/host-context.d.ts.map +0 -1
- package/dist/adapter/host-context.js +0 -16
- package/dist/adapter/index.d.ts +0 -22
- package/dist/adapter/index.d.ts.map +0 -1
- package/dist/adapter/index.js +0 -15
- package/dist/adapter/ingest/game-contract.d.ts +0 -53
- package/dist/adapter/ingest/game-contract.d.ts.map +0 -1
- package/dist/adapter/ingest/game-contract.js +0 -30
- package/dist/adapter/ingest/overlay-applier.d.ts +0 -118
- package/dist/adapter/ingest/overlay-applier.d.ts.map +0 -1
- package/dist/adapter/ingest/overlay-applier.js +0 -132
- package/dist/adapter/ingest/overlay-apply.d.ts +0 -60
- package/dist/adapter/ingest/overlay-apply.d.ts.map +0 -1
- package/dist/adapter/ingest/overlay-apply.js +0 -101
- package/dist/adapter/ingest/overlay-file.d.ts +0 -79
- package/dist/adapter/ingest/overlay-file.d.ts.map +0 -1
- package/dist/adapter/ingest/overlay-file.js +0 -66
- package/dist/adapter/ingest/overlay-report.d.ts +0 -113
- package/dist/adapter/ingest/overlay-report.d.ts.map +0 -1
- package/dist/adapter/ingest/overlay-report.js +0 -103
- package/dist/adapter/ingest/scene-capture.d.ts +0 -97
- package/dist/adapter/ingest/scene-capture.d.ts.map +0 -1
- package/dist/adapter/ingest/scene-capture.js +0 -248
- package/dist/adapter/ingest/upstream-pin.d.ts +0 -47
- package/dist/adapter/ingest/upstream-pin.d.ts.map +0 -1
- package/dist/adapter/ingest/upstream-pin.js +0 -50
- package/dist/adapter/loop-gate-report.d.ts +0 -34
- package/dist/adapter/loop-gate-report.d.ts.map +0 -1
- package/dist/adapter/loop-gate-report.js +0 -37
- package/dist/adapter/rapier-physics-adapter.d.ts +0 -12
- package/dist/adapter/rapier-physics-adapter.d.ts.map +0 -1
- package/dist/adapter/rapier-physics-adapter.js +0 -46
- package/dist/adapter/system-adapter.d.ts +0 -206
- package/dist/adapter/system-adapter.d.ts.map +0 -1
- package/dist/adapter/system-adapter.js +0 -13
- package/dist/adapter/transform.d.ts +0 -18
- package/dist/adapter/transform.d.ts.map +0 -1
- package/dist/adapter/transform.js +0 -1
- package/dist/adapter/vgai-scene-game-adapter.d.ts +0 -108
- package/dist/adapter/vgai-scene-game-adapter.d.ts.map +0 -1
- package/dist/adapter/vgai-scene-game-adapter.js +0 -762
- package/dist/ai/navigation.d.ts +0 -64
- package/dist/ai/navigation.d.ts.map +0 -1
- package/dist/ai/navigation.js +0 -133
- package/dist/animation/anim-graph-types.d.ts +0 -25
- package/dist/animation/anim-graph-types.d.ts.map +0 -1
- package/dist/animation/anim-graph-types.js +0 -1
- package/dist/animation/animation-clock.d.ts +0 -213
- package/dist/animation/animation-clock.d.ts.map +0 -1
- package/dist/animation/animation-clock.js +0 -301
- package/dist/animation/blend-node.d.ts +0 -22
- package/dist/animation/blend-node.d.ts.map +0 -1
- package/dist/animation/blend-node.js +0 -97
- package/dist/animation/camera-ownership.d.ts +0 -250
- package/dist/animation/camera-ownership.d.ts.map +0 -1
- package/dist/animation/camera-ownership.js +0 -169
- package/dist/animation/cinematic-cues.d.ts +0 -200
- package/dist/animation/cinematic-cues.d.ts.map +0 -1
- package/dist/animation/cinematic-cues.js +0 -213
- package/dist/animation/clip-map.d.ts +0 -12
- package/dist/animation/clip-map.d.ts.map +0 -1
- package/dist/animation/clip-map.js +0 -37
- package/dist/animation/gsap-registration.d.ts +0 -119
- package/dist/animation/gsap-registration.d.ts.map +0 -1
- package/dist/animation/gsap-registration.js +0 -92
- package/dist/animation/theatre-clock-binding.d.ts +0 -89
- package/dist/animation/theatre-clock-binding.d.ts.map +0 -1
- package/dist/animation/theatre-clock-binding.js +0 -29
- package/dist/animation/theatre-director.d.ts +0 -242
- package/dist/animation/theatre-director.d.ts.map +0 -1
- package/dist/animation/theatre-director.js +0 -235
- package/dist/animation/theatre-object-binding.d.ts +0 -305
- package/dist/animation/theatre-object-binding.d.ts.map +0 -1
- package/dist/animation/theatre-object-binding.js +0 -351
- package/dist/animation/xstate-animation-binding.d.ts +0 -56
- package/dist/animation/xstate-animation-binding.d.ts.map +0 -1
- package/dist/animation/xstate-animation-binding.js +0 -331
- package/dist/animation/xstate-animation-meta.d.ts +0 -266
- package/dist/animation/xstate-animation-meta.d.ts.map +0 -1
- package/dist/animation/xstate-animation-meta.js +0 -252
- package/dist/assets.d.ts +0 -26
- package/dist/assets.d.ts.map +0 -1
- package/dist/assets.js +0 -55
- package/dist/audio/index.d.ts +0 -4
- package/dist/audio/index.d.ts.map +0 -1
- package/dist/audio/index.js +0 -24
- package/dist/audio/tone-clock-binding.d.ts +0 -75
- package/dist/audio/tone-clock-binding.d.ts.map +0 -1
- package/dist/audio/tone-clock-binding.js +0 -29
- package/dist/audio/tone-context.d.ts +0 -114
- package/dist/audio/tone-context.d.ts.map +0 -1
- package/dist/audio/tone-context.js +0 -39
- package/dist/audio/tone-offline-render.d.ts +0 -90
- package/dist/audio/tone-offline-render.d.ts.map +0 -1
- package/dist/audio/tone-offline-render.js +0 -56
- package/dist/audio/wav-encode.d.ts +0 -38
- package/dist/audio/wav-encode.d.ts.map +0 -1
- package/dist/audio/wav-encode.js +0 -97
- package/dist/character/cloth-sim.d.ts +0 -179
- package/dist/character/cloth-sim.d.ts.map +0 -1
- package/dist/character/cloth-sim.js +0 -334
- package/dist/character/spring-chain.d.ts +0 -135
- package/dist/character/spring-chain.d.ts.map +0 -1
- package/dist/character/spring-chain.js +0 -165
- package/dist/core/game-loop.d.ts +0 -42
- package/dist/core/game-loop.d.ts.map +0 -1
- package/dist/core/game-loop.js +0 -167
- package/dist/core/seeded-random.d.ts +0 -69
- package/dist/core/seeded-random.d.ts.map +0 -1
- package/dist/core/seeded-random.js +0 -121
- package/dist/core/system-runner.d.ts +0 -120
- package/dist/core/system-runner.d.ts.map +0 -1
- package/dist/core/system-runner.js +0 -297
- package/dist/core/types.d.ts +0 -92
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js +0 -25
- package/dist/data/data-asset.d.ts +0 -101
- package/dist/data/data-asset.d.ts.map +0 -1
- package/dist/data/data-asset.js +0 -122
- package/dist/data/data-check-core.d.ts +0 -110
- package/dist/data/data-check-core.d.ts.map +0 -1
- package/dist/data/data-check-core.js +0 -178
- package/dist/data/data-ref.d.ts +0 -79
- package/dist/data/data-ref.d.ts.map +0 -1
- package/dist/data/data-ref.js +0 -130
- package/dist/data/vite-plugin-data.d.ts +0 -79
- package/dist/data/vite-plugin-data.d.ts.map +0 -1
- package/dist/data/vite-plugin-data.js +0 -217
- package/dist/dev/console-bridge.d.ts +0 -22
- package/dist/dev/console-bridge.d.ts.map +0 -1
- package/dist/dev/console-bridge.js +0 -71
- package/dist/dev/debug-draw.d.ts +0 -24
- package/dist/dev/debug-draw.d.ts.map +0 -1
- package/dist/dev/debug-draw.js +0 -73
- package/dist/dev/logger.d.ts +0 -30
- package/dist/dev/logger.d.ts.map +0 -1
- package/dist/dev/logger.js +0 -90
- package/dist/dev/performance-profiler.d.ts +0 -60
- package/dist/dev/performance-profiler.d.ts.map +0 -1
- package/dist/dev/performance-profiler.js +0 -181
- package/dist/dev/webgl-gpu-timer.d.ts +0 -8
- package/dist/dev/webgl-gpu-timer.d.ts.map +0 -1
- package/dist/dev/webgl-gpu-timer.js +0 -52
- package/dist/ecs/component-manager.d.ts +0 -205
- package/dist/ecs/component-manager.d.ts.map +0 -1
- package/dist/ecs/component-manager.js +0 -706
- package/dist/ecs/game-component.d.ts +0 -146
- package/dist/ecs/game-component.d.ts.map +0 -1
- package/dist/ecs/game-component.js +0 -141
- package/dist/ecs/hmr-swap-report.d.ts +0 -53
- package/dist/ecs/hmr-swap-report.d.ts.map +0 -1
- package/dist/ecs/hmr-swap-report.js +0 -55
- package/dist/humanoid/bake.operation.d.ts +0 -119
- package/dist/humanoid/bake.operation.d.ts.map +0 -1
- package/dist/humanoid/bake.operation.js +0 -228
- package/dist/humanoid/body.d.ts +0 -101
- package/dist/humanoid/body.d.ts.map +0 -1
- package/dist/humanoid/body.js +0 -530
- package/dist/humanoid/clips.d.ts +0 -62
- package/dist/humanoid/clips.d.ts.map +0 -1
- package/dist/humanoid/clips.js +0 -121
- package/dist/humanoid/compose.d.ts +0 -75
- package/dist/humanoid/compose.d.ts.map +0 -1
- package/dist/humanoid/compose.js +0 -176
- package/dist/humanoid/generate.d.ts +0 -92
- package/dist/humanoid/generate.d.ts.map +0 -1
- package/dist/humanoid/generate.js +0 -124
- package/dist/humanoid/index.d.ts +0 -24
- package/dist/humanoid/index.d.ts.map +0 -1
- package/dist/humanoid/index.js +0 -18
- package/dist/humanoid/schema.d.ts +0 -35
- package/dist/humanoid/schema.d.ts.map +0 -1
- package/dist/humanoid/schema.js +0 -87
- package/dist/humanoid/skeleton.d.ts +0 -103
- package/dist/humanoid/skeleton.d.ts.map +0 -1
- package/dist/humanoid/skeleton.js +0 -289
- package/dist/index.d.ts +0 -37
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -30
- package/dist/input/input-manager.d.ts +0 -945
- package/dist/input/input-manager.d.ts.map +0 -1
- package/dist/input/input-manager.js +0 -2207
- package/dist/input/input-types.d.ts +0 -174
- package/dist/input/input-types.d.ts.map +0 -1
- package/dist/input/input-types.js +0 -1
- package/dist/input/prompt-labels.d.ts +0 -21
- package/dist/input/prompt-labels.d.ts.map +0 -1
- package/dist/input/prompt-labels.js +0 -121
- package/dist/input/rebind-controller.d.ts +0 -59
- package/dist/input/rebind-controller.d.ts.map +0 -1
- package/dist/input/rebind-controller.js +0 -85
- package/dist/input/schema.d.ts +0 -16
- package/dist/input/schema.d.ts.map +0 -1
- package/dist/input/schema.js +0 -228
- package/dist/loader.d.ts +0 -43
- package/dist/loader.d.ts.map +0 -1
- package/dist/loader.js +0 -59
- package/dist/manifest/index.d.ts +0 -5
- package/dist/manifest/index.d.ts.map +0 -1
- package/dist/manifest/index.js +0 -8
- package/dist/manifest/load-file.d.ts +0 -4
- package/dist/manifest/load-file.d.ts.map +0 -1
- package/dist/manifest/load-file.js +0 -14
- package/dist/manifest/load.d.ts +0 -144
- package/dist/manifest/load.d.ts.map +0 -1
- package/dist/manifest/load.js +0 -273
- package/dist/manifest/schema.d.ts +0 -230
- package/dist/manifest/schema.d.ts.map +0 -1
- package/dist/manifest/schema.js +0 -394
- package/dist/physics/collision-system.d.ts +0 -41
- package/dist/physics/collision-system.d.ts.map +0 -1
- package/dist/physics/collision-system.js +0 -64
- package/dist/physics/physics-registry.d.ts +0 -45
- package/dist/physics/physics-registry.d.ts.map +0 -1
- package/dist/physics/physics-registry.js +0 -65
- package/dist/physics/transform-writer.d.ts +0 -16
- package/dist/physics/transform-writer.d.ts.map +0 -1
- package/dist/physics/transform-writer.js +0 -38
- package/dist/physics/trigger-dispatch.d.ts +0 -24
- package/dist/physics/trigger-dispatch.d.ts.map +0 -1
- package/dist/physics/trigger-dispatch.js +0 -80
- package/dist/react/game-state.d.ts +0 -156
- package/dist/react/game-state.d.ts.map +0 -1
- package/dist/react/game-state.js +0 -222
- package/dist/react/root-adapter.d.ts +0 -11
- package/dist/react/root-adapter.d.ts.map +0 -1
- package/dist/react/root-adapter.js +0 -41
- package/dist/react/unmanaged-root-detector.d.ts +0 -12
- package/dist/react/unmanaged-root-detector.d.ts.map +0 -1
- package/dist/react/unmanaged-root-detector.js +0 -45
- package/dist/react/use-data.d.ts +0 -60
- package/dist/react/use-data.d.ts.map +0 -1
- package/dist/react/use-data.js +0 -101
- package/dist/react/use-selection.d.ts +0 -75
- package/dist/react/use-selection.d.ts.map +0 -1
- package/dist/react/use-selection.js +0 -90
- package/dist/render/auto-batcher.d.ts +0 -34
- package/dist/render/auto-batcher.d.ts.map +0 -1
- package/dist/render/auto-batcher.js +0 -140
- package/dist/render/render-batch-system.d.ts +0 -33
- package/dist/render/render-batch-system.d.ts.map +0 -1
- package/dist/render/render-batch-system.js +0 -230
- package/dist/render/render-features.d.ts +0 -47
- package/dist/render/render-features.d.ts.map +0 -1
- package/dist/render/render-features.js +0 -105
- package/dist/render/render-settings.d.ts +0 -36
- package/dist/render/render-settings.d.ts.map +0 -1
- package/dist/render/render-settings.js +0 -51
- package/dist/runtime/create-runtime.d.ts +0 -249
- package/dist/runtime/create-runtime.d.ts.map +0 -1
- package/dist/runtime/create-runtime.js +0 -641
- package/dist/runtime/debug-bridge.d.ts +0 -257
- package/dist/runtime/debug-bridge.d.ts.map +0 -1
- package/dist/runtime/debug-bridge.js +0 -224
- package/dist/runtime/debug-registry.d.ts +0 -288
- package/dist/runtime/debug-registry.d.ts.map +0 -1
- package/dist/runtime/debug-registry.js +0 -513
- package/dist/runtime/frame-selector-cache.d.ts +0 -41
- package/dist/runtime/frame-selector-cache.d.ts.map +0 -1
- package/dist/runtime/frame-selector-cache.js +0 -65
- package/dist/runtime/game.d.ts +0 -496
- package/dist/runtime/game.d.ts.map +0 -1
- package/dist/runtime/game.js +0 -741
- package/dist/runtime/gameplay-rng-trap.d.ts +0 -48
- package/dist/runtime/gameplay-rng-trap.d.ts.map +0 -1
- package/dist/runtime/gameplay-rng-trap.js +0 -96
- package/dist/runtime/input-router.d.ts +0 -78
- package/dist/runtime/input-router.d.ts.map +0 -1
- package/dist/runtime/input-router.js +0 -171
- package/dist/runtime/mount-game.d.ts +0 -129
- package/dist/runtime/mount-game.d.ts.map +0 -1
- package/dist/runtime/mount-game.js +0 -152
- package/dist/runtime/mount-manifest.d.ts +0 -173
- package/dist/runtime/mount-manifest.d.ts.map +0 -1
- package/dist/runtime/mount-manifest.js +0 -297
- package/dist/runtime/render-audio-control.d.ts +0 -110
- package/dist/runtime/render-audio-control.d.ts.map +0 -1
- package/dist/runtime/render-audio-control.js +0 -111
- package/dist/runtime/render-control.d.ts +0 -291
- package/dist/runtime/render-control.d.ts.map +0 -1
- package/dist/runtime/render-control.js +0 -264
- package/dist/runtime/render-seed.d.ts +0 -57
- package/dist/runtime/render-seed.d.ts.map +0 -1
- package/dist/runtime/render-seed.js +0 -74
- package/dist/runtime/state-bridge.d.ts +0 -61
- package/dist/runtime/state-bridge.d.ts.map +0 -1
- package/dist/runtime/state-bridge.js +0 -63
- package/dist/runtime/types.d.ts +0 -253
- package/dist/runtime/types.d.ts.map +0 -1
- package/dist/runtime/types.js +0 -1
- package/dist/scene/asset-loaders.d.ts +0 -79
- package/dist/scene/asset-loaders.d.ts.map +0 -1
- package/dist/scene/asset-loaders.js +0 -141
- package/dist/scene/asset-paths.d.ts +0 -11
- package/dist/scene/asset-paths.d.ts.map +0 -1
- package/dist/scene/asset-paths.js +0 -108
- package/dist/scene/asset-ref-check.d.ts +0 -88
- package/dist/scene/asset-ref-check.d.ts.map +0 -1
- package/dist/scene/asset-ref-check.js +0 -214
- package/dist/scene/asset-registry.d.ts +0 -38
- package/dist/scene/asset-registry.d.ts.map +0 -1
- package/dist/scene/asset-registry.js +0 -66
- package/dist/scene/collider-dimensions.d.ts +0 -63
- package/dist/scene/collider-dimensions.d.ts.map +0 -1
- package/dist/scene/collider-dimensions.js +0 -98
- package/dist/scene/component-registry.d.ts +0 -22
- package/dist/scene/component-registry.d.ts.map +0 -1
- package/dist/scene/component-registry.js +0 -37
- package/dist/scene/defaults.d.ts +0 -252
- package/dist/scene/defaults.d.ts.map +0 -1
- package/dist/scene/defaults.js +0 -151
- package/dist/scene/geometries/index.d.ts +0 -8
- package/dist/scene/geometries/index.d.ts.map +0 -1
- package/dist/scene/geometries/index.js +0 -7
- package/dist/scene/geometries/terrain.d.ts +0 -2
- package/dist/scene/geometries/terrain.d.ts.map +0 -1
- package/dist/scene/geometries/terrain.js +0 -37
- package/dist/scene/geometry-registry.d.ts +0 -24
- package/dist/scene/geometry-registry.d.ts.map +0 -1
- package/dist/scene/geometry-registry.js +0 -20
- package/dist/scene/instance-registry.d.ts +0 -36
- package/dist/scene/instance-registry.d.ts.map +0 -1
- package/dist/scene/instance-registry.js +0 -55
- package/dist/scene/instancers/grid.d.ts +0 -2
- package/dist/scene/instancers/grid.d.ts.map +0 -1
- package/dist/scene/instancers/grid.js +0 -36
- package/dist/scene/instancers/index.d.ts +0 -8
- package/dist/scene/instancers/index.d.ts.map +0 -1
- package/dist/scene/instancers/index.js +0 -7
- package/dist/scene/light-camera-factory.d.ts +0 -23
- package/dist/scene/light-camera-factory.d.ts.map +0 -1
- package/dist/scene/light-camera-factory.js +0 -68
- package/dist/scene/material-factory.d.ts +0 -17
- package/dist/scene/material-factory.d.ts.map +0 -1
- package/dist/scene/material-factory.js +0 -197
- package/dist/scene/material-registry.d.ts +0 -40
- package/dist/scene/material-registry.d.ts.map +0 -1
- package/dist/scene/material-registry.js +0 -44
- package/dist/scene/materials/index.d.ts +0 -8
- package/dist/scene/materials/index.d.ts.map +0 -1
- package/dist/scene/materials/index.js +0 -7
- package/dist/scene/materials/water.d.ts +0 -2
- package/dist/scene/materials/water.d.ts.map +0 -1
- package/dist/scene/materials/water.js +0 -54
- package/dist/scene/parse.d.ts +0 -23
- package/dist/scene/parse.d.ts.map +0 -1
- package/dist/scene/parse.js +0 -179
- package/dist/scene/particles-factory.d.ts +0 -33
- package/dist/scene/particles-factory.d.ts.map +0 -1
- package/dist/scene/particles-factory.js +0 -282
- package/dist/scene/scene-apply.d.ts +0 -109
- package/dist/scene/scene-apply.d.ts.map +0 -1
- package/dist/scene/scene-apply.js +0 -370
- package/dist/scene/scene-diff-schema.d.ts +0 -285
- package/dist/scene/scene-diff-schema.d.ts.map +0 -1
- package/dist/scene/scene-diff-schema.js +0 -92
- package/dist/scene/scene-diff-types.d.ts +0 -40
- package/dist/scene/scene-diff-types.d.ts.map +0 -1
- package/dist/scene/scene-diff-types.js +0 -14
- package/dist/scene/scene-loader.d.ts +0 -167
- package/dist/scene/scene-loader.d.ts.map +0 -1
- package/dist/scene/scene-loader.js +0 -1211
- package/dist/scene/scene-query.d.ts +0 -11
- package/dist/scene/scene-query.d.ts.map +0 -1
- package/dist/scene/scene-query.js +0 -63
- package/dist/scene/scene-types.d.ts +0 -10
- package/dist/scene/scene-types.d.ts.map +0 -1
- package/dist/scene/scene-types.js +0 -8
- package/dist/scene/scene-version.d.ts +0 -26
- package/dist/scene/scene-version.d.ts.map +0 -1
- package/dist/scene/scene-version.js +0 -34
- package/dist/scene/schema/animation.d.ts +0 -8
- package/dist/scene/schema/animation.d.ts.map +0 -1
- package/dist/scene/schema/animation.js +0 -42
- package/dist/scene/schema/audio.d.ts +0 -13
- package/dist/scene/schema/audio.d.ts.map +0 -1
- package/dist/scene/schema/audio.js +0 -22
- package/dist/scene/schema/camera.d.ts +0 -28
- package/dist/scene/schema/camera.d.ts.map +0 -1
- package/dist/scene/schema/camera.js +0 -17
- package/dist/scene/schema/collider.d.ts +0 -40
- package/dist/scene/schema/collider.d.ts.map +0 -1
- package/dist/scene/schema/collider.js +0 -55
- package/dist/scene/schema/entity-ref.d.ts +0 -31
- package/dist/scene/schema/entity-ref.d.ts.map +0 -1
- package/dist/scene/schema/entity-ref.js +0 -61
- package/dist/scene/schema/entity.d.ts +0 -1036
- package/dist/scene/schema/entity.d.ts.map +0 -1
- package/dist/scene/schema/entity.js +0 -153
- package/dist/scene/schema/environment.d.ts +0 -425
- package/dist/scene/schema/environment.d.ts.map +0 -1
- package/dist/scene/schema/environment.js +0 -357
- package/dist/scene/schema/index.d.ts +0 -37
- package/dist/scene/schema/index.d.ts.map +0 -1
- package/dist/scene/schema/index.js +0 -19
- package/dist/scene/schema/instances.d.ts +0 -14
- package/dist/scene/schema/instances.d.ts.map +0 -1
- package/dist/scene/schema/instances.js +0 -28
- package/dist/scene/schema/joint.d.ts +0 -23
- package/dist/scene/schema/joint.d.ts.map +0 -1
- package/dist/scene/schema/joint.js +0 -23
- package/dist/scene/schema/light.d.ts +0 -38
- package/dist/scene/schema/light.d.ts.map +0 -1
- package/dist/scene/schema/light.js +0 -26
- package/dist/scene/schema/material.d.ts +0 -199
- package/dist/scene/schema/material.d.ts.map +0 -1
- package/dist/scene/schema/material.js +0 -103
- package/dist/scene/schema/mesh.d.ts +0 -48
- package/dist/scene/schema/mesh.d.ts.map +0 -1
- package/dist/scene/schema/mesh.js +0 -82
- package/dist/scene/schema/particles.d.ts +0 -2178
- package/dist/scene/schema/particles.d.ts.map +0 -1
- package/dist/scene/schema/particles.js +0 -321
- package/dist/scene/schema/physics.d.ts +0 -56
- package/dist/scene/schema/physics.d.ts.map +0 -1
- package/dist/scene/schema/physics.js +0 -37
- package/dist/scene/schema/scene-file.d.ts +0 -303
- package/dist/scene/schema/scene-file.d.ts.map +0 -1
- package/dist/scene/schema/scene-file.js +0 -256
- package/dist/scene/schema/shadow.d.ts +0 -28
- package/dist/scene/schema/shadow.d.ts.map +0 -1
- package/dist/scene/schema/shadow.js +0 -20
- package/dist/scene/schema/spline.d.ts +0 -25
- package/dist/scene/schema/spline.d.ts.map +0 -1
- package/dist/scene/schema/spline.js +0 -15
- package/dist/scene/schema/tuples.d.ts +0 -12
- package/dist/scene/schema/tuples.d.ts.map +0 -1
- package/dist/scene/schema/tuples.js +0 -14
- package/dist/scene/user-data.d.ts +0 -185
- package/dist/scene/user-data.d.ts.map +0 -1
- package/dist/scene/user-data.js +0 -144
- package/dist/setup/setup-audio.d.ts +0 -20
- package/dist/setup/setup-audio.d.ts.map +0 -1
- package/dist/setup/setup-audio.js +0 -41
- package/dist/setup/setup-particles.d.ts +0 -17
- package/dist/setup/setup-particles.d.ts.map +0 -1
- package/dist/setup/setup-particles.js +0 -16
- package/dist/setup/setup-physics.d.ts +0 -25
- package/dist/setup/setup-physics.d.ts.map +0 -1
- package/dist/setup/setup-physics.js +0 -51
- package/dist/setup/setup-renderer.d.ts +0 -69
- package/dist/setup/setup-renderer.d.ts.map +0 -1
- package/dist/setup/setup-renderer.js +0 -363
- package/dist/tools/define-tool.d.ts +0 -130
- package/dist/tools/define-tool.d.ts.map +0 -1
- package/dist/tools/define-tool.js +0 -96
- package/dist/world2d/authoring-2d.d.ts +0 -80
- package/dist/world2d/authoring-2d.d.ts.map +0 -1
- package/dist/world2d/authoring-2d.js +0 -195
- package/dist/world2d/capture-to-scene2d.d.ts +0 -5
- package/dist/world2d/capture-to-scene2d.d.ts.map +0 -1
- package/dist/world2d/capture-to-scene2d.js +0 -49
- package/dist/world2d/collision-2d.d.ts +0 -52
- package/dist/world2d/collision-2d.d.ts.map +0 -1
- package/dist/world2d/collision-2d.js +0 -70
- package/dist/world2d/components-2d.d.ts +0 -47
- package/dist/world2d/components-2d.d.ts.map +0 -1
- package/dist/world2d/components-2d.js +0 -77
- package/dist/world2d/index.d.ts +0 -34
- package/dist/world2d/index.d.ts.map +0 -1
- package/dist/world2d/index.js +0 -32
- package/dist/world2d/ingest-iframe-2d.d.ts +0 -82
- package/dist/world2d/ingest-iframe-2d.d.ts.map +0 -1
- package/dist/world2d/ingest-iframe-2d.js +0 -166
- package/dist/world2d/ingest2d.d.ts +0 -97
- package/dist/world2d/ingest2d.d.ts.map +0 -1
- package/dist/world2d/ingest2d.js +0 -40
- package/dist/world2d/physics2d-registry.d.ts +0 -24
- package/dist/world2d/physics2d-registry.d.ts.map +0 -1
- package/dist/world2d/physics2d-registry.js +0 -38
- package/dist/world2d/pixi-game-adapter.d.ts +0 -107
- package/dist/world2d/pixi-game-adapter.d.ts.map +0 -1
- package/dist/world2d/pixi-game-adapter.js +0 -210
- package/dist/world2d/pixi-surface.d.ts +0 -39
- package/dist/world2d/pixi-surface.d.ts.map +0 -1
- package/dist/world2d/pixi-surface.js +0 -47
- package/dist/world2d/scene-capture-2d.d.ts +0 -43
- package/dist/world2d/scene-capture-2d.d.ts.map +0 -1
- package/dist/world2d/scene-capture-2d.js +0 -92
- package/dist/world2d/scene2d-loader.d.ts +0 -27
- package/dist/world2d/scene2d-loader.d.ts.map +0 -1
- package/dist/world2d/scene2d-loader.js +0 -275
- package/dist/world2d/schema/entity2d.d.ts +0 -102
- package/dist/world2d/schema/entity2d.d.ts.map +0 -1
- package/dist/world2d/schema/entity2d.js +0 -119
- package/dist/world2d/schema/physics2d.d.ts +0 -46
- package/dist/world2d/schema/physics2d.d.ts.map +0 -1
- package/dist/world2d/schema/physics2d.js +0 -45
- package/dist/world2d/schema/sprite.d.ts +0 -42
- package/dist/world2d/schema/sprite.d.ts.map +0 -1
- package/dist/world2d/schema/sprite.js +0 -63
- package/dist/world2d/schema/tilemap.d.ts +0 -15
- package/dist/world2d/schema/tilemap.d.ts.map +0 -1
- package/dist/world2d/schema/tilemap.js +0 -19
- package/dist/world2d/schema/tuples2d.d.ts +0 -20
- package/dist/world2d/schema/tuples2d.d.ts.map +0 -1
- package/dist/world2d/schema/tuples2d.js +0 -19
- package/dist/world2d/system-adapters-2d.d.ts +0 -16
- package/dist/world2d/system-adapters-2d.d.ts.map +0 -1
- package/dist/world2d/system-adapters-2d.js +0 -37
- package/dist/world2d/transform-writer-2d.d.ts +0 -16
- package/dist/world2d/transform-writer-2d.d.ts.map +0 -1
- package/dist/world2d/transform-writer-2d.js +0 -22
- package/dist/world2d/types.d.ts +0 -59
- package/dist/world2d/types.d.ts.map +0 -1
- package/dist/world2d/types.js +0 -1
|
@@ -1,762 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VgaiSceneGameAdapter — the FIRST-PARTY implementer of {@link GameAdapter}.
|
|
3
|
-
*
|
|
4
|
-
* This is where `.vscn` + `GameComponent` + Rapier live now: the host no longer
|
|
5
|
-
* knows about any of them. `mount(host)` builds the full first-party runtime
|
|
6
|
-
* (the body that used to live inline in `create-runtime.ts`) from a neutral
|
|
7
|
-
* {@link HostContext}, runs the game's `setup`/scene load, and returns a
|
|
8
|
-
* {@link MountedGame}. First-party content is now just one implementer of the
|
|
9
|
-
* same interface an unmodified external game implements (Phase B).
|
|
10
|
-
*
|
|
11
|
-
* `GameSetupFn` / `GameContext` are imported ONLY here (and in the example
|
|
12
|
-
* `fromSetup` wrappers) — never by the host. That confinement is the inversion.
|
|
13
|
-
*/
|
|
14
|
-
import RAPIER from '@dimforge/rapier3d-compat';
|
|
15
|
-
import * as THREE from 'three';
|
|
16
|
-
import { createSeededRandom, DEFAULT_SEEDED_RANDOM_SEED, getSeededRandom, } from '../core/seeded-random';
|
|
17
|
-
import { createSystemRunner } from '../core/system-runner';
|
|
18
|
-
import { createDebugDraw } from '../dev/debug-draw';
|
|
19
|
-
import { createWebGLGpuTimer } from '../dev/webgl-gpu-timer';
|
|
20
|
-
import { createComponentManager } from '../ecs/component-manager';
|
|
21
|
-
import { InputManager } from '../input/input-manager';
|
|
22
|
-
import { setAssetPrefix } from '../loader';
|
|
23
|
-
import { createCollisionSystem } from '../physics/collision-system';
|
|
24
|
-
import { createPhysicsRegistry } from '../physics/physics-registry';
|
|
25
|
-
import { createTransformWriter } from '../physics/transform-writer';
|
|
26
|
-
import { createTriggerDispatch } from '../physics/trigger-dispatch';
|
|
27
|
-
import { RenderBatchSystem } from '../render/render-batch-system';
|
|
28
|
-
import { resolveRenderSettings } from '../render/render-settings';
|
|
29
|
-
import { createDebugRegistry, getDebugRegistry, } from '../runtime/debug-registry';
|
|
30
|
-
import { tickCustomMaterials } from '../scene/material-registry';
|
|
31
|
-
import { clearAssetCaches, loadScene, loadSceneFromData, updateSceneLODs, } from '../scene/scene-loader';
|
|
32
|
-
import { hasUserData, setUserData } from '../scene/user-data';
|
|
33
|
-
import { setupAudio } from '../setup/setup-audio';
|
|
34
|
-
import { setupParticles } from '../setup/setup-particles';
|
|
35
|
-
import { setupPhysics, updatePhysicsDebug } from '../setup/setup-physics';
|
|
36
|
-
import { applyRendererSettings, applyScenePostProcessing, createSceneView, } from '../setup/setup-renderer';
|
|
37
|
-
import { createAudioSystemAdapter, createInputManagerAdapter, createNavigationAdapter, createVgaiAssetAdapter, } from './first-party-systems';
|
|
38
|
-
import { createRapierPhysicsAdapter } from './rapier-physics-adapter';
|
|
39
|
-
/** Minimal stand-in for the GPU composer when mounting headlessly. */
|
|
40
|
-
function headlessComposer(renderer) {
|
|
41
|
-
return {
|
|
42
|
-
render: () => { },
|
|
43
|
-
setSize: () => { },
|
|
44
|
-
dispose: () => { },
|
|
45
|
-
addPass: () => { },
|
|
46
|
-
removeAllPasses: () => { },
|
|
47
|
-
passes: [],
|
|
48
|
-
getRenderer: () => renderer,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Wrap a first-party `setup` function as a {@link GameAdapter}. This is how every
|
|
53
|
-
* first-party example becomes an implementer of the same interface an external
|
|
54
|
-
* game implements — with no change to the setup's body.
|
|
55
|
-
*/
|
|
56
|
-
export function fromSetup(id, setup) {
|
|
57
|
-
return new VgaiSceneGameAdapter({ id, setup });
|
|
58
|
-
}
|
|
59
|
-
export class VgaiSceneGameAdapter {
|
|
60
|
-
config;
|
|
61
|
-
id;
|
|
62
|
-
constructor(config = {}) {
|
|
63
|
-
this.config = config;
|
|
64
|
-
this.id = config.id ?? 'vgai-scene';
|
|
65
|
-
}
|
|
66
|
-
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one cohesive first-party bootstrap (moved verbatim from create-runtime); splitting it would obscure the ordering contract
|
|
67
|
-
async mount(host) {
|
|
68
|
-
const { setup, editorPreview, scenePath, sceneData, componentRegistry, inputMapPath = '/inputmaps/default.inputmap.json', assetPrefix = '/', } = this.config;
|
|
69
|
-
const headless = host.headless === true;
|
|
70
|
-
const { width, height } = host.surface;
|
|
71
|
-
const renderer = host.renderer;
|
|
72
|
-
setAssetPrefix(assetPrefix);
|
|
73
|
-
// --- Scene view (scene/camera/composer). Browser: the canonical builder, so
|
|
74
|
-
// behavior is byte-identical to the old create-runtime. Headless: plain
|
|
75
|
-
// scene/camera + a no-op composer (no GPU). ---
|
|
76
|
-
let scene;
|
|
77
|
-
let camera;
|
|
78
|
-
let composer;
|
|
79
|
-
if (headless) {
|
|
80
|
-
scene = new THREE.Scene();
|
|
81
|
-
scene.background = new THREE.Color(0x1a1a2e);
|
|
82
|
-
camera = new THREE.PerspectiveCamera(60, width / height || 1, 0.1, 1000);
|
|
83
|
-
camera.position.set(0, 5, 10);
|
|
84
|
-
camera.lookAt(0, 0, 0);
|
|
85
|
-
composer = headlessComposer(renderer);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
const view = createSceneView(renderer, width, height);
|
|
89
|
-
scene = view.scene;
|
|
90
|
-
camera = view.camera;
|
|
91
|
-
composer = view.composer;
|
|
92
|
-
}
|
|
93
|
-
// --- Rapier physics ---
|
|
94
|
-
await RAPIER.init();
|
|
95
|
-
const physics = setupPhysics(RAPIER, scene);
|
|
96
|
-
const physicsRegistry = createPhysicsRegistry();
|
|
97
|
-
const writeTransforms = createTransformWriter(physicsRegistry, scene);
|
|
98
|
-
// --- Input (InputManager attaches window listeners; stub it headlessly) ---
|
|
99
|
-
const input = headless ? headlessInput() : new InputManager();
|
|
100
|
-
if (!headless)
|
|
101
|
-
await input.loadMap(inputMapPath);
|
|
102
|
-
// --- Collision system ---
|
|
103
|
-
const collisions = createCollisionSystem(physics.rapierWorld, physics.eventQueue);
|
|
104
|
-
// --- Audio (Web Audio — browser only) ---
|
|
105
|
-
const audio = headless ? headlessAudio() : setupAudio(camera);
|
|
106
|
-
// --- Particles (three.quarks BatchedRenderer) ---
|
|
107
|
-
const particles = setupParticles(scene);
|
|
108
|
-
// --- Debug draw / assets ---
|
|
109
|
-
const debugDraw = createDebugDraw(scene);
|
|
110
|
-
const assets = host.assets;
|
|
111
|
-
// Test/headless adapters may provide the renderer surface needed by the
|
|
112
|
-
// runtime without a real WebGL context. GPU timing is optional diagnostics:
|
|
113
|
-
// degrade honestly when the renderer/context cannot expose extensions.
|
|
114
|
-
const rendererContext = typeof renderer.getContext === 'function' ? renderer.getContext() : undefined;
|
|
115
|
-
const gpuTimer = !headless && rendererContext && typeof rendererContext.getExtension === 'function'
|
|
116
|
-
? createWebGLGpuTimer(rendererContext)
|
|
117
|
-
: null;
|
|
118
|
-
// --- System runner (engine-level systems) ---
|
|
119
|
-
const systems = createSystemRunner(host.game?.profiler.systemObserver, 'threejs');
|
|
120
|
-
// D15/T-D15.3/.5: pass the LIVE shared game tick (not a locally-counted
|
|
121
|
-
// one) into every `poll()` call — `debugRegistry` is declared further
|
|
122
|
-
// down in this same `mount()` (it needs `ctx`/`systemAdapters` to exist
|
|
123
|
-
// first), but this callback only ever executes during real frame
|
|
124
|
-
// ticks, long after `mount()` has fully returned and `debugRegistry` is
|
|
125
|
-
// initialized (a safe closure-over-a-later-const, not a genuine
|
|
126
|
-
// use-before-init). `host.game` gates it: a bare mount with no `Game`
|
|
127
|
-
// shell behind it (test harnesses predating T7.1) has no shared tick to
|
|
128
|
-
// key off, so `InputManager.poll()` falls back to its own internal
|
|
129
|
-
// self-incrementing counter instead (unchanged pre-D15 behavior) rather
|
|
130
|
-
// than being pinned to a constant `0` forever.
|
|
131
|
-
systems.add('input', () => input.poll(host.game ? debugRegistry.getGameTick() : undefined), {
|
|
132
|
-
name: 'input.poll',
|
|
133
|
-
});
|
|
134
|
-
systems.add('physics', () => physics.rapierWorld.step(physics.eventQueue), {
|
|
135
|
-
name: 'physics.step',
|
|
136
|
-
});
|
|
137
|
-
systems.add('postPhysics', () => {
|
|
138
|
-
collisions.drain();
|
|
139
|
-
writeTransforms();
|
|
140
|
-
}, { name: 'physics.sync' });
|
|
141
|
-
systems.add('preRender', (dt) => {
|
|
142
|
-
particles.batchedRenderer.update(dt);
|
|
143
|
-
tickCustomMaterials(scene, dt);
|
|
144
|
-
updateSceneLODs(scene, camera);
|
|
145
|
-
}, { name: 'materials-and-particles' });
|
|
146
|
-
if (!headless) {
|
|
147
|
-
systems.add('render', (dt) => {
|
|
148
|
-
if (host.game?.profiler.enabled)
|
|
149
|
-
gpuTimer?.begin();
|
|
150
|
-
try {
|
|
151
|
-
composer.render(dt);
|
|
152
|
-
}
|
|
153
|
-
finally {
|
|
154
|
-
gpuTimer?.end();
|
|
155
|
-
}
|
|
156
|
-
if (physics.debugEnabled)
|
|
157
|
-
updatePhysicsDebug(physics.rapierWorld, physics.debugMesh);
|
|
158
|
-
}, { name: 'three.render' });
|
|
159
|
-
}
|
|
160
|
-
// --- Debug toggle (browser only) ---
|
|
161
|
-
const onDebugToggle = (e) => {
|
|
162
|
-
if (e.code === 'KeyP') {
|
|
163
|
-
physics.debugEnabled = !physics.debugEnabled;
|
|
164
|
-
physics.debugMesh.visible = physics.debugEnabled;
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
if (!headless)
|
|
168
|
-
window.addEventListener('keydown', onDebugToggle);
|
|
169
|
-
const postFrame = () => {
|
|
170
|
-
input.endFrame();
|
|
171
|
-
if (host.game?.profiler.enabled) {
|
|
172
|
-
host.game.profiler.reportRender({
|
|
173
|
-
gpuMs: gpuTimer?.poll() ?? null,
|
|
174
|
-
drawCalls: renderer.info.render.calls,
|
|
175
|
-
triangles: renderer.info.render.triangles,
|
|
176
|
-
geometries: renderer.info.memory.geometries,
|
|
177
|
-
textures: renderer.info.memory.textures,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
// The mounted game's adapter surface (`mounted.systems`). Declared before
|
|
182
|
-
// ctx so `ctx.registerSystemAdapter` can close over it: the engine fills
|
|
183
|
-
// the first-party entries below; GAME-owned capabilities (networking,
|
|
184
|
-
// navigation) are registered by the game's setup through the ctx hook.
|
|
185
|
-
// The editor holds this same object reference (setActiveSystems), so
|
|
186
|
-
// late registrations are visible to its panels at read time.
|
|
187
|
-
const systemAdapters = {};
|
|
188
|
-
// --- GameContext (the first-party runtime surface) ---
|
|
189
|
-
const ctx = {
|
|
190
|
-
scene,
|
|
191
|
-
camera,
|
|
192
|
-
rapierWorld: physics.rapierWorld,
|
|
193
|
-
rapier: RAPIER,
|
|
194
|
-
physics: physicsRegistry,
|
|
195
|
-
input,
|
|
196
|
-
collisions,
|
|
197
|
-
composer,
|
|
198
|
-
audio,
|
|
199
|
-
particles,
|
|
200
|
-
debugDraw,
|
|
201
|
-
assets,
|
|
202
|
-
systems,
|
|
203
|
-
components: null,
|
|
204
|
-
registerSystemAdapter: (kind, adapter) => {
|
|
205
|
-
systemAdapters[kind] = adapter;
|
|
206
|
-
},
|
|
207
|
-
};
|
|
208
|
-
// Game root (T7.1 slice 1): only present once the host has constructed a
|
|
209
|
-
// Game shell (createGameRuntime does this before mount; headless/foreign
|
|
210
|
-
// hosts may omit it — ctx.game/ctx.roots simply stay undefined, which is
|
|
211
|
-
// the documented zero-break behavior). `ctx.roots` is assigned the SAME
|
|
212
|
-
// live array `host.game` mutates via `registerWorld` (not a copy) — the
|
|
213
|
-
// default world is registered AFTER mount returns, and this reference
|
|
214
|
-
// must observe that later push.
|
|
215
|
-
if (host.game) {
|
|
216
|
-
ctx.game = host.game;
|
|
217
|
-
ctx.roots = host.game.roots;
|
|
218
|
-
}
|
|
219
|
-
ctx.components = createComponentManager(ctx, physicsRegistry);
|
|
220
|
-
collisions.onCollision(createTriggerDispatch(physicsRegistry, ctx.components, physics.rapierWorld, ctx));
|
|
221
|
-
// Everything registered above (engine systems + the ComponentManager's
|
|
222
|
-
// per-phase tick, just wired in) is "engine" and must survive a warm
|
|
223
|
-
// restart. Everything a game (setup()/scenePath/sceneData, below) adds
|
|
224
|
-
// from here on is "game" content that `hotReload` bulk-removes via
|
|
225
|
-
// `systems.removeAllNonEngine()` on every restart (T1.7).
|
|
226
|
-
systems.markEngineBoundary();
|
|
227
|
-
// First-party System adapters over the real subsystems — seeded HERE,
|
|
228
|
-
// BEFORE setup()/scene load runs below, so that a game which registers any
|
|
229
|
-
// of these kinds during its own setup (via `ctx.registerSystemAdapter`)
|
|
230
|
-
// always wins over the engine's first-party entry (see
|
|
231
|
-
// registerSystemAdapter's docstring in runtime/types.ts). `navigation` is
|
|
232
|
-
// ALSO first-party now (R8 item 7): `createNavigationAdapter` wraps the
|
|
233
|
-
// real `NavMeshManager` a scenePath/sceneData scene load may produce (see
|
|
234
|
-
// `applySceneNavigation` below) — it is wired once that scene instance
|
|
235
|
-
// resolves, not here (no NavMeshManager exists yet at this point in the
|
|
236
|
-
// mount). `networking` remains the one game-owned capability with no
|
|
237
|
-
// first-party implementer; it simply starts absent here.
|
|
238
|
-
systemAdapters.physics = createRapierPhysicsAdapter(physicsRegistry, physics.debugMesh);
|
|
239
|
-
systemAdapters.input = createInputManagerAdapter(input);
|
|
240
|
-
systemAdapters.assets = createVgaiAssetAdapter();
|
|
241
|
-
// D10/T7.6: the audio seam `Game.play.pause()` silences on pause. Works
|
|
242
|
-
// against the headless stand-in too (`headlessAudio()`'s plain
|
|
243
|
-
// `masterGain.gain` object) — this world's `pause()` mutes it harmlessly.
|
|
244
|
-
systemAdapters.audio = createAudioSystemAdapter(audio);
|
|
245
|
-
// Debug/synthetic-player seam (T1.1, docs/SYNTHETIC-PLAYER-SPEC.md §3.1):
|
|
246
|
-
// ONE registry per Game root, shared across every world that mounts onto
|
|
247
|
-
// it — `getDebugRegistry(host.game)` reaches the SAME accumulator
|
|
248
|
-
// `createGame` filed, so a second/third world's `ctx.debug` feeds it too
|
|
249
|
-
// (see debug-registry.ts's module doc for the provenance/id note). A
|
|
250
|
-
// mount with no Game shell at all (bare test harnesses predating T7.1)
|
|
251
|
-
// gets a private, mount-local registry instead — same absence precedent
|
|
252
|
-
// as `ctx.game`/`ctx.roots` above.
|
|
253
|
-
const debugRegistry = (host.game ? getDebugRegistry(host.game) : null) ??
|
|
254
|
-
createDebugRegistry({ getTick: () => 0, getSimT: () => 0 });
|
|
255
|
-
systemAdapters.debug = debugRegistry.adapter;
|
|
256
|
-
ctx.debug = debugRegistry.forWorld(this.id);
|
|
257
|
-
// T1.2: the InputManager is a first-party per-world handle the registry
|
|
258
|
-
// has no other way to reach — wired as a lazy supplier (not a direct
|
|
259
|
-
// read here), scoped to THIS world's id, so the built-in `input.actions`
|
|
260
|
-
// provider always reflects the CURRENT action set, not a snapshot taken
|
|
261
|
-
// at mount time. Per-world (not a single last-writer-wins slot) since
|
|
262
|
-
// D15/T-D15.5 — see `debug-registry.ts`'s `setInputActionsSource` doc.
|
|
263
|
-
debugRegistry.setInputActionsSource(this.id, () => typeof input.actionNames === 'function'
|
|
264
|
-
? input.actionNames().map((name) => ({ name, valueType: input.getActionValueType(name) }))
|
|
265
|
-
: []);
|
|
266
|
-
// D15/T-D15.5 — same lazy-supplier pattern (and same headless-stand-in
|
|
267
|
-
// guard) as `setInputActionsSource` immediately above: the built-in
|
|
268
|
-
// `input.trace` provider always reads the CURRENT recorded trace, never
|
|
269
|
-
// a snapshot taken at mount time. `seed`/`fixedDt` are assembled here
|
|
270
|
-
// (not inside `InputManager`, which has no business knowing about
|
|
271
|
-
// `ctx.random` or the loop) — the two replay-critical metadata fields
|
|
272
|
-
// the design doc's format sketch (§2.c) calls for beside the raw
|
|
273
|
-
// per-tick deltas; `null` only absent a Game/ctx.random behind this
|
|
274
|
-
// mount, matching every other "no Game" fallback in this file.
|
|
275
|
-
debugRegistry.setInputTraceSource(this.id, () => {
|
|
276
|
-
const raw = typeof input.getInputTrace === 'function'
|
|
277
|
-
? input.getInputTrace()
|
|
278
|
-
: { version: 1, ticks: [] };
|
|
279
|
-
const seed = (host.game ? getSeededRandom(host.game) : null)?.seed ?? null;
|
|
280
|
-
const fixedDt = host.game?.loop.fixedDt ?? null;
|
|
281
|
-
return { version: raw.version, seed, fixedDt, ticks: raw.ticks };
|
|
282
|
-
});
|
|
283
|
-
// Task 2.1 — the same InputManager instance, wired as the debug bridge's
|
|
284
|
-
// actuation target (`runtime/debug-bridge.ts`'s `input.*` methods) at the
|
|
285
|
-
// same seed spot as `setInputActionsSource` above. Per-world (D15 review
|
|
286
|
-
// objection 2 fix) — see `debug-registry.ts`'s `setVirtualInputTarget`
|
|
287
|
-
// doc for why this used to be a single last-writer-wins slot.
|
|
288
|
-
debugRegistry.setVirtualInputTarget(this.id, {
|
|
289
|
-
setVirtualAction: (action, value) => input.setVirtualAction(action, value),
|
|
290
|
-
tapVirtualAction: (action) => input.tapVirtualAction(action),
|
|
291
|
-
clearVirtualActions: () => input.clearVirtualActions(),
|
|
292
|
-
scheduleActionAtTick: (tick, action, value) => input.scheduleActionAtTick(tick, action, value),
|
|
293
|
-
startInputRecording: () => input.startInputRecording(),
|
|
294
|
-
stopInputRecording: () => input.stopInputRecording(),
|
|
295
|
-
isInputRecording: () => input.isInputRecording(),
|
|
296
|
-
injectAxis: (sourceId, value) => input.injectAxis(sourceId, value),
|
|
297
|
-
injectVector2: (sourceId, value) => input.injectVector2(sourceId, value),
|
|
298
|
-
injectPointerDelta: (sourceId, delta) => input.injectPointerDelta(sourceId, delta),
|
|
299
|
-
injectPointerPosition: (sourceId, value) => input.injectPointerPosition(sourceId, value),
|
|
300
|
-
});
|
|
301
|
-
// R4-class fix — wire the InputManager's `'input.schedule.dropped'` sink
|
|
302
|
-
// to THIS world's debug registry, same seed spot/precedent as
|
|
303
|
-
// `setInputActionsSource`/`setVirtualInputTarget` above (typeof-guarded:
|
|
304
|
-
// a headless `InputManager` stand-in may have no `setDebugEmit`).
|
|
305
|
-
if (typeof input.setDebugEmit === 'function') {
|
|
306
|
-
input.setDebugEmit((event, detail) => ctx.debug?.emit(event, detail));
|
|
307
|
-
}
|
|
308
|
-
// D15 (T-D15.1) — same "ONE per Game root, shared across every world"
|
|
309
|
-
// pattern as the debug registry immediately above: `getSeededRandom
|
|
310
|
-
// (host.game)` reaches the SAME `SeededRandom` `createGame` filed (boot-
|
|
311
|
-
// seeded by the manifest-aware mount path, `mount-manifest.ts`, before
|
|
312
|
-
// ANY world's `mount()`/`setup()` runs — see `createGame`'s own doc
|
|
313
|
-
// comment), so every world's `ctx.random` is the identical instance, not
|
|
314
|
-
// a per-world copy. Same absence precedent as `ctx.debug`: a mount with
|
|
315
|
-
// no Game shell at all gets a private, mount-local surface instead.
|
|
316
|
-
ctx.random =
|
|
317
|
-
(host.game ? getSeededRandom(host.game) : null) ??
|
|
318
|
-
createSeededRandom(DEFAULT_SEEDED_RANDOM_SEED);
|
|
319
|
-
// Snapshot of the engine-owned adapter kinds, taken right after seeding
|
|
320
|
-
// and before any setup() has had a chance to run. `hotReload`/`disposeGame`
|
|
321
|
-
// use this to strip every GAME-registered kind (including an override of a
|
|
322
|
-
// first-party kind) left over from the outgoing game, so a warm restart or
|
|
323
|
-
// a full stop never exposes a disposed game's networking/etc. adapter to
|
|
324
|
-
// the next setup.
|
|
325
|
-
const engineAdapterKinds = new Set(Object.keys(systemAdapters));
|
|
326
|
-
// 'navigation' is engine-owned too (R8 item 7), but the scene load that
|
|
327
|
-
// populates it (below, `applySceneNavigation`) happens AFTER this
|
|
328
|
-
// snapshot — add it explicitly so the generic "strip every non-engine
|
|
329
|
-
// kind" step (hotReload/disposeGame) never mistakes a first-party
|
|
330
|
-
// navigation adapter for game-registered content and deletes it. (The
|
|
331
|
-
// adapter is still kept in sync with the CURRENT scene's NavMeshManager
|
|
332
|
-
// via the dedicated `clear navigation adapter` teardown step below, which
|
|
333
|
-
// runs independently of this snapshot.)
|
|
334
|
-
engineAdapterKinds.add('navigation');
|
|
335
|
-
// --- Scene / game setup ---
|
|
336
|
-
const engineSceneChildren = new Set(scene.children.slice());
|
|
337
|
-
// Tag engine-owned infra (particle BatchedRenderer, debug-draw + subtrees) so
|
|
338
|
-
// the editor's play-mode hierarchy skips them — they're not game entities.
|
|
339
|
-
for (const c of engineSceneChildren) {
|
|
340
|
-
c.traverse((n) => setUserData(n, 'engineInternal', true));
|
|
341
|
-
}
|
|
342
|
-
let currentCleanup = null;
|
|
343
|
-
let batchSystem = null;
|
|
344
|
-
// Apply scene-level render settings + transparent auto-batching after a scene
|
|
345
|
-
// loads (GPU host only). Gated on the resolved `environment.rendering` cascade
|
|
346
|
-
// (defaults preserve prior behavior when a scene omits `rendering`).
|
|
347
|
-
const applySceneRendering = (inst) => {
|
|
348
|
-
if (headless)
|
|
349
|
-
return;
|
|
350
|
-
const scope = inst.environment?.rendering;
|
|
351
|
-
const settings = resolveRenderSettings(scope);
|
|
352
|
-
// live renderer settings (shadows, resolution scale)
|
|
353
|
-
applyRendererSettings(renderer, scope);
|
|
354
|
-
// post-processing master switch: (re)build when the scene defines effects OR
|
|
355
|
-
// the master is off (to strip the default bloom pass down to a plain scene).
|
|
356
|
-
if (inst.environment?.postProcessing || !settings['postProcessing']) {
|
|
357
|
-
applyScenePostProcessing(composer, renderer, scene, camera, inst.environment);
|
|
358
|
-
}
|
|
359
|
-
// transparent batching: collapse static/mover meshes sharing a signature
|
|
360
|
-
if (settings['autoBatch']) {
|
|
361
|
-
batchSystem = new RenderBatchSystem(scene, settings);
|
|
362
|
-
batchSystem.build();
|
|
363
|
-
ctx.systems.add('preRender', () => batchSystem?.update());
|
|
364
|
-
if (import.meta.env?.DEV)
|
|
365
|
-
window.__vgaiBatch = batchSystem;
|
|
366
|
-
}
|
|
367
|
-
};
|
|
368
|
-
// Wire the (first-party) navigation system adapter to whichever
|
|
369
|
-
// NavMeshManager the CURRENT scene instance carries — reassigned on every
|
|
370
|
-
// scene load, and explicitly cleared (not just left stale) when the new
|
|
371
|
-
// scene has none, so `mounted.systems.navigation` never lingers pointing
|
|
372
|
-
// at a manager a later teardown step disposes (R8 item 7).
|
|
373
|
-
const applySceneNavigation = (inst) => {
|
|
374
|
-
if (inst.navMesh) {
|
|
375
|
-
systemAdapters.navigation = createNavigationAdapter(inst.navMesh);
|
|
376
|
-
}
|
|
377
|
-
else {
|
|
378
|
-
delete systemAdapters.navigation;
|
|
379
|
-
}
|
|
380
|
-
};
|
|
381
|
-
const loadFromData = async (data) => {
|
|
382
|
-
const inst = await loadSceneFromData(data, {
|
|
383
|
-
scene,
|
|
384
|
-
rapierWorld: ctx.rapierWorld,
|
|
385
|
-
rapier: ctx.rapier,
|
|
386
|
-
physics: ctx.physics,
|
|
387
|
-
audioListener: ctx.audio.listener,
|
|
388
|
-
...(componentRegistry ? { componentRegistry } : {}),
|
|
389
|
-
componentManager: ctx.components,
|
|
390
|
-
particleRenderer: ctx.particles.batchedRenderer,
|
|
391
|
-
...(headless ? {} : { renderer }),
|
|
392
|
-
});
|
|
393
|
-
applySceneRendering(inst);
|
|
394
|
-
applySceneNavigation(inst);
|
|
395
|
-
ctx.systems.add('postPhysics', (dt) => inst.update(dt));
|
|
396
|
-
return inst;
|
|
397
|
-
};
|
|
398
|
-
if (setup) {
|
|
399
|
-
if (headless)
|
|
400
|
-
throw new Error('VgaiSceneGameAdapter: setup-based games require a GPU host');
|
|
401
|
-
currentCleanup = await setup(ctx, editorPreview);
|
|
402
|
-
}
|
|
403
|
-
else if (scenePath) {
|
|
404
|
-
// #139: captured BEFORE load so adoptSceneCamera can tell whether a
|
|
405
|
-
// component (e.g. SceneCamera.init) already framed the camera.
|
|
406
|
-
const preLoadPose = captureCameraPose(camera);
|
|
407
|
-
const inst = await loadScene(scenePath, {
|
|
408
|
-
scene,
|
|
409
|
-
rapierWorld: ctx.rapierWorld,
|
|
410
|
-
rapier: ctx.rapier,
|
|
411
|
-
physics: ctx.physics,
|
|
412
|
-
audioListener: ctx.audio.listener,
|
|
413
|
-
...(componentRegistry ? { componentRegistry } : {}),
|
|
414
|
-
componentManager: ctx.components,
|
|
415
|
-
particleRenderer: ctx.particles.batchedRenderer,
|
|
416
|
-
...(headless ? {} : { renderer }),
|
|
417
|
-
});
|
|
418
|
-
applyEditorCamera(editorPreview, camera) || adoptSceneCamera(inst, camera, preLoadPose);
|
|
419
|
-
applySceneRendering(inst);
|
|
420
|
-
applySceneNavigation(inst);
|
|
421
|
-
ctx.systems.add('postPhysics', (dt) => inst.update(dt));
|
|
422
|
-
// A pre-baked navmesh (sibling .navmesh file — see scene-loader.ts) holds
|
|
423
|
-
// live recast-navigation WASM handles that leak unless destroyed
|
|
424
|
-
// explicitly; dispose it alongside the scene instance on teardown.
|
|
425
|
-
currentCleanup = {
|
|
426
|
-
dispose: () => {
|
|
427
|
-
inst.navMesh?.dispose(scene);
|
|
428
|
-
inst.dispose();
|
|
429
|
-
},
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
else if (sceneData) {
|
|
433
|
-
const preLoadPose = captureCameraPose(camera);
|
|
434
|
-
const inst = await loadFromData(sceneData);
|
|
435
|
-
applyEditorCamera(editorPreview, camera) || adoptSceneCamera(inst, camera, preLoadPose);
|
|
436
|
-
currentCleanup = {
|
|
437
|
-
dispose: () => {
|
|
438
|
-
inst.navMesh?.dispose(scene);
|
|
439
|
-
inst.dispose();
|
|
440
|
-
},
|
|
441
|
-
};
|
|
442
|
-
}
|
|
443
|
-
// Idempotency guard for disposeGame — see below. Declared here (not inside
|
|
444
|
-
// disposeGame) so hotReload can also refuse to run on an already-disposed
|
|
445
|
-
// adapter.
|
|
446
|
-
let disposed = false;
|
|
447
|
-
// Run one teardown step in isolation: a throwing step (e.g. a
|
|
448
|
-
// GameComponent's dispose() misbehaving, or a WASM free() panicking) must
|
|
449
|
-
// not abort the remaining steps — otherwise a single bad component leaks
|
|
450
|
-
// the Rapier world and skips input.dispose() with no way to retry (a
|
|
451
|
-
// second call is a no-op once `disposed` is set). Logs and continues.
|
|
452
|
-
const safeStep = (label, fn) => {
|
|
453
|
-
try {
|
|
454
|
-
fn();
|
|
455
|
-
}
|
|
456
|
-
catch (err) {
|
|
457
|
-
console.error(`VgaiSceneGameAdapter: teardown step "${label}" threw (continuing)`, err);
|
|
458
|
-
}
|
|
459
|
-
};
|
|
460
|
-
const disposeGame = () => {
|
|
461
|
-
// A second stop() must be a safe no-op — do NOT double-free the Rapier
|
|
462
|
-
// world/EventQueue (WASM handles panic/throw on a second free) or
|
|
463
|
-
// double-run teardown side effects.
|
|
464
|
-
if (disposed)
|
|
465
|
-
return;
|
|
466
|
-
disposed = true;
|
|
467
|
-
safeStep('batchSystem.teardown', () => {
|
|
468
|
-
batchSystem?.teardown(); // re-attach detached sources before scene teardown
|
|
469
|
-
batchSystem = null;
|
|
470
|
-
});
|
|
471
|
-
safeStep('currentCleanup.dispose', () => {
|
|
472
|
-
currentCleanup?.dispose();
|
|
473
|
-
currentCleanup = null;
|
|
474
|
-
});
|
|
475
|
-
// The scene instance's NavMeshManager (if any) was just disposed above
|
|
476
|
-
// (currentCleanup.dispose calls `inst.navMesh?.dispose(scene)`) — clear
|
|
477
|
-
// the wrapper too, or `mounted.systems.navigation` would keep pointing
|
|
478
|
-
// at a freed manager (R8 item 7). Unconditional: harmless if navigation
|
|
479
|
-
// was never set.
|
|
480
|
-
safeStep('clear navigation adapter', () => {
|
|
481
|
-
delete systemAdapters.navigation;
|
|
482
|
-
});
|
|
483
|
-
if (!headless) {
|
|
484
|
-
safeStep('removeEventListener(keydown)', () => window.removeEventListener('keydown', onDebugToggle));
|
|
485
|
-
}
|
|
486
|
-
// Components BEFORE the physics world is freed/bodies are removed: a
|
|
487
|
-
// GameComponent's dispose() may read `this.rigidBody`/`this.collider`
|
|
488
|
-
// (see game-component.ts) — freeing the world first would make those
|
|
489
|
-
// dangling WASM references. Isolated: a throwing component dispose must
|
|
490
|
-
// not prevent the world/eventQueue frees or input.dispose() below.
|
|
491
|
-
safeStep('components.clear', () => ctx.components.clear());
|
|
492
|
-
safeStep('remove rigid bodies', () => {
|
|
493
|
-
const handles = [];
|
|
494
|
-
physics.rapierWorld.forEachRigidBody((b) => handles.push(b.handle));
|
|
495
|
-
for (const h of handles) {
|
|
496
|
-
const b = physics.rapierWorld.getRigidBody(h);
|
|
497
|
-
if (b)
|
|
498
|
-
physics.rapierWorld.removeRigidBody(b);
|
|
499
|
-
}
|
|
500
|
-
});
|
|
501
|
-
safeStep('rapierWorld.free', () => physics.rapierWorld.free());
|
|
502
|
-
safeStep('eventQueue.free', () => physics.eventQueue.free()); // WASM handle — must be freed manually
|
|
503
|
-
safeStep('physicsRegistry.clear', () => physicsRegistry.clear());
|
|
504
|
-
safeStep('scene children dispose', () => {
|
|
505
|
-
for (const obj of [...scene.children]) {
|
|
506
|
-
scene.remove(obj);
|
|
507
|
-
obj.traverse((node) => {
|
|
508
|
-
if (node instanceof THREE.Mesh) {
|
|
509
|
-
if (!hasUserData(node, '__sharedGeometry'))
|
|
510
|
-
node.geometry?.dispose();
|
|
511
|
-
if (Array.isArray(node.material))
|
|
512
|
-
node.material.forEach((m) => {
|
|
513
|
-
m.dispose();
|
|
514
|
-
});
|
|
515
|
-
else
|
|
516
|
-
node.material?.dispose();
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
scene.fog = null;
|
|
521
|
-
scene.background = null;
|
|
522
|
-
scene.environment = null;
|
|
523
|
-
});
|
|
524
|
-
safeStep('clearAssetCaches', () => clearAssetCaches());
|
|
525
|
-
safeStep('debugDraw.clear', () => debugDraw.clear());
|
|
526
|
-
// R8 item 7 (C) — disposeGame (Stop) used to skip both of these, unlike
|
|
527
|
-
// hotReload (warm restart), which already ran them: a game lifecycle
|
|
528
|
-
// system registered via `ctx.systems.register(...)` never had its
|
|
529
|
-
// `dispose()` hook called on a full Stop, and a game-registered
|
|
530
|
-
// systemAdapters kind (e.g. a `setup`-registered 'networking') survived
|
|
531
|
-
// a Stop and would be visible on a STALE `mounted.systems` even though
|
|
532
|
-
// the game that owned it is gone. Same two steps, same relative
|
|
533
|
-
// ordering as hotReload (before the
|
|
534
|
-
// engine-owned audio/input teardown below, which hotReload doesn't
|
|
535
|
-
// touch at all since it warm-restarts rather than tearing engine
|
|
536
|
-
// subsystems down).
|
|
537
|
-
safeStep('systems.removeAllNonEngine', () => systems.removeAllNonEngine());
|
|
538
|
-
safeStep('strip game-registered systemAdapters', () => {
|
|
539
|
-
for (const kind of Object.keys(systemAdapters)) {
|
|
540
|
-
if (!engineAdapterKinds.has(kind))
|
|
541
|
-
delete systemAdapters[kind];
|
|
542
|
-
}
|
|
543
|
-
});
|
|
544
|
-
// Defect 2 fix: a full Stop means the whole GAME is going away (every
|
|
545
|
-
// world it mounted, plus any react-door registrations from its HUDs)
|
|
546
|
-
// — unlike hotReload below (a SINGLE mount warm-restarting), so this is
|
|
547
|
-
// the one call site that legitimately wants strip()'s global, no-id
|
|
548
|
-
// form rather than scoping to `this.id`.
|
|
549
|
-
safeStep('debugRegistry.strip', () => debugRegistry.strip());
|
|
550
|
-
if (!headless) {
|
|
551
|
-
safeStep('audio teardown', () => {
|
|
552
|
-
audio.masterGain.gain.value = 0;
|
|
553
|
-
audio.listener.context.suspend();
|
|
554
|
-
camera.remove(audio.listener);
|
|
555
|
-
composer.dispose();
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
safeStep('input.dispose', () => input.dispose());
|
|
559
|
-
safeStep('gpuTimer.dispose', () => gpuTimer?.dispose());
|
|
560
|
-
};
|
|
561
|
-
const hotReload = async (newSetup, newEditorPreview) => {
|
|
562
|
-
if (disposed) {
|
|
563
|
-
throw new Error('VgaiSceneGameAdapter: cannot hotReload after dispose()/stop()');
|
|
564
|
-
}
|
|
565
|
-
// Full parity with disposeGame for the parts a warm restart rebuilds:
|
|
566
|
-
// batch-render teardown, game cleanup, component batch teardown (in that
|
|
567
|
-
// ordering, BEFORE bodies are pulled from the world — see disposeGame),
|
|
568
|
-
// scene-UI dispose (React root unmount), and bulk system removal. Each
|
|
569
|
-
// step isolated the same way as disposeGame — one throwing step (e.g. a
|
|
570
|
-
// component dispose) must not abort the rest of the warm restart.
|
|
571
|
-
safeStep('batchSystem.teardown', () => {
|
|
572
|
-
batchSystem?.teardown(); // re-attach detached sources before scene teardown
|
|
573
|
-
batchSystem = null;
|
|
574
|
-
});
|
|
575
|
-
safeStep('currentCleanup.dispose', () => {
|
|
576
|
-
currentCleanup?.dispose();
|
|
577
|
-
currentCleanup = null;
|
|
578
|
-
});
|
|
579
|
-
// Same reasoning as disposeGame: the outgoing scene instance's
|
|
580
|
-
// NavMeshManager was just disposed above, and `hotReload`'s `newSetup`
|
|
581
|
-
// (below) never auto-wires a replacement (that only happens for THIS
|
|
582
|
-
// adapter's own scenePath/sceneData mount, once, at initial mount) — so
|
|
583
|
-
// clear the stale wrapper here. A `newSetup` that wants navigation may
|
|
584
|
-
// register its own via `ctx.registerSystemAdapter('navigation', ...)`.
|
|
585
|
-
safeStep('clear navigation adapter', () => {
|
|
586
|
-
delete systemAdapters.navigation;
|
|
587
|
-
});
|
|
588
|
-
safeStep('components.clear', () => ctx.components.clear());
|
|
589
|
-
safeStep('remove rigid bodies', () => {
|
|
590
|
-
const handles = [];
|
|
591
|
-
physics.rapierWorld.forEachRigidBody((b) => handles.push(b.handle));
|
|
592
|
-
for (const h of handles) {
|
|
593
|
-
const b = physics.rapierWorld.getRigidBody(h);
|
|
594
|
-
if (b)
|
|
595
|
-
physics.rapierWorld.removeRigidBody(b);
|
|
596
|
-
}
|
|
597
|
-
physicsRegistry.clear();
|
|
598
|
-
});
|
|
599
|
-
safeStep('scene children dispose', () => {
|
|
600
|
-
for (const obj of [...scene.children]) {
|
|
601
|
-
if (engineSceneChildren.has(obj))
|
|
602
|
-
continue;
|
|
603
|
-
scene.remove(obj);
|
|
604
|
-
obj.traverse((node) => {
|
|
605
|
-
if (node instanceof THREE.Mesh) {
|
|
606
|
-
if (!hasUserData(node, '__sharedGeometry'))
|
|
607
|
-
node.geometry?.dispose();
|
|
608
|
-
if (Array.isArray(node.material))
|
|
609
|
-
node.material.forEach((m) => {
|
|
610
|
-
m.dispose();
|
|
611
|
-
});
|
|
612
|
-
else
|
|
613
|
-
node.material?.dispose();
|
|
614
|
-
}
|
|
615
|
-
});
|
|
616
|
-
}
|
|
617
|
-
scene.fog = null;
|
|
618
|
-
scene.background = null;
|
|
619
|
-
scene.environment = null;
|
|
620
|
-
});
|
|
621
|
-
safeStep('debugDraw.clear', () => debugDraw.clear());
|
|
622
|
-
// Bulk-remove every system the outgoing game registered (this restart's
|
|
623
|
-
// predecessor) so warm restarts never accumulate duplicate systems —
|
|
624
|
-
// engine systems registered before mount()'s boundary mark are untouched.
|
|
625
|
-
safeStep('systems.removeAllNonEngine', () => systems.removeAllNonEngine());
|
|
626
|
-
// Strip every GAME-registered systemAdapters kind left by the outgoing
|
|
627
|
-
// game (including any override of a first-party kind) so the disposed
|
|
628
|
-
// game's networking/etc. adapter is never exposed to the next setup —
|
|
629
|
-
// see registerSystemAdapter's docstring in runtime/types.ts. ('navigation'
|
|
630
|
-
// is engine-kind and is NOT touched here — it's a first-party adapter now,
|
|
631
|
-
// kept in sync with the current scene's NavMeshManager by the dedicated
|
|
632
|
-
// `clear navigation adapter` step above instead.) The new setup below
|
|
633
|
-
// either re-registers a kind or it stays absent.
|
|
634
|
-
safeStep('strip game-registered systemAdapters', () => {
|
|
635
|
-
for (const kind of Object.keys(systemAdapters)) {
|
|
636
|
-
if (!engineAdapterKinds.has(kind))
|
|
637
|
-
delete systemAdapters[kind];
|
|
638
|
-
}
|
|
639
|
-
});
|
|
640
|
-
// Hot-reload re-seed (spec §3.1): the incoming game's setup (below)
|
|
641
|
-
// re-registers its providers/commands under the SAME worldId — strip()
|
|
642
|
-
// clears the outgoing game's registrations first so that re-seed is
|
|
643
|
-
// silent (no stale duplicate-name warning) rather than "replacing" a
|
|
644
|
-
// dead game's entries. Defect 2 fix: scoped to THIS mount's worldId
|
|
645
|
-
// (`this.id`) — a blind global strip() here wiped every OTHER live
|
|
646
|
-
// world's registrations on every warm restart of just this one, plus
|
|
647
|
-
// every react-door registration (whose `useEffect` cleanup never
|
|
648
|
-
// re-fires to restore them after someone else's strip).
|
|
649
|
-
safeStep('debugRegistry.strip', () => debugRegistry.strip(this.id));
|
|
650
|
-
currentCleanup = await newSetup(ctx, newEditorPreview);
|
|
651
|
-
};
|
|
652
|
-
return {
|
|
653
|
-
kind: 'threejs',
|
|
654
|
-
scene,
|
|
655
|
-
camera,
|
|
656
|
-
firstParty: true,
|
|
657
|
-
drivesOwnLoop: false,
|
|
658
|
-
update: (dt) => {
|
|
659
|
-
systems.run(dt);
|
|
660
|
-
postFrame();
|
|
661
|
-
},
|
|
662
|
-
resize: (w, h) => {
|
|
663
|
-
const safeWidth = Math.max(1, w);
|
|
664
|
-
const safeHeight = Math.max(1, h);
|
|
665
|
-
composer.setSize(safeWidth, safeHeight);
|
|
666
|
-
camera.aspect = safeWidth / safeHeight;
|
|
667
|
-
camera.updateProjectionMatrix();
|
|
668
|
-
},
|
|
669
|
-
dispose: disposeGame,
|
|
670
|
-
systems: systemAdapters,
|
|
671
|
-
ctx,
|
|
672
|
-
composer: headless ? null : composer,
|
|
673
|
-
hotReload,
|
|
674
|
-
frame: {
|
|
675
|
-
runPhase: (phase, dt) => systems.runPhase(phase, dt),
|
|
676
|
-
endFrame: postFrame,
|
|
677
|
-
},
|
|
678
|
-
};
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
// --- Camera precedence helpers (moved from create-runtime, unchanged) ---
|
|
682
|
-
function applyEditorCamera(editor, runtimeCamera) {
|
|
683
|
-
if (!editor?.viewportCamera)
|
|
684
|
-
return false;
|
|
685
|
-
runtimeCamera.position.fromArray(editor.viewportCamera.position);
|
|
686
|
-
runtimeCamera.quaternion.fromArray(editor.viewportCamera.quaternion);
|
|
687
|
-
return true;
|
|
688
|
-
}
|
|
689
|
-
export function captureCameraPose(camera) {
|
|
690
|
-
return { position: camera.position.clone(), quaternion: camera.quaternion.clone() };
|
|
691
|
-
}
|
|
692
|
-
export function adoptSceneCamera(sceneInstance, runtimeCamera, preLoadPose) {
|
|
693
|
-
const sceneCam = sceneInstance.cameras[0];
|
|
694
|
-
if (!sceneCam)
|
|
695
|
-
return false;
|
|
696
|
-
// #133 (blind run #4): `camera.type: 'orthographic'` builds a real
|
|
697
|
-
// OrthographicCamera in the scene graph (`createCamera`), but the RUNTIME
|
|
698
|
-
// renders through a hardcoded PerspectiveCamera — the authored projection
|
|
699
|
-
// silently never reached the screen. Until ortho support is ranked
|
|
700
|
-
// (implement-vs-reject, owner call on #133), say so loudly instead of
|
|
701
|
-
// letting a coplanar game render in unexplained perspective.
|
|
702
|
-
if (sceneCam.isOrthographicCamera) {
|
|
703
|
-
console.warn("adoptSceneCamera (#133): this scene's camera is ORTHOGRAPHIC, but the runtime camera is " +
|
|
704
|
-
'perspective-only — the orthographic projection is NOT applied (only the pose is). ' +
|
|
705
|
-
'Use type: "perspective" (a long-lens fake: far position + small fov) until #133 lands.');
|
|
706
|
-
}
|
|
707
|
-
// #139 (blind run #5): if a GameComponent already positioned/oriented the
|
|
708
|
-
// runtime camera during scene load (`SceneCamera.init`'s
|
|
709
|
-
// `ctx.camera.position.set` + `lookAt` is the blessed shape), the camera
|
|
710
|
-
// ENTITY's transform must not stomp it — an unauthored `transform.rotation`
|
|
711
|
-
// is identity ("stare down −Z"), which silently blanked an entire correct
|
|
712
|
-
// game while every state-based probe spec passed. Components win the pose;
|
|
713
|
-
// the entity still contributes the LENS (fov/near/far below), which
|
|
714
|
-
// `SceneCamera` never sets.
|
|
715
|
-
const componentFramedCamera = preLoadPose !== undefined &&
|
|
716
|
-
(!runtimeCamera.position.equals(preLoadPose.position) ||
|
|
717
|
-
!runtimeCamera.quaternion.equals(preLoadPose.quaternion));
|
|
718
|
-
const parent = sceneCam.parent;
|
|
719
|
-
if (parent && !componentFramedCamera) {
|
|
720
|
-
parent.updateMatrixWorld(true);
|
|
721
|
-
runtimeCamera.position.copy(parent.getWorldPosition(new THREE.Vector3()));
|
|
722
|
-
const worldQuat = parent.getWorldQuaternion(new THREE.Quaternion());
|
|
723
|
-
runtimeCamera.quaternion.copy(worldQuat);
|
|
724
|
-
// Identity orientation on an adopted scene camera is almost never intent
|
|
725
|
-
// (it means "look at the horizon down −Z", not "look at my scene") — the
|
|
726
|
-
// exact silent-blank-viewport footgun above. Adopt it anyway (authored
|
|
727
|
-
// data is truth) but say so loudly, with the two blessed remedies.
|
|
728
|
-
if (Math.abs(1 - Math.abs(worldQuat.w)) < 1e-6) {
|
|
729
|
-
console.warn('adoptSceneCamera (#139): the scene camera entity has no rotation — the runtime camera ' +
|
|
730
|
-
'will stare horizontally down −Z and may show nothing. Either attach the SceneCamera ' +
|
|
731
|
-
'component (position + lookAt, no quaternion math) or author transform.rotation on ' +
|
|
732
|
-
'the camera entity.');
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
if (sceneCam instanceof THREE.PerspectiveCamera) {
|
|
736
|
-
runtimeCamera.fov = sceneCam.fov;
|
|
737
|
-
runtimeCamera.near = sceneCam.near;
|
|
738
|
-
runtimeCamera.far = sceneCam.far;
|
|
739
|
-
runtimeCamera.updateProjectionMatrix();
|
|
740
|
-
}
|
|
741
|
-
return true;
|
|
742
|
-
}
|
|
743
|
-
/** Headless input stand-in — `InputManager` attaches `window` listeners in its
|
|
744
|
-
* constructor, which Node lacks. The scene-data path never reads input. */
|
|
745
|
-
function headlessInput() {
|
|
746
|
-
return {
|
|
747
|
-
poll: () => { },
|
|
748
|
-
endFrame: () => { },
|
|
749
|
-
dispose: () => { },
|
|
750
|
-
loadMap: async () => { },
|
|
751
|
-
isPressed: () => false,
|
|
752
|
-
getAxis: () => 0,
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
/** Headless audio stand-in (no Web Audio). Only the fields the loader/cleanup
|
|
756
|
-
* touch are present; setup-based games never mount headlessly. */
|
|
757
|
-
function headlessAudio() {
|
|
758
|
-
return {
|
|
759
|
-
listener: undefined,
|
|
760
|
-
masterGain: { gain: { value: 1 } },
|
|
761
|
-
};
|
|
762
|
-
}
|