@volter/game-editor 0.5.65
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/BUNDLED_NOTICES +11228 -0
- package/LICENSE +686 -0
- package/LICENSE-BLENDER +1409 -0
- package/LICENSE-MCP +21 -0
- package/NOTICE +21 -0
- package/catalog/entries/audio.json +14 -0
- package/catalog/entries/bake.json +36 -0
- package/catalog/entries/blender.json +17 -0
- package/catalog/entries/react-root.json +24 -0
- package/catalog/entries/reflections.json +29 -0
- package/catalog/entries/static-batch.json +25 -0
- package/catalog/project-source/LICENSE +37 -0
- package/catalog/project-source/src/contributions/bake.kind.ts +40 -0
- package/catalog/project-source/src/contributions/builder-document.tsx +65 -0
- package/catalog/project-source/src/contributions/builder-state.ts +27 -0
- package/catalog/project-source/src/contributions/builder-ui.tsx +61 -0
- package/catalog/project-source/src/contributions/module-source.ts +502 -0
- package/catalog/project-source/src/contributions/pages.finder.ts +61 -0
- package/catalog/project-source/src/lib/audio/sfx.ts +255 -0
- package/catalog/project-source/src/lib/bake/asset-seed.ts +128 -0
- package/catalog/project-source/src/lib/bake/bake-schema.ts +65 -0
- package/catalog/project-source/src/lib/bake/clip-layering.ts +203 -0
- package/catalog/project-source/src/lib/bake/gltf-bake.ts +657 -0
- package/catalog/project-source/src/lib/bake/mesh-slice.ts +157 -0
- package/catalog/project-source/src/lib/bake/node-image.ts +463 -0
- package/catalog/project-source/src/lib/bake/object3d-bake.ts +121 -0
- package/catalog/project-source/src/lib/bake/object3d-lifecycle.ts +15 -0
- package/catalog/project-source/src/lib/bake/object3d-source.ts +8 -0
- package/catalog/project-source/src/lib/bake/params.ts +75 -0
- package/catalog/project-source/src/lib/bake/rest-relative-animation.ts +217 -0
- package/catalog/project-source/src/lib/bake/use-model.ts +95 -0
- package/catalog/project-source/src/lib/react-root/index.ts +20 -0
- package/catalog/project-source/src/lib/react-root/react-root-adapter.tsx +57 -0
- package/catalog/project-source/src/lib/reflections/ReflectionProbe.tsx +201 -0
- package/catalog/project-source/src/lib/reflections/index.ts +19 -0
- package/catalog/project-source/src/lib/reflections/probe-controller.ts +75 -0
- package/catalog/project-source/src/lib/reflections/reflection-probe-registry.ts +402 -0
- package/catalog/project-source/src/lib/reflections/volume-reflection-material.ts +416 -0
- package/catalog/project-source/src/lib/static-batch/Frozen.tsx +91 -0
- package/catalog/project-source/src/lib/static-batch/freeze.ts +579 -0
- package/catalog/project-source/src/lib/static-batch/index.ts +44 -0
- package/catalog/project-source/src/lib/static-batch/mutation-watch.ts +149 -0
- package/catalog/project-source/src/lib/static-batch/shadow-cache.ts +171 -0
- package/catalog/project-source/src/tools/bake-module.tool.ts +139 -0
- package/catalog/project-source/src/tools/bake-preview.tool.ts +475 -0
- package/dist/.vite/manifest.json +8304 -0
- package/dist/assets/AssetBudgetPanel-J9--TZPU.js +23 -0
- package/dist/assets/AudioViewer-CR7333fe.js +1 -0
- package/dist/assets/BVHLoader-6bQIXhMX.js +1 -0
- package/dist/assets/BufferGeometryUtils-Nz37EVXf.js +1 -0
- package/dist/assets/CCDIKSolver-CD7vLpsK.js +1 -0
- package/dist/assets/CSS3DRenderer-CL7ABLVK.js +1 -0
- package/dist/assets/CanvasSceneViewport-Bpi6gVTC.js +1 -0
- package/dist/assets/ColladaLoader-aVOPIsCh.js +3 -0
- package/dist/assets/ColorInput-DQBNrW-K.js +1 -0
- package/dist/assets/ConvexGeometry-CAzXlPVG.js +1 -0
- package/dist/assets/ConvexHull-BINCESFp.js +1 -0
- package/dist/assets/CopyShader-BzTUYzf6.js +24 -0
- package/dist/assets/DecalGeometry-160KRdfg.js +1 -0
- package/dist/assets/EXRLoader-Cdans_oJ.js +1 -0
- package/dist/assets/EffectComposer-DQxfsXBZ.js +1 -0
- package/dist/assets/EntityModelDocument-Ccvw66N9.js +1 -0
- package/dist/assets/EnvironmentAssetDocument-Dg-Qq6O6.js +1 -0
- package/dist/assets/FBXLoader-B4MoUtAn.js +1 -0
- package/dist/assets/Fbo-Dz-Soul3.js +1 -0
- package/dist/assets/FontLoader-CvGoVI5a.js +2 -0
- package/dist/assets/GLTFExporter-HgrCle4L.js +1 -0
- package/dist/assets/GameplaySessionTimeline-B52W3FVZ.js +1 -0
- package/dist/assets/Gltf-UHVWKz65.js +2 -0
- package/dist/assets/HDRLoader-THU88oVD.js +5 -0
- package/dist/assets/ImageViewer-Tn7s_MnW.js +1 -0
- package/dist/assets/InspectorCanvasPreview-CEr_Kxna.js +1 -0
- package/dist/assets/InspectorObjectPreview-CVejvLRg.js +1 -0
- package/dist/assets/JsonAssetDocument-C7VGcLhu.js +3 -0
- package/dist/assets/LineSegments2-CsOpKSiM.js +370 -0
- package/dist/assets/MTLLoader-_Xzd4_0p.js +2 -0
- package/dist/assets/MarchingCubes-Bsp4wrzd.js +1 -0
- package/dist/assets/MeshBVH-BiDHDcu-.js +1 -0
- package/dist/assets/ModelAssetDocument-F5GACirk.js +1 -0
- package/dist/assets/NonThreeAuthoringBootstrap-C3woOMxX.js +1 -0
- package/dist/assets/OBJLoader-BhIC6Hwo.js +5 -0
- package/dist/assets/Object3DDocumentViewport-DB7T0NTl.js +2 -0
- package/dist/assets/Object3DPreview-DL8oi7Xs.js +2 -0
- package/dist/assets/OnlineAssetDetail-C6z9RvYK.js +2 -0
- package/dist/assets/OrbitControls-CM3bPray.js +1 -0
- package/dist/assets/OrbitControls-DLpayAaK.js +1 -0
- package/dist/assets/OrthographicCamera-bQozawrh.js +1 -0
- package/dist/assets/PLYLoader-DYQqs5Ik.js +2 -0
- package/dist/assets/PerspectiveCamera-CQ2lh01o.js +1 -0
- package/dist/assets/PlayBar-BR-Vg3Jb.js +2 -0
- package/dist/assets/RGBELoader-BgBcQv8j.js +1 -0
- package/dist/assets/RectAreaLightUniformsLib-CMMoWfll.js +1 -0
- package/dist/assets/RenderPass-DPrn-Uky.js +1 -0
- package/dist/assets/ResolutionPicker-C67vs1F3.js +1 -0
- package/dist/assets/RootSelectionOverlay-BZPlxmXU.js +1 -0
- package/dist/assets/RoundedBox-BDGBg6QZ.js +1 -0
- package/dist/assets/RoundedBoxGeometry-CyUuYPfW.js +1 -0
- package/dist/assets/STLLoader-Dyv3lsxY.js +1 -0
- package/dist/assets/SelectionBox-D_75KrNW.js +1 -0
- package/dist/assets/ShaderPass-QYRpPuFJ.js +1 -0
- package/dist/assets/ShadowEditor-DkImwu1Y.js +1 -0
- package/dist/assets/SimplifyModifier-C8ayvRzd.js +1 -0
- package/dist/assets/SkeletonUtils-Cps8GOC6.js +1 -0
- package/dist/assets/Sky-CQKCgYDs.js +154 -0
- package/dist/assets/SourceAssetViewer-2SWQoUut.js +12 -0
- package/dist/assets/StageHost-BN-IoTef.js +2 -0
- package/dist/assets/StoryPreviewMount-DjyxRCXu.js +1 -0
- package/dist/assets/TDSLoader-D_T8XJ81.js +1 -0
- package/dist/assets/TextGeometry-DOWAEUV0.js +1 -0
- package/dist/assets/ThreeBoardDocument-CVncZyIq.js +2 -0
- package/dist/assets/ThreeIsolationSceneContent-C8C8whSF.js +1 -0
- package/dist/assets/ToolObject3DPreview-BRoDWe4Q.js +1 -0
- package/dist/assets/TrackballControls-DfznuQTh.js +1 -0
- package/dist/assets/TransientHint-BB1fwrvK.js +1 -0
- package/dist/assets/UnrealBloomPass-CR-cS_K5.js +83 -0
- package/dist/assets/VideoViewer-C6kocgIU.js +1 -0
- package/dist/assets/_commonjsHelpers-D6-XlEtG.js +1 -0
- package/dist/assets/active-ingest-CT6jSGhr.js +3 -0
- package/dist/assets/adapter-surface-Y37Nzcyw.js +1 -0
- package/dist/assets/after-paint-CB4bz1-e.js +1 -0
- package/dist/assets/agx-base-srgb-BjWZJgrZ.lut +0 -0
- package/dist/assets/agx-look-medium-high-contrast-D5F_ob1L.lut +0 -0
- package/dist/assets/agx-look-punchy-dxsnycNs.lut +0 -0
- package/dist/assets/animation-clock-CnjZqfJp.js +1 -0
- package/dist/assets/asset-budget-asset.menu-Di3KiQCd.js +1 -0
- package/dist/assets/asset-budget.action-DCzzcuTh.js +1 -0
- package/dist/assets/asset-budget.document-BWU8wnVW.js +1 -0
- package/dist/assets/asset-budget.menu-BGZpT_31.js +1 -0
- package/dist/assets/asset-editor-persistence-BBaONOJt.js +1 -0
- package/dist/assets/asset-loaders-BOy5Ss8k.js +2 -0
- package/dist/assets/asset-parse-error-BHMwBRU3.js +3 -0
- package/dist/assets/assets-BuSoGjBX.js +1 -0
- package/dist/assets/audio-meter-CyiToeUW.js +1 -0
- package/dist/assets/audio-unlock.service-CfUgUQVy.js +1 -0
- package/dist/assets/audio.utility-C6K6jem8.js +1 -0
- package/dist/assets/authoring-CgcOFhGS.js +1 -0
- package/dist/assets/autoplay.service-BZBGNSvt.js +1 -0
- package/dist/assets/axe-LkjAB6Lv.js +30 -0
- package/dist/assets/babylon-authoring-adapter-CL02gWDn.js +1 -0
- package/dist/assets/binding-Bmxqznjk.js +1 -0
- package/dist/assets/binding-identity-DcTpbvyg.js +1 -0
- package/dist/assets/binding-resolver-Dsh-6Vor.js +2 -0
- package/dist/assets/blender-emscripten-engine-9ZIRYNhe.js +2 -0
- package/dist/assets/blender-node-editor.document-iIDkB9sI.js +1 -0
- package/dist/assets/blender-properties-tab-C5CyPydi.js +3 -0
- package/dist/assets/blender-runtime-host-BpBwGv7r.js +4 -0
- package/dist/assets/blender-runtime-skin-DyQ9B6CR.js +7140 -0
- package/dist/assets/blender-runtime.document-lIYhhPtv.js +8 -0
- package/dist/assets/blender-timeline.document-77fx96N7.js +1 -0
- package/dist/assets/blender-uv-editor.document-fsT7B4gV.js +1 -0
- package/dist/assets/blender-version.status-o6dBm3n6.js +1 -0
- package/dist/assets/blender-wali-engine-wTOcrOMC.js +2 -0
- package/dist/assets/blender.command-BtJeWk-A.js +1 -0
- package/dist/assets/blender.keymap-GAQgeklK.js +1 -0
- package/dist/assets/blender.status-ujwGU6dU.js +1 -0
- package/dist/assets/blender.style-Dcem5f_T.js +1 -0
- package/dist/assets/board-guides-DziKSTss.js +1 -0
- package/dist/assets/body-marks-h_xDxiDE.js +1 -0
- package/dist/assets/bridge.command-o5gDNEwa.js +3 -0
- package/dist/assets/browserAll-DeWblVez.js +1 -0
- package/dist/assets/build-profiles.document-kW8iw8Xj.js +2 -0
- package/dist/assets/build-progress.status-BNRLytg2.js +1 -0
- package/dist/assets/build-session-C_sg3CEn.js +9 -0
- package/dist/assets/build.action-lYjTLb7K.js +1 -0
- package/dist/assets/build.command-DIGgUPU_.js +1 -0
- package/dist/assets/build.header-CKajx5U3.js +1 -0
- package/dist/assets/build.menu-BdU0QXny.js +1 -0
- package/dist/assets/build.service-CbBAyeu3.js +1 -0
- package/dist/assets/bus-mixer-CGfWDP3C.js +1 -0
- package/dist/assets/camera-KEsKvOL7.js +1 -0
- package/dist/assets/camera-runtime.inspector-B7unX4g1.js +1 -0
- package/dist/assets/canvas-entry-runtime-SfBxaR9M.js +2 -0
- package/dist/assets/capability-coverage-Czas4C18.js +7 -0
- package/dist/assets/chrome-trace-YZHMz60-.js +1 -0
- package/dist/assets/client-DNXj_opT.js +25 -0
- package/dist/assets/clip-planes-CnAI6DZn.js +1 -0
- package/dist/assets/collaboration-presence-DLoZ7EA3.js +1 -0
- package/dist/assets/collider-Bw0mXlsW.js +1 -0
- package/dist/assets/collider-dimensions-9xoFADXN.js +1 -0
- package/dist/assets/collision-system-DpNUJRJ3.js +1 -0
- package/dist/assets/command-results-CUQD49AB.js +1 -0
- package/dist/assets/component-board-registry-DrIa2csL.js +1 -0
- package/dist/assets/component-board.service-DCwcUssB.js +2 -0
- package/dist/assets/component-board.service-DidCyM4O.js +2 -0
- package/dist/assets/component-verbs.command-7xzfjGMZ.js +1 -0
- package/dist/assets/component-verbs.service-Bv9jId3q.js +1 -0
- package/dist/assets/config-CEZk921y.js +6 -0
- package/dist/assets/configurations-DTBMdaTL.js +1 -0
- package/dist/assets/connection.status-BifnQdOs.js +1 -0
- package/dist/assets/console-bridge-CHcb-xk5.js +1 -0
- package/dist/assets/constraint-De8f1Uiq.js +1 -0
- package/dist/assets/constraints.inspector-B9U9Yj-u.js +1 -0
- package/dist/assets/countdown-timer-CUm74dom.js +1 -0
- package/dist/assets/coverage.service-VTX5Mcsx.js +3 -0
- package/dist/assets/crash-null-boundary-v3a0uEgw.js +1 -0
- package/dist/assets/create-runtime-CVCc1BDx.js +1 -0
- package/dist/assets/curve-7Q79VgU4.js +1 -0
- package/dist/assets/data-asset-4hjS642k.js +5 -0
- package/dist/assets/data-check-core-CQEjuFyt.js +1 -0
- package/dist/assets/data-ref-CQI28C0D.js +1 -0
- package/dist/assets/debug-bridge-CCohG-d-.js +1 -0
- package/dist/assets/debug-registry-Dgvitx8M.js +1 -0
- package/dist/assets/defaults-DKiBJCPN.js +1 -0
- package/dist/assets/deferred-commands-CEMmvL47.js +1 -0
- package/dist/assets/deferred-ingest-play-DCJi_Pgu.js +2 -0
- package/dist/assets/design-time-layers-wYgOTgni.js +1 -0
- package/dist/assets/design-time-mount-registry-DUpXCg1U.js +1 -0
- package/dist/assets/design-time-mount.service-BzY21e1F.js +2 -0
- package/dist/assets/design-time-react-mount-DM9WLrF2.js +1 -0
- package/dist/assets/dev-build-gDYrq68M.js +1 -0
- package/dist/assets/directional-shadow-fit-BVkOKAv2.js +1 -0
- package/dist/assets/document-preview-three-Kbg2GCLm.js +1 -0
- package/dist/assets/dom-authoring-adapter-CY8C7f4T.js +1 -0
- package/dist/assets/draco3d-BBUTcNkz.js +1 -0
- package/dist/assets/draco_decoder-DsQ12WqX.wasm +0 -0
- package/dist/assets/draco_encoder-2Tcju8Ns.wasm +0 -0
- package/dist/assets/edit-mode-audio.service-Bzetwd5B.js +1 -0
- package/dist/assets/edit-mode-authoring-B47TfLqu.js +1 -0
- package/dist/assets/edit-mode-networking.service-YCX6RRb_.js +1 -0
- package/dist/assets/editor-api-BoJIcyZG.js +1 -0
- package/dist/assets/editor-port-C_FeBdeV.js +1 -0
- package/dist/assets/editor-presentation-activity-C7SNSmTd.js +1 -0
- package/dist/assets/entry-adjudication-Cq8Yeb74.js +1 -0
- package/dist/assets/environment-capture-7himRh2L.js +1 -0
- package/dist/assets/esbuild-BHljloGq.wasm +0 -0
- package/dist/assets/events-156d8d12.esm-ErOhDXXB.js +36 -0
- package/dist/assets/extend-B-eOccUm.js +36 -0
- package/dist/assets/extends-CF3RwP-h.js +1 -0
- package/dist/assets/eyedropper-session-bjPXnfeX.js +1 -0
- package/dist/assets/fflate.module-DPuTF8aG.js +6 -0
- package/dist/assets/filmic-srgb-Ct35FIH6.lut +0 -0
- package/dist/assets/first-party-audio-system-DxnGJOER.js +1 -0
- package/dist/assets/first-party-navigation-system-CL5Bquub.js +1 -0
- package/dist/assets/fork-menu-BoVyw2Wu.js +1 -0
- package/dist/assets/frame-debugger-store-D1Mf_5up.js +1 -0
- package/dist/assets/frame-delta-D2nsw_Ht.js +1 -0
- package/dist/assets/frame-pacing-D5acoOzO.js +1 -0
- package/dist/assets/frame-selector-cache-cCeUbcjG.js +1 -0
- package/dist/assets/game-DHOZVb-7.js +1 -0
- package/dist/assets/game-contract-seams-a5YXejOu.js +1 -0
- package/dist/assets/game-css-scope-transform-Eng4wS8E.js +33 -0
- package/dist/assets/game-document.service-DbRfx2V0.js +1 -0
- package/dist/assets/game-eval.command-D-7Dxbj_.js +2 -0
- package/dist/assets/game-input-seams-CIQdetRw.js +1 -0
- package/dist/assets/game-loop-CZvXlY00.js +1 -0
- package/dist/assets/game-module-access-B2mFxv-i.js +1 -0
- package/dist/assets/game.layout-CBASrvQu.js +1 -0
- package/dist/assets/gameplay-export-BoKXm51x.js +1 -0
- package/dist/assets/gameplay-replay-e5umMlXv.js +1 -0
- package/dist/assets/gameplay-rng-trap-CTNhm-UW.js +3 -0
- package/dist/assets/gameplay.command-DxcVYX6F.js +1 -0
- package/dist/assets/generation-DhwCUHPf.css +1 -0
- package/dist/assets/generation-jobs-BQrXbGp_.js +1 -0
- package/dist/assets/generation.service-CDIgObuw.js +1 -0
- package/dist/assets/generations-DzUogZsM.js +1 -0
- package/dist/assets/generations.status-CgOUBCum.js +1 -0
- package/dist/assets/hierarchy-marks-BLPfSIym.js +1 -0
- package/dist/assets/host-pointer-DbGSCjE9.js +1 -0
- package/dist/assets/hosted-asset-materialization-CiIvWkGU.js +2 -0
- package/dist/assets/ibl-override-material-BlmCxFKq.js +6 -0
- package/dist/assets/index-96FBF1Oj.js +1 -0
- package/dist/assets/index-BAWkB0dv.js +1 -0
- package/dist/assets/index-BDnS2b6S.js +1 -0
- package/dist/assets/index-BHp07vN0.js +2 -0
- package/dist/assets/index-BMxv2MNV.js +1 -0
- package/dist/assets/index-BP6wv2A0.js +5 -0
- package/dist/assets/index-BcCBqgM_.js +952 -0
- package/dist/assets/index-Bge9JUr6.js +1 -0
- package/dist/assets/index-BjTCPEQ7.js +134 -0
- package/dist/assets/index-BncK9THk.js +1 -0
- package/dist/assets/index-CJbYy-CF.js +3 -0
- package/dist/assets/index-CVCb_ImQ.js +1 -0
- package/dist/assets/index-CZd9o7Lu.js +1 -0
- package/dist/assets/index-CanA16PU.js +2 -0
- package/dist/assets/index-CinJrH5C.js +9 -0
- package/dist/assets/index-CtzuWnCS.js +1 -0
- package/dist/assets/index-D2fNXpHa.css +1 -0
- package/dist/assets/index-DUpHH6JR.js +3120 -0
- package/dist/assets/index-DUqP1RMl.js +1 -0
- package/dist/assets/index-D_NuPfjr.js +9 -0
- package/dist/assets/index-Da9JhEvW.js +25 -0
- package/dist/assets/index-DgapqSPi.js +7 -0
- package/dist/assets/index-FUuS4qwW.js +562 -0
- package/dist/assets/index-GIL7oGEO.js +4894 -0
- package/dist/assets/index-IEjydI9d.js +1 -0
- package/dist/assets/index-OrYXPk3Z.js +487 -0
- package/dist/assets/index-V1R-e5Bd.js +1 -0
- package/dist/assets/index-bQE2NA0D.js +1 -0
- package/dist/assets/index-gHZae-lw.js +13 -0
- package/dist/assets/index-mjWQmGhM.js +1 -0
- package/dist/assets/index-nmcBqr7Y.js +1 -0
- package/dist/assets/inference-diagnostics-Dhmtfbq_.js +1 -0
- package/dist/assets/ingest-BbYMC2vQ.js +1 -0
- package/dist/assets/ingest-boot-viewport-D5rI_Kk_.js +1 -0
- package/dist/assets/ingest-siblings-Bop2kqVl.js +1 -0
- package/dist/assets/ingest-source-persistence-C_6Hiyra.js +1 -0
- package/dist/assets/ingest.service-BTDnQfM1.js +1 -0
- package/dist/assets/input-manager-DH_hGW6d.js +1 -0
- package/dist/assets/input-router-BNQvtIqw.js +1 -0
- package/dist/assets/inspect-BZfi3mmo.js +1 -0
- package/dist/assets/inspection-CObLhnrs.js +1 -0
- package/dist/assets/instance-fork-actions-D3sRzS3K.js +1 -0
- package/dist/assets/instances.command-D6UkZNO8.js +1 -0
- package/dist/assets/instruments-CKR02Y8I.js +1 -0
- package/dist/assets/json-history-resource-BbxllWfV.js +1 -0
- package/dist/assets/jsx-runtime-DPjLkJKQ.js +9 -0
- package/dist/assets/light-D-_wsKTq.js +1 -0
- package/dist/assets/light-camera-factory-CWbbe9gI.js +1 -0
- package/dist/assets/lil-gui.module.min-BF55BEwA.js +10 -0
- package/dist/assets/live-behaviors-Bxq49Maz.js +1 -0
- package/dist/assets/live-gesture-lock-DJbrjOqf.js +1 -0
- package/dist/assets/loader-CaF_I7Yt.js +1 -0
- package/dist/assets/logger-Dqis-7W1.js +1 -0
- package/dist/assets/loop-gate-report-N52EWFGD.js +1 -0
- package/dist/assets/matcap-texture-CVfalpWT.js +1 -0
- package/dist/assets/material-CpAdjDxn.js +1 -0
- package/dist/assets/material-factory-Bz6h__6g.js +1 -0
- package/dist/assets/mesh-B3WPtNKO.js +1 -0
- package/dist/assets/mesh-shadow-CZnXrw_l.js +1 -0
- package/dist/assets/mikktspace.module-DO88SLib.js +1 -0
- package/dist/assets/model-asset-sections-CFvvihfx.css +1 -0
- package/dist/assets/model-asset-sections.service-CHhFS3ZX.js +1 -0
- package/dist/assets/model.layout-BJUEQYUI.js +1 -0
- package/dist/assets/models.finder-G2jQgIRu.js +1 -0
- package/dist/assets/module-mode-DVBLT9d-.js +2 -0
- package/dist/assets/mount-canvas-ingest-root-DDuAWf_C.js +2 -0
- package/dist/assets/mount-dom-ingest-root-D_EiBgpn.js +2 -0
- package/dist/assets/mount-game-6t9cKNo4.js +1 -0
- package/dist/assets/mount-ingest-root-glv2SSWf.js +2 -0
- package/dist/assets/mount-manifest-CGVxhmAw.js +1 -0
- package/dist/assets/mount-readiness-Ds0HvvLH.js +4 -0
- package/dist/assets/mount-three-ingest-root-hrUt9VVU.js +1 -0
- package/dist/assets/mounted-authoring-Dmg5xmhP.js +1 -0
- package/dist/assets/mounted-story-viewport-source-DjP6RA9U.js +1 -0
- package/dist/assets/native-debug-module-CWicoSGD.js +1 -0
- package/dist/assets/native-entry-surface-BE8LJNdu.js +1 -0
- package/dist/assets/navigation-CIiCx-SM.js +1 -0
- package/dist/assets/navmesh-workflow-store-Cmnm57TB.js +1 -0
- package/dist/assets/navmesh.menu-CAKiH8PW.js +1 -0
- package/dist/assets/navmesh.service-jgDWlgj1.js +1 -0
- package/dist/assets/network.utility-CEu5nHf7.js +1 -0
- package/dist/assets/object-marks-DwvIEBOK.js +1 -0
- package/dist/assets/object3d-authoring-subject-CH5sI2oP.js +1 -0
- package/dist/assets/output-DK8waum9.js +195 -0
- package/dist/assets/particles-Y626p22p.js +1 -0
- package/dist/assets/particles-factory-DnLOHXT8.js +1 -0
- package/dist/assets/pasteboard-materialize-BqSS4QzV.js +20 -0
- package/dist/assets/pasteboard.action-DU3UHtJG.js +2 -0
- package/dist/assets/performance-profiler-D_Jey87L.js +1 -0
- package/dist/assets/physics-registry-B2Jkp8e6.js +1 -0
- package/dist/assets/physics-registry-CUB9cT9p.js +1 -0
- package/dist/assets/pixi-authoring-adapter-CjibysC3.js +1 -0
- package/dist/assets/pixi-live-write-target-DuWydlWb.js +1 -0
- package/dist/assets/pixi-primitive-DlWbUPN9.js +1 -0
- package/dist/assets/pixi-react-root-factory-DYsznYRQ.js +1 -0
- package/dist/assets/pixi-story-model-DNkfnWUV.js +1 -0
- package/dist/assets/pixi-transform-channels-VjdohT11.js +1 -0
- package/dist/assets/play-mode-BFU2PCkG.js +22 -0
- package/dist/assets/play.command-BpqqLqkq.js +2 -0
- package/dist/assets/playtest-BXIL1JEF.js +1 -0
- package/dist/assets/pose-guard-6Osb2cFu.js +1 -0
- package/dist/assets/presentation-BPP5pXeQ.js +1 -0
- package/dist/assets/product-DFhyARJj.js +1 -0
- package/dist/assets/profiler.action-CaXJDp3t.js +1 -0
- package/dist/assets/profiler.menu-BIMF6Bi4.js +1 -0
- package/dist/assets/profiler.utility-BExw9wBO.js +1 -0
- package/dist/assets/project-authoring-session-Bnt6icLr.js +2 -0
- package/dist/assets/project-provenance-BoP3nrle.js +1 -0
- package/dist/assets/prompt-labels-DSMdM2_B.js +1 -0
- package/dist/assets/properties-bone-constraints.inspector-ByT6p7S-.js +1 -0
- package/dist/assets/properties-bone.inspector-z4qJwKO5.js +1 -0
- package/dist/assets/properties-collection.inspector-D0_3ijWU.js +1 -0
- package/dist/assets/properties-constraints.inspector-CESzjuls.js +1 -0
- package/dist/assets/properties-data.inspector-hG8Wgyzb.js +1 -0
- package/dist/assets/properties-material.inspector-CzY0JCQ6.js +1 -0
- package/dist/assets/properties-modifiers.inspector-3dDhwf7g.js +1 -0
- package/dist/assets/properties-object.inspector-CiarfxkT.js +1 -0
- package/dist/assets/properties-output.inspector-DKJxmKSD.js +1 -0
- package/dist/assets/properties-particles.inspector-CCEdYWGm.js +1 -0
- package/dist/assets/properties-physics.inspector-B2c0KUyA.js +1 -0
- package/dist/assets/properties-render.inspector-Bcm0HLRW.js +1 -0
- package/dist/assets/properties-scene.inspector-PIM_eTb_.js +1 -0
- package/dist/assets/properties-texture.inspector-CgFlnyr8.js +1 -0
- package/dist/assets/properties-view-layer.inspector-DGjF_Aqo.js +1 -0
- package/dist/assets/properties-world.inspector-CrMvaRvB.js +1 -0
- package/dist/assets/r3f-design-session-D-4yyDO9.js +2 -0
- package/dist/assets/r3f-physics-binding-BBo8oma9.js +1 -0
- package/dist/assets/r3f-root-factory-z9llD1OU.js +1 -0
- package/dist/assets/r3f-source-authoring-adapter-w6Bc60K-.js +13 -0
- package/dist/assets/rapier-physics-adapter-CaZqWLu0.js +1 -0
- package/dist/assets/rapier-physics-bridge-CMoeVo3Y.js +1 -0
- package/dist/assets/react-18-By2b4xR9.js +1 -0
- package/dist/assets/react-inspector.service-B_neRnSK.js +1 -0
- package/dist/assets/react-root-CEz5NTck.js +1 -0
- package/dist/assets/react-story-board-BDDwiE2H.js +1 -0
- package/dist/assets/react-three-fiber.esm-CycrbDlA.js +1 -0
- package/dist/assets/react-three-rapier.esm-CEfKpvxT.js +1 -0
- package/dist/assets/react-world-authoring-adapter-DmrwM3py.js +1 -0
- package/dist/assets/realm-services-CobQsq_X.js +1 -0
- package/dist/assets/rebind-controller-Dtq19Vb3.js +1 -0
- package/dist/assets/recast-navigation.wasm-compat-Dsoa_MD-.js +1 -0
- package/dist/assets/reflection-probe-Don-M3Fj.js +1 -0
- package/dist/assets/reflection-probe-capture.inspector-CmFUoJCx.js +1 -0
- package/dist/assets/register-render-vitals-BiZk29b2.js +1 -0
- package/dist/assets/registry-02YZjMNp.js +1 -0
- package/dist/assets/relative-path-guard-GiM7Lsz8.js +1 -0
- package/dist/assets/render-audio-control-vMRlePWb.js +1 -0
- package/dist/assets/render-batch-system-0vq7p0VC.js +1 -0
- package/dist/assets/render-census-BrQX_CXv.js +1 -0
- package/dist/assets/render-control-Df3yTiyr.js +1 -0
- package/dist/assets/render-env-D2IV2x5k.js +1 -0
- package/dist/assets/render-features-CPQ_e568.js +1 -0
- package/dist/assets/render-seed-DF4JHy7P.js +1 -0
- package/dist/assets/render-settings-Bw4W9SYF.js +1 -0
- package/dist/assets/render-vitals-BZ5HtvMi.js +1 -0
- package/dist/assets/renderer-config-BqG4O8i9.js +1 -0
- package/dist/assets/resolve-three-SZE_WWUM.js +702 -0
- package/dist/assets/root-seam-contract-Z0VWX3Bk.js +1 -0
- package/dist/assets/rrweb-Cd2ifIRP.js +142 -0
- package/dist/assets/run-ticks-settled-C4ksViyA.js +1 -0
- package/dist/assets/runtime-inspection-l2iFQSsg.js +1 -0
- package/dist/assets/scene-capture-BQKzU0NT.js +1 -0
- package/dist/assets/scene-capture-CGYF-Viw.js +1 -0
- package/dist/assets/scene-document.service-qkDjUrlP.js +2 -0
- package/dist/assets/scene-framing-Cat0GtyJ.js +1 -0
- package/dist/assets/scene-index-B6BZOHMk.js +1 -0
- package/dist/assets/scene-query-C7_N-TpI.js +1 -0
- package/dist/assets/schema-kl9-2B_J.js +1 -0
- package/dist/assets/sculpt.layout-zJF55yCR.js +1 -0
- package/dist/assets/seeded-random-i3mtgBKZ.js +1 -0
- package/dist/assets/session-CZ5JPg-z.js +4877 -0
- package/dist/assets/setup-audio-S8GQF91f.js +1 -0
- package/dist/assets/setup-particles-GCXlnkj_.js +1 -0
- package/dist/assets/setup-physics-BeZ7-LKD.js +1 -0
- package/dist/assets/setup-renderer-DVXaSGin.js +1587 -0
- package/dist/assets/shading.layout-DULYZV6M.js +1 -0
- package/dist/assets/sim-clock-CLflx7kg.js +1 -0
- package/dist/assets/sky-precompute-worker-ChN7J87v.js +1 -0
- package/dist/assets/soft-particle-depth-DGvfQDi1.js +1 -0
- package/dist/assets/source-object3d-authoring-adapter-B-L6Ha6f.js +1 -0
- package/dist/assets/source-persistence-backend-C-aR-B_Y.js +1 -0
- package/dist/assets/spark-renderer-lifecycle-ynWESJcv.js +1 -0
- package/dist/assets/spark.module-4pXQoz5d.js +12120 -0
- package/dist/assets/stage-invalidation-DBg3C3Ta.js +1 -0
- package/dist/assets/stage-keyboard-n-5kKH-m.js +1 -0
- package/dist/assets/stage-overlay-set-B9zp2sLB.js +1 -0
- package/dist/assets/stage-presence-markers-DiGI6A45.js +1 -0
- package/dist/assets/standard-viewport-dressing-CzjAe_0A.js +7 -0
- package/dist/assets/state-bridge-DLP1jLRW.js +1 -0
- package/dist/assets/state-watch.action-BOvQR2qt.js +1 -0
- package/dist/assets/state-watch.menu-CNLvDeeY.js +1 -0
- package/dist/assets/state-watch.utility-Bg1tTTQU.js +1 -0
- package/dist/assets/static-batch-advisor-B13QEH7d.js +1 -0
- package/dist/assets/stats.module-BL02l9NC.js +1 -0
- package/dist/assets/story-arg-descriptors-Ek86ExX7.js +1 -0
- package/dist/assets/story-capture-_gC8dXV-.js +1 -0
- package/dist/assets/story-documents--TDLaPeL.js +3 -0
- package/dist/assets/story-documents.service-BiS_YbNQ.js +1 -0
- package/dist/assets/story-documents.service-CxOPYJ2j.js +1 -0
- package/dist/assets/story-media-presence-BHzk2IV5.js +1 -0
- package/dist/assets/story-mount-turn-DFRTj5hi.js +1 -0
- package/dist/assets/story-pixi-preview-BUrOJZXS.js +1 -0
- package/dist/assets/story-presentation-j2AVN-mK.js +1 -0
- package/dist/assets/story-three-preview-BHEDZzcl.js +2 -0
- package/dist/assets/structural-ids-Dc-7rEwi.js +1 -0
- package/dist/assets/structural-signature-0w-i_ats.js +1 -0
- package/dist/assets/surface-content-Dg9Kkazf.js +1 -0
- package/dist/assets/surface-state-DaxyruCj.js +3 -0
- package/dist/assets/system-adapters-rIC8FSGP.js +1 -0
- package/dist/assets/system-runner-DkOjxEBt.js +1 -0
- package/dist/assets/system-slot-E2mEdiih.js +1 -0
- package/dist/assets/team-playtest.service-DqOinFVA.js +1 -0
- package/dist/assets/texture.layout-DASpHVht.js +1 -0
- package/dist/assets/three-CDSueJyJ.js +1 -0
- package/dist/assets/three-authoring-adapter-CmSQ3Vui.js +1 -0
- package/dist/assets/three-authoring.service-iuHLwtf1.js +2 -0
- package/dist/assets/three-ingest-runtime-QzDYk6tU.js +1 -0
- package/dist/assets/three-projection-core-BmKMZ-nf.js +1 -0
- package/dist/assets/three-viewport-presentation-QBQpSdMh.js +1 -0
- package/dist/assets/three.module-D396a9Mn.js +3840 -0
- package/dist/assets/three.quarks.esm-B1C61jGo.js +1039 -0
- package/dist/assets/tools-B_NJsk05.js +1 -0
- package/dist/assets/transform-writer-BhBBTx33.js +1 -0
- package/dist/assets/transport.header-B-6HQlU2.js +1 -0
- package/dist/assets/trigger-volume-BNK2XzPL.js +1 -0
- package/dist/assets/tuples-CIQ4Bn1U.js +1 -0
- package/dist/assets/tween.module-DciWpAG6.js +1 -0
- package/dist/assets/ui-board-document-Bwtt--xp.js +2 -0
- package/dist/assets/unexported-game-trap-Dm1JYKHy.js +2 -0
- package/dist/assets/unmanaged-root-detector-B8CpbkSN.js +2 -0
- package/dist/assets/upstream-pin-BdgRH6ID.js +1 -0
- package/dist/assets/use-data-Dzq-MytE.js +1 -0
- package/dist/assets/use-live-actor-state-DErbWQWF.js +1 -0
- package/dist/assets/use-selection-DbR73-xd.js +1 -0
- package/dist/assets/user-data-BB2Of6Ht.js +1 -0
- package/dist/assets/utility-view-state-BHypxA33.js +1 -0
- package/dist/assets/uv-editing.layout-BEKHxmHw.js +1 -0
- package/dist/assets/vgai-shared-fontawesome-CU65D4Ij.js +1 -0
- package/dist/assets/vgai-shared-jsx-dev-runtime-DFDKL7fx.js +1 -0
- package/dist/assets/vgai-shared-jsx-runtime-DIqBpTut.js +1 -0
- package/dist/assets/vgai-shared-react-BT7rMc2H.js +1 -0
- package/dist/assets/vgai-shared-react-dom-DFajMqMT.js +1 -0
- package/dist/assets/vgai-shared-react-dom-client-S0ozfl6_.js +1 -0
- package/dist/assets/vgai-shared-three-Bc5PvpLM.js +1 -0
- package/dist/assets/viewport-pick-context-DkawXbEi.js +1 -0
- package/dist/assets/viewport-root-presentation-CWsE56K6.js +1 -0
- package/dist/assets/viewport-shading-BuA88e_A.js +1 -0
- package/dist/assets/viewport-shading-boundary-B_-_gABg.js +82 -0
- package/dist/assets/viewport-surface-status-B3om4Kcf.js +1 -0
- package/dist/assets/vision_bundle-DX0dWqEa.js +15 -0
- package/dist/assets/voxel-surface-DtcsSWRL.js +1 -0
- package/dist/assets/wav-encode-D31zWF6O.js +1 -0
- package/dist/assets/webgl-frame-capture-FlF9zQmW.js +1 -0
- package/dist/assets/webgl-gpu-timer-D3YX7RaD.js +1 -0
- package/dist/assets/webworkerAll-CM2o_dnz.js +1 -0
- package/dist/assets/worker-UrMcrc5_.js +2 -0
- package/dist/assets/world-documents-147tiFZe.js +1 -0
- package/dist/assets/world-root-stage-binding-vwTrtBz6.js +1 -0
- package/dist/assets/world-state-BWG-IcOd.js +1 -0
- package/dist/assets/writer-B-KovzkA.js +5 -0
- package/dist/assets/xstate-animation-binding-Brd0NST6.js +1 -0
- package/dist/assets/xstate-animation-meta-Q3u9zh_m.js +1 -0
- package/dist/assets/xstate-behavior.action-B8UluFBK.js +1 -0
- package/dist/assets/xstate-behavior.document-CKAsE45I.js +1 -0
- package/dist/assets/xstate-behavior.inspector-vJJyuifc.js +1 -0
- package/dist/assets/xstate-behavior.menu-BXbPICIh.js +1 -0
- package/dist/assets/xstate-inspection-BsZv8LS9.js +1 -0
- package/dist/vgai-shared-react.json +10 -0
- package/dist/vgai-shared-three.json +3 -0
- package/dist-node/cli.js +9320 -0
- package/dist-node/create.js +3239 -0
- package/package.json +91 -0
- package/presets.mjs +2 -0
- package/src/contributions.d.ts +4 -0
- package/src/index.ts +38 -0
- package/starter/cube.blend +0 -0
- package/starter/cube.py +81 -0
- package/template/.agents/references/project-manual.md +341 -0
- package/template/.agents/skills/editor/SKILL.md +53 -0
- package/template/.agents/skills/editor/agents/openai.yaml +4 -0
- package/template/.agents/skills/editor/references/editor-control.md +363 -0
- package/template/.agents/skills/vgai-3d-models/SKILL.md +64 -0
- package/template/.agents/skills/vgai-ingest-existing-game/SKILL.md +112 -0
- package/template/.agents/skills/vgai-threejs-authoring/SKILL.md +347 -0
- package/template/.agents/skills/vgai-threejs-authoring/agents/openai.yaml +4 -0
- package/template/.agents/skills/vgai-threejs-authoring/references/helper-catalog.md +65 -0
- package/template/.claude/skills/editor/SKILL.md +53 -0
- package/template/.claude/skills/editor/agents/openai.yaml +4 -0
- package/template/.claude/skills/editor/references/editor-control.md +363 -0
- package/template/.claude/skills/vgai-3d-models/SKILL.md +64 -0
- package/template/.claude/skills/vgai-ingest-existing-game/SKILL.md +112 -0
- package/template/.claude/skills/vgai-threejs-authoring/SKILL.md +347 -0
- package/template/.claude/skills/vgai-threejs-authoring/agents/openai.yaml +4 -0
- package/template/.claude/skills/vgai-threejs-authoring/references/helper-catalog.md +65 -0
- package/template/.github/copilot-instructions.md +6 -0
- package/template/.github/skills/editor/SKILL.md +53 -0
- package/template/.github/skills/editor/agents/openai.yaml +4 -0
- package/template/.github/skills/editor/references/editor-control.md +363 -0
- package/template/.github/skills/vgai-3d-models/SKILL.md +64 -0
- package/template/.github/skills/vgai-ingest-existing-game/SKILL.md +112 -0
- package/template/.github/skills/vgai-threejs-authoring/SKILL.md +347 -0
- package/template/.github/skills/vgai-threejs-authoring/agents/openai.yaml +4 -0
- package/template/.github/skills/vgai-threejs-authoring/references/helper-catalog.md +65 -0
- package/template/.mcp.json +12 -0
- package/template/.vgai/assets.json +1 -0
- package/template/.vgai/provenance.json +4 -0
- package/template/.volter/tracker/validation/.preset.base.mts +178 -0
- package/template/.volter/tracker/validation/preset.mts +186 -0
- package/template/.volter/tracker/visualizer/.extension.base.tsx +14 -0
- package/template/.volter/tracker/visualizer/extension.tsx +14 -0
- package/template/.volter/tracker-config.json +17 -0
- package/template/AGENTS.md +176 -0
- package/template/CLAUDE.md +1 -0
- package/template/DEVLOG.md +20 -0
- package/template/IDIOMS.md +118 -0
- package/template/LICENSE +30 -0
- package/template/README.md +83 -0
- package/template/ROADMAP.md +20 -0
- package/template/asset-manifest.json +3 -0
- package/template/check-idioms.ts +1533 -0
- package/template/index.html +18 -0
- package/template/manifest-entry-modules-plugin.ts +53 -0
- package/template/package.json +62 -0
- package/template/public/jsm/libs/basis/basis_transcoder.js +19 -0
- package/template/public/jsm/libs/basis/basis_transcoder.wasm +0 -0
- package/template/public/jsm/libs/draco/gltf/draco_decoder.js +33 -0
- package/template/public/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
- package/template/public/jsm/libs/draco/gltf/draco_encoder.js +33 -0
- package/template/public/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
- package/template/public/shaders/daylight-sky.frag.glsl +15 -0
- package/template/public/shaders/daylight-sky.vert.glsl +7 -0
- package/template/scripts/patch-drei-stats-gl.mjs +35 -0
- package/template/server/colyseus-setup.ts +111 -0
- package/template/server/loopback.ts +76 -0
- package/template/server/main.ts +78 -0
- package/template/server/rooms/arena-room.ts +488 -0
- package/template/server/rooms/game-room.ts +274 -0
- package/template/server/rooms.ts +15 -0
- package/template/server/tsconfig.json +19 -0
- package/template/src/bot/QaTester.tsx +35 -0
- package/template/src/bot/behaviors.ts +203 -0
- package/template/src/bot/bot-station.ts +192 -0
- package/template/src/bot/tester-run.ts +238 -0
- package/template/src/bot/tester-station.ts +193 -0
- package/template/src/components/environment/DaylightSky.tsx +54 -0
- package/template/src/components/environment/Ground.tsx +129 -0
- package/template/src/components/environment/SceneAtmosphere.tsx +14 -0
- package/template/src/components/environment/SoftGroundShadow.tsx +62 -0
- package/template/src/components/environment/SunShadowFit.tsx +141 -0
- package/template/src/contributions/README.md +98 -0
- package/template/src/contributions/analytics.analytics.tsx +26 -0
- package/template/src/contributions/data.document.tsx +35 -0
- package/template/src/contributions/pages.finder.ts +61 -0
- package/template/src/contributions/tester.inspector.tsx +64 -0
- package/template/src/contributions/use-game-modules.ts +80 -0
- package/template/src/data/README.md +17 -0
- package/template/src/input.ts +97 -0
- package/template/src/lib/audio/capability.json +4 -0
- package/template/src/lib/audio/sfx.ts +255 -0
- package/template/src/lib/react-root/capability.json +4 -0
- package/template/src/lib/react-root/index.ts +20 -0
- package/template/src/lib/react-root/react-root-adapter.tsx +57 -0
- package/template/src/lib/reflections/ReflectionProbe.tsx +201 -0
- package/template/src/lib/reflections/capability.json +4 -0
- package/template/src/lib/reflections/index.ts +19 -0
- package/template/src/lib/reflections/probe-controller.ts +75 -0
- package/template/src/lib/reflections/reflection-probe-registry.ts +402 -0
- package/template/src/lib/reflections/volume-reflection-material.ts +416 -0
- package/template/src/lib/static-batch/Frozen.tsx +91 -0
- package/template/src/lib/static-batch/capability.json +4 -0
- package/template/src/lib/static-batch/freeze.ts +579 -0
- package/template/src/lib/static-batch/index.ts +44 -0
- package/template/src/lib/static-batch/mutation-watch.ts +149 -0
- package/template/src/lib/static-batch/shadow-cache.ts +171 -0
- package/template/src/main.ts +63 -0
- package/template/src/manifest-entry-modules.d.ts +3 -0
- package/template/src/prefabs/HeroBox.stories.tsx +23 -0
- package/template/src/prefabs/HeroBox.tsx +35 -0
- package/template/src/scenes/MainScene.tsx +77 -0
- package/template/src/world.tsx +87 -0
- package/template/tsconfig.json +35 -0
- package/template/tsconfig.node.json +32 -0
- package/template/tsconfig.tools.json +22 -0
- package/template/validate-asset-content.ts +27 -0
- package/template/validate-assets.ts +60 -0
- package/template/validate-manifest.ts +55 -0
- package/template/vgai.adapter.ts +76 -0
- package/template/vgai.project.json +24 -0
- package/template/vite.config.ts +247 -0
- package/template-dotfiles/gitignore +63 -0
- package/workbench/src/media/game-cover.css +83 -0
- package/workbench/src/product.contribution.ts +188 -0
- package/workbench/src/vgaiGameSkew.ts +276 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GameRoom — multiplayer arena with collectible orbs.
|
|
3
|
+
*
|
|
4
|
+
* Uses @colyseus/schema state sync (the idiomatic Colyseus pattern).
|
|
5
|
+
* Server mutates Schema state directly; Colyseus encodes deltas and
|
|
6
|
+
* syncs them to all clients automatically.
|
|
7
|
+
*
|
|
8
|
+
* Messages (client → server only):
|
|
9
|
+
* position { x, y, z } — client movement input
|
|
10
|
+
* __vgai:debugCommand { name, args, requestId } — a `locus: 'server'`
|
|
11
|
+
* debug command's client leg (the "Multiplayer locus" note,
|
|
12
|
+
* build plan Task 4.2); see
|
|
13
|
+
* `DEBUG_COMMANDS`/`onCreate` below.
|
|
14
|
+
*
|
|
15
|
+
* Everything else (players, orbs, scores) is synchronized via Schema
|
|
16
|
+
* state: new joiners receive the full state automatically, and ongoing
|
|
17
|
+
* changes are delta-encoded at the patch rate (~20 Hz).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { Room, type Client } from 'colyseus';
|
|
21
|
+
import { Schema, MapSchema, type } from '@colyseus/schema';
|
|
22
|
+
|
|
23
|
+
// --- Constants ---
|
|
24
|
+
|
|
25
|
+
const COLORS = [0xff6644, 0x44ff99, 0x4499ff, 0xffee44, 0xff44bb, 0x44ffee, 0xaa44ff, 0xff4488];
|
|
26
|
+
const NAMES = ['Coral', 'Mint', 'Sky', 'Gold', 'Rose', 'Teal', 'Violet', 'Crimson'];
|
|
27
|
+
const ARENA_HALF = 7.5;
|
|
28
|
+
const SPAWN_RADIUS = 5;
|
|
29
|
+
const MAX_ORBS = 6;
|
|
30
|
+
const COLLECT_RADIUS_SQ = 1.0;
|
|
31
|
+
const ORB_RESPAWN_MS = 3_000;
|
|
32
|
+
const SIM_INTERVAL_MS = 50;
|
|
33
|
+
/** How much room a joining player gets from the nearest orb — twice the
|
|
34
|
+
* collect radius, so a spawn never sits on the edge of a pickup either. */
|
|
35
|
+
const SPAWN_CLEARANCE_SQ = COLLECT_RADIUS_SQ * 4;
|
|
36
|
+
/** Evenly spaced candidate angles `chooseSpawnPosition` scans. Enough that a
|
|
37
|
+
* clear angle always falls inside the widest gap the orbs can leave. */
|
|
38
|
+
const SPAWN_ANGLE_SAMPLES = 64;
|
|
39
|
+
|
|
40
|
+
// --- Schema definitions ---
|
|
41
|
+
|
|
42
|
+
class PlayerSchema extends Schema {
|
|
43
|
+
@type('string') sessionId = '';
|
|
44
|
+
@type('string') name = '';
|
|
45
|
+
@type('uint32') color = 0;
|
|
46
|
+
@type('float32') x = 0;
|
|
47
|
+
@type('float32') y = 0;
|
|
48
|
+
@type('float32') z = 0;
|
|
49
|
+
@type('uint16') score = 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
class OrbSchema extends Schema {
|
|
53
|
+
@type('string') id = '';
|
|
54
|
+
@type('float32') x = 0;
|
|
55
|
+
@type('float32') z = 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
class GameState extends Schema {
|
|
59
|
+
@type({ map: PlayerSchema }) players = new MapSchema<PlayerSchema>();
|
|
60
|
+
@type({ map: OrbSchema }) orbs = new MapSchema<OrbSchema>();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// --- Helpers ---
|
|
64
|
+
|
|
65
|
+
let nextOrbId = 0;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The `locus: 'server'` debug-command table (Task 4.2) — one worked example,
|
|
69
|
+
* `give-score`, demonstrating the same declared-fixture rule as client-side
|
|
70
|
+
* debug commands: mutates the AUTHORITATIVE
|
|
71
|
+
* (server) copy of state, never client prediction. Gated by
|
|
72
|
+
* `allowDebugCommands` — see `onCreate` — so a production `npm run server`
|
|
73
|
+
* boot never accepts these unless explicitly opted in.
|
|
74
|
+
*/
|
|
75
|
+
const DEBUG_COMMANDS: Record<string, (room: GameRoom, client: Client, args: unknown[]) => unknown> =
|
|
76
|
+
{
|
|
77
|
+
'give-score': (room, client, args) => {
|
|
78
|
+
const amount = typeof args[0] === 'number' ? args[0] : 1;
|
|
79
|
+
const player = room.state.players.get(client.sessionId);
|
|
80
|
+
if (!player) throw new Error(`give-score: no player for session "${client.sessionId}"`);
|
|
81
|
+
player.score += amount;
|
|
82
|
+
return { score: player.score };
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Pick a spawn point on the spawn circle that is CLEAR of every orb.
|
|
88
|
+
*
|
|
89
|
+
* A raw random angle can drop a joining player straight onto a pickup, and
|
|
90
|
+
* the very next simulation tick collects it: a free point nobody's rules
|
|
91
|
+
* awarded, and — because the roll happens at join — a room whose score is
|
|
92
|
+
* non-deterministic from tick zero. That is exactly what made
|
|
93
|
+
* `tests/logic/room.test.ts` fail intermittently, and no assertion tolerance
|
|
94
|
+
* would have fixed it, because the defect is here.
|
|
95
|
+
*
|
|
96
|
+
* The spawn stays random: `angleOffset` is a random angle, and this only
|
|
97
|
+
* rejects the angles that land on a pickup. Scanning a fixed number of evenly
|
|
98
|
+
* spaced candidates (rather than re-rolling until clear) makes the search
|
|
99
|
+
* terminate in bounded time; if every candidate were blocked — impossible
|
|
100
|
+
* with the current constants, but the code must not pretend otherwise — the
|
|
101
|
+
* roomiest one wins.
|
|
102
|
+
*
|
|
103
|
+
* Pure, and exported, so the clearance is provable in `tests/logic/` without
|
|
104
|
+
* booting a server.
|
|
105
|
+
*/
|
|
106
|
+
export function chooseSpawnPosition(
|
|
107
|
+
orbs: Iterable<{ x: number; z: number }>,
|
|
108
|
+
angleOffset: number = Math.random() * Math.PI * 2,
|
|
109
|
+
): { x: number; y: number; z: number } {
|
|
110
|
+
const placed = [...orbs];
|
|
111
|
+
let best = { x: SPAWN_RADIUS, y: 0, z: 0 };
|
|
112
|
+
let bestClearanceSq = -1;
|
|
113
|
+
for (let i = 0; i < SPAWN_ANGLE_SAMPLES; i++) {
|
|
114
|
+
const angle = angleOffset + (i * Math.PI * 2) / SPAWN_ANGLE_SAMPLES;
|
|
115
|
+
const candidate = {
|
|
116
|
+
x: Math.cos(angle) * SPAWN_RADIUS,
|
|
117
|
+
y: 0,
|
|
118
|
+
z: Math.sin(angle) * SPAWN_RADIUS,
|
|
119
|
+
};
|
|
120
|
+
let clearanceSq = Number.POSITIVE_INFINITY;
|
|
121
|
+
for (const orb of placed) {
|
|
122
|
+
const dx = candidate.x - orb.x;
|
|
123
|
+
const dz = candidate.z - orb.z;
|
|
124
|
+
clearanceSq = Math.min(clearanceSq, dx * dx + dz * dz);
|
|
125
|
+
}
|
|
126
|
+
if (clearanceSq >= SPAWN_CLEARANCE_SQ) return candidate;
|
|
127
|
+
if (clearanceSq > bestClearanceSq) {
|
|
128
|
+
bestClearanceSq = clearanceSq;
|
|
129
|
+
best = candidate;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return best;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function randomOrbPosition(): { x: number; z: number } {
|
|
136
|
+
return {
|
|
137
|
+
x: (Math.random() - 0.5) * ARENA_HALF * 1.6,
|
|
138
|
+
z: (Math.random() - 0.5) * ARENA_HALF * 1.6,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// --- Room ---
|
|
143
|
+
|
|
144
|
+
export class GameRoom extends Room {
|
|
145
|
+
state = new GameState();
|
|
146
|
+
patchRate = 50;
|
|
147
|
+
|
|
148
|
+
private colorIndex = 0;
|
|
149
|
+
// Orb respawns are counted in simulation ticks, not `this.clock` timers, so
|
|
150
|
+
// the room's timing is driven entirely by `setSimulationInterval` and is
|
|
151
|
+
// reproducible from the tick count alone.
|
|
152
|
+
private orbRespawnTicks: number[] = [];
|
|
153
|
+
|
|
154
|
+
onCreate(options?: { allowDebugCommands?: boolean }) {
|
|
155
|
+
// Off by default (FROZEN DECISION: env-var OR room-option) — the loopback harness/
|
|
156
|
+
// the loopback harness (`../loopback.ts`) opt in via the room option; a
|
|
157
|
+
// plain `npm run server` boot never accepts debug commands unless
|
|
158
|
+
// VGAI_ALLOW_DEBUG_COMMANDS is set in its environment.
|
|
159
|
+
const debugCommandsAllowed =
|
|
160
|
+
options?.allowDebugCommands === true || Boolean(process.env['VGAI_ALLOW_DEBUG_COMMANDS']);
|
|
161
|
+
|
|
162
|
+
// Handle client messages
|
|
163
|
+
this.onMessage('position', (client, position: { x: number; y: number; z: number }) => {
|
|
164
|
+
const player = this.state.players.get(client.sessionId);
|
|
165
|
+
if (player) {
|
|
166
|
+
player.x = Math.max(-ARENA_HALF, Math.min(ARENA_HALF, position.x));
|
|
167
|
+
player.y = position.y;
|
|
168
|
+
player.z = Math.max(-ARENA_HALF, Math.min(ARENA_HALF, position.z));
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
this.onMessage(
|
|
173
|
+
'__vgai:debugCommand',
|
|
174
|
+
(client, message: { name: string; args?: unknown[]; requestId: string }) => {
|
|
175
|
+
if (!debugCommandsAllowed) {
|
|
176
|
+
client.send('__vgai:debugCommandResult', {
|
|
177
|
+
requestId: message.requestId,
|
|
178
|
+
ok: false,
|
|
179
|
+
error: 'debug commands disabled',
|
|
180
|
+
});
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const handler = DEBUG_COMMANDS[message.name];
|
|
184
|
+
if (!handler) {
|
|
185
|
+
client.send('__vgai:debugCommandResult', {
|
|
186
|
+
requestId: message.requestId,
|
|
187
|
+
ok: false,
|
|
188
|
+
error: `debug: no server command registered under "${message.name}"`,
|
|
189
|
+
});
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
const result = handler(this, client, message.args ?? []);
|
|
194
|
+
client.send('__vgai:debugCommandResult', {
|
|
195
|
+
requestId: message.requestId,
|
|
196
|
+
ok: true,
|
|
197
|
+
result,
|
|
198
|
+
});
|
|
199
|
+
} catch (err) {
|
|
200
|
+
client.send('__vgai:debugCommandResult', {
|
|
201
|
+
requestId: message.requestId,
|
|
202
|
+
ok: false,
|
|
203
|
+
error: err instanceof Error ? err.message : String(err),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
// Spawn initial orbs
|
|
210
|
+
for (let i = 0; i < MAX_ORBS; i++) {
|
|
211
|
+
this.spawnOrb();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Server game loop at 20 Hz — check orb collection, tick pending respawns
|
|
215
|
+
this.setSimulationInterval(() => {
|
|
216
|
+
for (let i = this.orbRespawnTicks.length - 1; i >= 0; i--) {
|
|
217
|
+
if (--this.orbRespawnTicks[i]! <= 0) {
|
|
218
|
+
this.orbRespawnTicks.splice(i, 1);
|
|
219
|
+
this.spawnOrb();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
for (const [orbId, orb] of this.state.orbs) {
|
|
224
|
+
for (const player of this.state.players.values()) {
|
|
225
|
+
const dx = player.x - orb.x;
|
|
226
|
+
const dz = player.z - orb.z;
|
|
227
|
+
if (dx * dx + dz * dz < COLLECT_RADIUS_SQ) {
|
|
228
|
+
player.score++;
|
|
229
|
+
this.state.orbs.delete(orbId);
|
|
230
|
+
this.orbRespawnTicks.push(Math.ceil(ORB_RESPAWN_MS / SIM_INTERVAL_MS));
|
|
231
|
+
break; // one collection per orb per tick
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}, SIM_INTERVAL_MS);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
onJoin(client: Client, options?: { color?: number; name?: string }) {
|
|
239
|
+
const idx = this.colorIndex % COLORS.length;
|
|
240
|
+
const color = (options?.color != null) ? options.color : COLORS[idx]!;
|
|
241
|
+
const name = options?.name ?? NAMES[idx]!;
|
|
242
|
+
this.colorIndex++;
|
|
243
|
+
|
|
244
|
+
const pos = chooseSpawnPosition(this.state.orbs.values());
|
|
245
|
+
const player = new PlayerSchema();
|
|
246
|
+
player.sessionId = client.sessionId;
|
|
247
|
+
player.name = name;
|
|
248
|
+
player.color = color;
|
|
249
|
+
player.x = pos.x;
|
|
250
|
+
player.y = pos.y;
|
|
251
|
+
player.z = pos.z;
|
|
252
|
+
player.score = 0;
|
|
253
|
+
|
|
254
|
+
this.state.players.set(client.sessionId, player);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
onLeave(client: Client, _code?: number) {
|
|
258
|
+
this.state.players.delete(client.sessionId);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
onDispose() {
|
|
262
|
+
// Room cleanup
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
private spawnOrb() {
|
|
266
|
+
const id = `orb_${nextOrbId++}`;
|
|
267
|
+
const pos = randomOrbPosition();
|
|
268
|
+
const orb = new OrbSchema();
|
|
269
|
+
orb.id = id;
|
|
270
|
+
orb.x = pos.x;
|
|
271
|
+
orb.z = pos.z;
|
|
272
|
+
this.state.orbs.set(id, orb);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Room registry — defines all available Colyseus rooms, passed to
|
|
3
|
+
* `startColyseus({ rooms, ... })` (colyseus-setup.ts) to call server.define()
|
|
4
|
+
* for each. Imported by the e2e showcase harness
|
|
5
|
+
* (packages/editor/e2e/helpers/colyseus.ts) and the unit-test in-process
|
|
6
|
+
* loopback server (packages/editor/test/helpers/colyseus-loopback.ts).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { ArenaRoom } from './rooms/arena-room.js';
|
|
10
|
+
import { GameRoom } from './rooms/game-room.js';
|
|
11
|
+
|
|
12
|
+
export const rooms = [
|
|
13
|
+
{ name: 'game_room', handler: GameRoom, matchBy: ['vgaiPlaytest'] },
|
|
14
|
+
{ name: 'arena_room', handler: ArenaRoom, matchBy: ['vgaiPlaytest'] },
|
|
15
|
+
];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2021",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"useDefineForClassFields": false,
|
|
9
|
+
|
|
10
|
+
"strict": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"verbatimModuleSyntax": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"isolatedModules": true,
|
|
15
|
+
"skipLibCheck": true,
|
|
16
|
+
"noEmit": true
|
|
17
|
+
},
|
|
18
|
+
"include": ["."]
|
|
19
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The QA tester's HANDS ON THE FRAME — the one piece of the playtesting loop
|
|
3
|
+
* that must live in the world tree, because acting through input each sim
|
|
4
|
+
* tick IS frame work. Everything else about the tester (its doors, its run
|
|
5
|
+
* state, its repertoire) is plain application code in
|
|
6
|
+
* `src/bot/tester-station.ts`, reached directly as a running module by the
|
|
7
|
+
* Tester contribution and `vgai eval`.
|
|
8
|
+
*
|
|
9
|
+
* The tester's hands run in the INPUT phase — before everything. Fiber sorts
|
|
10
|
+
* `useFrame` callbacks ascending, and this world's own behavior hooks sit at
|
|
11
|
+
* 0 (game logic / animation) or -1 (a movement solve landing before
|
|
12
|
+
* `<Physics>` steps). A virtual action must already be written when the first
|
|
13
|
+
* of those reads it, so the tester runs below the lot of them. Negative by
|
|
14
|
+
* necessity, never positive: a positive priority takes over rendering and
|
|
15
|
+
* blacks out the world (check-idioms W8).
|
|
16
|
+
*
|
|
17
|
+
* Cost when idle: one no-op frame callback. Nothing rendered.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { useFrame } from '@react-three/fiber';
|
|
21
|
+
import { useEffect } from 'react';
|
|
22
|
+
import { stepTester, stopTesterForUnmount } from './tester-station';
|
|
23
|
+
|
|
24
|
+
const TESTER_FRAME_PRIORITY = -100;
|
|
25
|
+
|
|
26
|
+
export function QaTester() {
|
|
27
|
+
// A run cannot outlive the frame that steps it: stopping Play unmounts this
|
|
28
|
+
// component, and the cleanup ends any run still seated so the next session
|
|
29
|
+
// starts clean.
|
|
30
|
+
useEffect(() => stopTesterForUnmount, []);
|
|
31
|
+
useFrame((_, dt) => {
|
|
32
|
+
stepTester(dt);
|
|
33
|
+
}, TESTER_FRAME_PRIORITY);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The QA TESTER's REPERTOIRE — everything this game's bot knows how to do,
|
|
3
|
+
* as ordinary game-owned code.
|
|
4
|
+
*
|
|
5
|
+
* The tester is the person holding the controller: it plays THIS game, at sim
|
|
6
|
+
* speed, through the real input pipeline. What it can be asked to do is
|
|
7
|
+
* game-specific by nature, so this file is a plain `Record<string, behavior>`.
|
|
8
|
+
* There is deliberately NO behavior tree, utility system,
|
|
9
|
+
* goal stack, or standardized brain here: a behavior is a function that gets
|
|
10
|
+
* stepped once per tick and returns whether it is still going. A game that
|
|
11
|
+
* wants a planner writes one inside its own behavior; nothing here needs to
|
|
12
|
+
* know.
|
|
13
|
+
*
|
|
14
|
+
* The repertoire ACCRETES per mechanic. When a slice ships a mechanic, the
|
|
15
|
+
* tester learns to exercise it — a new entry below, in the same breath as that
|
|
16
|
+
* mechanic's exported setup function and readout. That is what makes "give the bot a goal"
|
|
17
|
+
* a thing the developer can say at the REPL instead of hand-flying the game.
|
|
18
|
+
*
|
|
19
|
+
* A behavior may ONLY act through `ctx.hands` (virtual input, which merges
|
|
20
|
+
* into the same keys feed a human's keyboard drives) and read whatever state
|
|
21
|
+
* the game exposes. It never teleports, never writes game state, and never
|
|
22
|
+
* calls a setup function: buying ARRIVAL at a situation is the developer's
|
|
23
|
+
* job (ordinary exported functions reached from the REPL), and playing it is
|
|
24
|
+
* the tester's.
|
|
25
|
+
*
|
|
26
|
+
* Goals are started with `hireTester` from `tester-station.ts`; the repertoire
|
|
27
|
+
* is returned by `describeTester`. Both are ordinary exports on the running
|
|
28
|
+
* module — see `src/bot/QaTester.tsx`.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { z } from 'zod';
|
|
32
|
+
|
|
33
|
+
/** What a behavior reports after one tick. `running` means "give me another
|
|
34
|
+
* tick"; the other two end the run. */
|
|
35
|
+
export type TesterOutcome = 'running' | 'done' | 'failed';
|
|
36
|
+
|
|
37
|
+
/** One sim tick, as the behavior sees it. `dt` is the fixed step the engine
|
|
38
|
+
* loop just ran; `elapsed` is sim seconds since this goal started — the unit
|
|
39
|
+
* every budget in a behavior should be written in. */
|
|
40
|
+
export interface TesterTick {
|
|
41
|
+
readonly dt: number;
|
|
42
|
+
readonly elapsed: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The tester's HANDS: the only way a behavior is allowed to touch the game.
|
|
47
|
+
*
|
|
48
|
+
* Every method here is a virtual actuation of one of the game's OWN declared
|
|
49
|
+
* input actions, which the engine merges into the same reads a real key
|
|
50
|
+
* produces (edges included). There is no state-write door on this interface on
|
|
51
|
+
* purpose — see this module's header.
|
|
52
|
+
*/
|
|
53
|
+
export interface TesterHands {
|
|
54
|
+
/** Every input action this game actually declared. A behavior that needs an
|
|
55
|
+
* action should check this rather than assume: driving an undeclared action
|
|
56
|
+
* throws, which fails the run loudly. */
|
|
57
|
+
actions(): readonly string[];
|
|
58
|
+
/** Hold (or level-set) an action — `true`/`false` for a digital action, a
|
|
59
|
+
* number for a scalar, `{x, y}` for a vector2. Exactly what holding and
|
|
60
|
+
* releasing a key does. */
|
|
61
|
+
set(action: string, value: boolean | number | { x: number; y: number }): void;
|
|
62
|
+
/** One honest press, carried through a full tick. */
|
|
63
|
+
tap(action: string): void;
|
|
64
|
+
/** Let go of everything this tester is holding. */
|
|
65
|
+
release(): void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** What a behavior is handed when it is created. */
|
|
69
|
+
export interface TesterContext {
|
|
70
|
+
readonly hands: TesterHands;
|
|
71
|
+
/** Publish what the tester is doing, to `bot.status` and the in-game HUD.
|
|
72
|
+
* Cheap; call it when something changes, not every tick. */
|
|
73
|
+
report(patch: { step?: string; progress?: number; note?: string }): void;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* One thing the tester knows how to do.
|
|
78
|
+
*
|
|
79
|
+
* `create` runs once when the goal starts and returns the per-tick step
|
|
80
|
+
* function, so anything the behavior needs to remember is an ordinary closure
|
|
81
|
+
* variable. `params` (when declared) is parsed by the driver BEFORE `create`,
|
|
82
|
+
* so a mistyped goal fails at the door with zod's own message rather than
|
|
83
|
+
* halfway through a run.
|
|
84
|
+
*/
|
|
85
|
+
export interface TesterBehavior<P = unknown> {
|
|
86
|
+
/** One line, written for the developer choosing a goal — say what the tester
|
|
87
|
+
* will DO and name the params it takes. This is the discovery surface. */
|
|
88
|
+
readonly summary: string;
|
|
89
|
+
readonly params?: z.ZodType;
|
|
90
|
+
create(ctx: TesterContext, params: P): (tick: TesterTick) => TesterOutcome;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const sweepParams = z
|
|
94
|
+
.object({
|
|
95
|
+
actions: z
|
|
96
|
+
.array(z.string())
|
|
97
|
+
.optional()
|
|
98
|
+
.describe('Which declared actions to press, in order. Defaults to all of them.'),
|
|
99
|
+
holdSimSeconds: z
|
|
100
|
+
.number()
|
|
101
|
+
.positive()
|
|
102
|
+
.default(0.75)
|
|
103
|
+
.describe('How long to hold each action, in sim seconds.'),
|
|
104
|
+
})
|
|
105
|
+
.strict();
|
|
106
|
+
|
|
107
|
+
type SweepParams = z.infer<typeof sweepParams>;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* `sweep` — the STARTER behavior, and the one a real game deletes first.
|
|
111
|
+
*
|
|
112
|
+
* It holds each of the game's declared input actions in turn for a sim-time
|
|
113
|
+
* budget, reporting as it goes. That is a genuinely useful first goal (it
|
|
114
|
+
* proves the controller is wired: bindings exist, something consumes them,
|
|
115
|
+
* the world reacts), and it is deliberately the least intelligent thing a
|
|
116
|
+
* tester can do — pressing every button is not playing the game. The moment
|
|
117
|
+
* this project has a mechanic, replace this with a goal named after what the
|
|
118
|
+
* tester is trying to ACHIEVE (`reach-the-ledge`, `kill-the-first-wave`), and
|
|
119
|
+
* let the repertoire grow from there.
|
|
120
|
+
*
|
|
121
|
+
* On the neutral starter world it fails, loudly and correctly: a project that
|
|
122
|
+
* declares no input actions has no controller for a tester to hold, and
|
|
123
|
+
* reporting `done` for having pressed nothing would be a lie the whole live
|
|
124
|
+
* loop is built to prevent.
|
|
125
|
+
*/
|
|
126
|
+
const sweep: TesterBehavior<SweepParams> = {
|
|
127
|
+
summary:
|
|
128
|
+
'Hold each declared input action in turn for a sim-time budget — the starter goal that ' +
|
|
129
|
+
'proves the controller is wired. Params: {actions?: string[], holdSimSeconds?: number}. ' +
|
|
130
|
+
"Replace it with this game's first real goal (see src/bot/behaviors.ts).",
|
|
131
|
+
params: sweepParams,
|
|
132
|
+
create(ctx, params) {
|
|
133
|
+
const actions = params.actions ?? [...ctx.hands.actions()];
|
|
134
|
+
const hold = params.holdSimSeconds;
|
|
135
|
+
|
|
136
|
+
if (actions.length === 0) {
|
|
137
|
+
return () => {
|
|
138
|
+
ctx.report({
|
|
139
|
+
note:
|
|
140
|
+
'this project declares no input actions, so the tester has no controller to hold — ' +
|
|
141
|
+
'declare your actions in src/input.ts (and read them from the mechanic that cares), ' +
|
|
142
|
+
'then give the tester a goal that plays the mechanic it drives',
|
|
143
|
+
});
|
|
144
|
+
return 'failed';
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let index = -1;
|
|
149
|
+
let releaseAt = 0;
|
|
150
|
+
|
|
151
|
+
return (tick) => {
|
|
152
|
+
if (tick.elapsed < releaseAt) return 'running';
|
|
153
|
+
|
|
154
|
+
const finished = actions[index];
|
|
155
|
+
if (finished !== undefined) ctx.hands.set(finished, false);
|
|
156
|
+
|
|
157
|
+
index += 1;
|
|
158
|
+
const next = actions[index];
|
|
159
|
+
if (next === undefined) {
|
|
160
|
+
ctx.report({ progress: actions.length, note: 'swept every declared action' });
|
|
161
|
+
return 'done';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
releaseAt = tick.elapsed + hold;
|
|
165
|
+
ctx.hands.set(next, true);
|
|
166
|
+
ctx.report({ step: `hold ${next}`, progress: index });
|
|
167
|
+
return 'running';
|
|
168
|
+
};
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* THE repertoire. Add a behavior by adding a key — nothing else registers it,
|
|
174
|
+
* and nothing outside this file decides what a goal means.
|
|
175
|
+
*/
|
|
176
|
+
export const testerBehaviors: Record<string, TesterBehavior> = {
|
|
177
|
+
sweep,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/** The repertoire as data, for the Tester contribution and the live REPL. */
|
|
181
|
+
export function describeTesterBehaviors(): Array<{ name: string; summary: string }> {
|
|
182
|
+
return Object.entries(testerBehaviors).map(([name, behavior]) => ({
|
|
183
|
+
name,
|
|
184
|
+
summary: behavior.summary,
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Look up a goal by name, or throw naming the whole repertoire — an unknown
|
|
190
|
+
* goal is a typo or a behavior nobody has written yet, and both are answered
|
|
191
|
+
* by seeing what the tester actually knows.
|
|
192
|
+
*/
|
|
193
|
+
export function resolveTesterBehavior(name: string): TesterBehavior {
|
|
194
|
+
const behavior = testerBehaviors[name];
|
|
195
|
+
if (behavior) return behavior;
|
|
196
|
+
const known = Object.keys(testerBehaviors);
|
|
197
|
+
throw new Error(
|
|
198
|
+
`hireTester: this game's tester has no behavior named "${name}". ` +
|
|
199
|
+
(known.length === 0
|
|
200
|
+
? 'Its repertoire is empty — add one in src/bot/behaviors.ts.'
|
|
201
|
+
: `It knows: ${known.join(', ')}. Add another in src/bot/behaviors.ts.`),
|
|
202
|
+
);
|
|
203
|
+
}
|