@vgai/editor 0.2.0
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/LICENSE +661 -0
- package/README.md +35 -0
- package/dist/a/b/c/test-nested.json +1 -0
- package/dist/assets/CCDIKSolver-Dz-ysxZF.js +1 -0
- package/dist/assets/SelectionBox-BXsv_6aH.js +1 -0
- package/dist/assets/browser-project-scripts-DOru4L1x.js +2 -0
- package/dist/assets/browserAll-CEkWYlFk.js +1 -0
- package/dist/assets/collision-world-DniMB0qq.glb +0 -0
- package/dist/assets/create-runtime-DYIWr3va.js +1 -0
- package/dist/assets/data-asset-Bb9sIM7i.js +5 -0
- package/dist/assets/esbuild-BHljloGq.wasm +0 -0
- package/dist/assets/fake-three-BMTQ9rl_.js +1 -0
- package/dist/assets/game-8SDZPPgH.js +1 -0
- package/dist/assets/game-BI111o5f.js +10 -0
- package/dist/assets/game-CevorxyV.js +1 -0
- package/dist/assets/game-Di1H0gFj.js +1 -0
- package/dist/assets/game-Di7XlywD.js +1 -0
- package/dist/assets/game-DjnCaw8R.js +1 -0
- package/dist/assets/game-Q9A0aXSV.js +1 -0
- package/dist/assets/game-pt_1lQLv.js +1 -0
- package/dist/assets/game-source-CvidN7AB.js +1 -0
- package/dist/assets/game-xsOho_wg.js +83 -0
- package/dist/assets/index-Bp5cecD6.js +12 -0
- package/dist/assets/index-CPVV6pjw.js +1 -0
- package/dist/assets/index-CpOnYyeD.js +213 -0
- package/dist/assets/index-Cs8xwv3e.js +1 -0
- package/dist/assets/index-DL7RcQ0n.js +27 -0
- package/dist/assets/index-Dr8H_6Rl.js +1 -0
- package/dist/assets/index-_bCaipUk.js +13650 -0
- package/dist/assets/ingest-siblings-Dz8eEqrV.js +1 -0
- package/dist/assets/mount-manifest-Bhk0ohsl.js +1 -0
- package/dist/assets/recast-navigation.wasm-compat-CvP4UGK6.js +1 -0
- package/dist/assets/scene-query-BivAHhJu.js +1 -0
- package/dist/assets/stats.module--VATS4Kh.js +1 -0
- package/dist/assets/webworkerAll-BLrH0F6F.js +1 -0
- package/dist/assets/xstate-animation-binding-1NGLmw6y.js +1 -0
- package/dist/assets/xstate.esm-BgUD33nl.js +3 -0
- package/dist/index.html +37 -0
- package/dist/ingest/racing-game/UPSTREAM.md +68 -0
- package/dist/ingest/racing-game/a/Inter-Black.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Black.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-BlackItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-BlackItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Bold.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Bold.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-BoldItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-BoldItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBold.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBold.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBoldItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBoldItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLight.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLight.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLightItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLightItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Italic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Italic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Light.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Light.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-LightItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-LightItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Medium.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Medium.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-MediumItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-MediumItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Regular.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Regular.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBold.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBold.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBoldItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBoldItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Thin.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Thin.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ThinItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ThinItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-italic.var.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-roman.var.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter.var.woff2 +0 -0
- package/dist/ingest/racing-game/a/index.css +1 -0
- package/dist/ingest/racing-game/images/bronze.png +0 -0
- package/dist/ingest/racing-game/images/gold.png +0 -0
- package/dist/ingest/racing-game/images/silver.png +0 -0
- package/dist/ingest/racing-game/index.html +15 -0
- package/dist/ingest/racing-game/models/chassis-draco.glb +0 -0
- package/dist/ingest/racing-game/models/track-draco.glb +0 -0
- package/dist/ingest/racing-game/models/wheel-draco.glb +0 -0
- package/dist/ingest/racing-game/rg-entry.js +1 -0
- package/dist/ingest/racing-game/sounds/accelerate.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/boost.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/crash.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/engine.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/honk.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/tire-brake.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/train.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/water.mp3 +0 -0
- package/dist/ingest/racing-game/textures/cursor.svg +3 -0
- package/dist/ingest/racing-game/textures/dikhololo_night_1k.hdr +0 -0
- package/dist/ingest/racing-game/textures/heightmap_1024.png +0 -0
- package/dist/ingest/racing-game/textures/mask.svg +11 -0
- package/dist/ingest/racing-game/textures/no_sound.png +0 -0
- package/dist/ingest/racing-game/three-r139.module.js +50617 -0
- package/dist/ingest/racing-game/vendor.js +179 -0
- package/dist/ingest/racing-game/vgai.game.json +20 -0
- package/dist/ingest/simcity/UPSTREAM.md +65 -0
- package/dist/ingest/simcity/favicon.ico +0 -0
- package/dist/ingest/simcity/fonts/Bebas-Regular.otf +0 -0
- package/dist/ingest/simcity/fonts/Digitalt.otf +0 -0
- package/dist/ingest/simcity/fonts/Stanberry.ttf +0 -0
- package/dist/ingest/simcity/icons/bulldozer-color.png +0 -0
- package/dist/ingest/simcity/icons/bulldozer.png +0 -0
- package/dist/ingest/simcity/icons/calendar.png +0 -0
- package/dist/ingest/simcity/icons/factory-color.png +0 -0
- package/dist/ingest/simcity/icons/factory.png +0 -0
- package/dist/ingest/simcity/icons/house-color.png +0 -0
- package/dist/ingest/simcity/icons/house.png +0 -0
- package/dist/ingest/simcity/icons/job.png +0 -0
- package/dist/ingest/simcity/icons/office.png +0 -0
- package/dist/ingest/simcity/icons/pause-color.png +0 -0
- package/dist/ingest/simcity/icons/pause.png +0 -0
- package/dist/ingest/simcity/icons/person.png +0 -0
- package/dist/ingest/simcity/icons/play-color.png +0 -0
- package/dist/ingest/simcity/icons/play.png +0 -0
- package/dist/ingest/simcity/icons/power-color.png +0 -0
- package/dist/ingest/simcity/icons/power-line-color.png +0 -0
- package/dist/ingest/simcity/icons/power.png +0 -0
- package/dist/ingest/simcity/icons/road-color.png +0 -0
- package/dist/ingest/simcity/icons/road.png +0 -0
- package/dist/ingest/simcity/icons/select-color.png +0 -0
- package/dist/ingest/simcity/icons/select.png +0 -0
- package/dist/ingest/simcity/icons/store-color.png +0 -0
- package/dist/ingest/simcity/index.html +94 -0
- package/dist/ingest/simcity/index.js +58 -0
- package/dist/ingest/simcity/main.css +233 -0
- package/dist/ingest/simcity/models/armored-truck.glb +0 -0
- package/dist/ingest/simcity/models/building-block-4floor-corner.glb +0 -0
- package/dist/ingest/simcity/models/building-block-4floor-short.glb +0 -0
- package/dist/ingest/simcity/models/building-block-5floor.glb +0 -0
- package/dist/ingest/simcity/models/building-burger-joint.glb +0 -0
- package/dist/ingest/simcity/models/building-cafe.glb +0 -0
- package/dist/ingest/simcity/models/building-casino.glb +0 -0
- package/dist/ingest/simcity/models/building-cinema.glb +0 -0
- package/dist/ingest/simcity/models/building-house-block-big.glb +0 -0
- package/dist/ingest/simcity/models/building-house-family-large.glb +0 -0
- package/dist/ingest/simcity/models/building-house-family-small.glb +0 -0
- package/dist/ingest/simcity/models/building-office-balcony.glb +0 -0
- package/dist/ingest/simcity/models/building-office-big.glb +0 -0
- package/dist/ingest/simcity/models/building-office-pyramid.glb +0 -0
- package/dist/ingest/simcity/models/building-office-tall.glb +0 -0
- package/dist/ingest/simcity/models/building-office.glb +0 -0
- package/dist/ingest/simcity/models/building-restaurant.glb +0 -0
- package/dist/ingest/simcity/models/building-skyscraper.glb +0 -0
- package/dist/ingest/simcity/models/car-ambulance-pickup.glb +0 -0
- package/dist/ingest/simcity/models/car-baywatch.glb +0 -0
- package/dist/ingest/simcity/models/car-hippie-van.glb +0 -0
- package/dist/ingest/simcity/models/car-passenger-race.glb +0 -0
- package/dist/ingest/simcity/models/car-passenger.glb +0 -0
- package/dist/ingest/simcity/models/car-police.glb +0 -0
- package/dist/ingest/simcity/models/car-taxi.glb +0 -0
- package/dist/ingest/simcity/models/car-tow-truck.glb +0 -0
- package/dist/ingest/simcity/models/car-truck-dump.glb +0 -0
- package/dist/ingest/simcity/models/car-veteran.glb +0 -0
- package/dist/ingest/simcity/models/construction-small.glb +0 -0
- package/dist/ingest/simcity/models/data-center.glb +0 -0
- package/dist/ingest/simcity/models/industry-factory-old.glb +0 -0
- package/dist/ingest/simcity/models/industry-factory.glb +0 -0
- package/dist/ingest/simcity/models/industry-refinery.glb +0 -0
- package/dist/ingest/simcity/models/industry-warehouse.glb +0 -0
- package/dist/ingest/simcity/models/power_line_pole_modified.glb +0 -0
- package/dist/ingest/simcity/models/tile-plain_grass.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-curve.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-end.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-intersection-t.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-intersection.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-straight.glb +0 -0
- package/dist/ingest/simcity/models/truck.glb +0 -0
- package/dist/ingest/simcity/statusIcons/no-power.png +0 -0
- package/dist/ingest/simcity/statusIcons/no-road-access.png +0 -0
- package/dist/ingest/simcity/textures/base.png +0 -0
- package/dist/ingest/simcity/textures/grid.png +0 -0
- package/dist/ingest/simcity/textures/specular.png +0 -0
- package/dist/ingest/simcity/three-r155.module.js +51466 -0
- package/dist/ingest/simcity/vgai.game.json +20 -0
- package/dist/ingest/tanks/UPSTREAM.md +69 -0
- package/dist/ingest/tanks/index.html +214 -0
- package/dist/ingest/tanks/models/pixelTank.fbx +0 -0
- package/dist/ingest/tanks/tanks-entry.js +92 -0
- package/dist/ingest/tanks/three-r170.module.js +54571 -0
- package/dist/ingest/tanks/vgai.game.json +20 -0
- package/dist/inputmaps/default.inputmap.json +41 -0
- package/dist/jsm/libs/draco/gltf/draco_decoder.js +33 -0
- package/dist/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
- package/dist/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
- package/dist/scenes/untitled.vscn.json +29 -0
- package/dist/textures/waternormals.jpg +0 -0
- package/dist-server/packaged.mjs +18155 -0
- package/package.json +36 -0
- package/server/asset-library-routes.ts +833 -0
- package/server/canonical-path.ts +50 -0
- package/server/cloud-asset-catalog.ts +101 -0
- package/server/dev.ts +350 -0
- package/server/editor-server.ts +1537 -0
- package/server/editor-sse.ts +73 -0
- package/server/game-globals-shadow.ts +58 -0
- package/server/local-asset-catalog.ts +163 -0
- package/server/packaged.ts +571 -0
- package/server/prod.ts +75 -0
- package/server/project-optimize-deps-entries.ts +149 -0
- package/server/project-view.ts +65 -0
- package/server/server-utils.ts +430 -0
- package/server/session-registry.ts +93 -0
- package/src/EditorContext.tsx +87 -0
- package/src/achieved-tier.ts +126 -0
- package/src/action-registry.ts +268 -0
- package/src/adapter-resolver.ts +1858 -0
- package/src/asset-events.ts +100 -0
- package/src/authoring/active-adapter.ts +98 -0
- package/src/authoring/active-systems.ts +50 -0
- package/src/authoring/boundary-authoring-adapter.ts +178 -0
- package/src/authoring/composite-authoring-adapter.ts +891 -0
- package/src/authoring/design-time-layers.ts +776 -0
- package/src/authoring/edit-mode-authoring.ts +643 -0
- package/src/authoring/embed-only-adapter.ts +57 -0
- package/src/authoring/ephemeral-persistence.ts +26 -0
- package/src/authoring/eyedropper-session.ts +69 -0
- package/src/authoring/first-party-hierarchy-menu.ts +74 -0
- package/src/authoring/first-party-inspector/AddSectionMenu.tsx +118 -0
- package/src/authoring/first-party-inspector/EnvironmentSection.tsx +550 -0
- package/src/authoring/first-party-inspector/HeaderSection.tsx +329 -0
- package/src/authoring/first-party-inspector/is-first-party-selection.ts +44 -0
- package/src/authoring/first-party-inspector/register.tsx +108 -0
- package/src/authoring/ingest-authoring-adapter.ts +475 -0
- package/src/authoring/ingest-capture.ts +94 -0
- package/src/authoring/ingest-game-adapter.ts +291 -0
- package/src/authoring/ingest-iframe-adapter.ts +38 -0
- package/src/authoring/ingest-iframe-reachable-adapter.ts +401 -0
- package/src/authoring/ingest-overlay.ts +193 -0
- package/src/authoring/layered-pick.ts +87 -0
- package/src/authoring/mount-failure-report.ts +112 -0
- package/src/authoring/overlay-report.ts +52 -0
- package/src/authoring/project-scenes.ts +111 -0
- package/src/authoring/react-dom-authoring-adapter.ts +795 -0
- package/src/authoring/react-inspector-section.tsx +1041 -0
- package/src/authoring/react-world-authoring-adapter.ts +2400 -0
- package/src/authoring/root-activation.ts +61 -0
- package/src/authoring/scene-ui-layer.ts +485 -0
- package/src/authoring/story-overlay.ts +48 -0
- package/src/authoring/ui-authoring-adapter.ts +325 -0
- package/src/authoring/ui-hierarchy-menu.ts +40 -0
- package/src/authoring/ui-inspector-sections.tsx +156 -0
- package/src/authoring/undo-timeline.ts +145 -0
- package/src/authoring/vgai-scene-authoring-adapter.ts +746 -0
- package/src/authoring/viewport-pick-context.ts +31 -0
- package/src/authoring/viewport-raycast.ts +80 -0
- package/src/authoring/world-overlay.ts +76 -0
- package/src/authoring/world-pan-state.ts +115 -0
- package/src/authoring/world-session-state.ts +102 -0
- package/src/authoring/world2d-authoring-adapter.ts +313 -0
- package/src/browser-external-watch.ts +98 -0
- package/src/browser-play-entry.ts +112 -0
- package/src/browser-project-scripts.ts +112 -0
- package/src/browser-transpile.ts +246 -0
- package/src/browser-watch-reload.ts +100 -0
- package/src/command-listener.ts +326 -0
- package/src/components/AlignToolbar.tsx +189 -0
- package/src/components/AppRoot.tsx +73 -0
- package/src/components/AssetBrowser.tsx +502 -0
- package/src/components/BottomPanel.tsx +326 -0
- package/src/components/BuildPanel.tsx +455 -0
- package/src/components/CameraInfo.tsx +56 -0
- package/src/components/CommandPalette.tsx +265 -0
- package/src/components/ConsolePanel.tsx +272 -0
- package/src/components/DataPanel.tsx +1268 -0
- package/src/components/DefaultEditorLayout.tsx +509 -0
- package/src/components/FolderTree.tsx +179 -0
- package/src/components/GameHierarchy.tsx +1349 -0
- package/src/components/Inspector.tsx +671 -0
- package/src/components/InspectorToolSection.tsx +74 -0
- package/src/components/MountFailureBanner.tsx +110 -0
- package/src/components/NetworkSection.tsx +109 -0
- package/src/components/OnlineAssetBrowser.tsx +448 -0
- package/src/components/OverlayReportBanner.tsx +122 -0
- package/src/components/PlayBar.tsx +356 -0
- package/src/components/PrefabSaveDialog.tsx +201 -0
- package/src/components/ProjectHeader.tsx +174 -0
- package/src/components/ProjectScreen.tsx +1004 -0
- package/src/components/RightPanel.tsx +166 -0
- package/src/components/RootActivateDialog.tsx +105 -0
- package/src/components/SaveDialog.tsx +197 -0
- package/src/components/SaveStatus.tsx +69 -0
- package/src/components/StatsOverlay.tsx +35 -0
- package/src/components/ToolHost.tsx +80 -0
- package/src/components/Toolbar.tsx +307 -0
- package/src/components/ViewportOverlay.tsx +234 -0
- package/src/components/ViewportPanel.tsx +369 -0
- package/src/components/WorldContextMenu.tsx +257 -0
- package/src/components/WorldSelectionOverlay.tsx +2003 -0
- package/src/components/WorldTextEditor.tsx +86 -0
- package/src/components/asset-viewers/AssetViewer.tsx +38 -0
- package/src/components/asset-viewers/AudioViewer.tsx +149 -0
- package/src/components/asset-viewers/GenericJsonViewer.tsx +77 -0
- package/src/components/asset-viewers/ImageViewer.tsx +65 -0
- package/src/components/asset-viewers/InputMapViewer.tsx +206 -0
- package/src/components/asset-viewers/ModelViewer.tsx +180 -0
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +236 -0
- package/src/components/data-csv.ts +301 -0
- package/src/components/entity-name-commit.ts +18 -0
- package/src/components/inspector-property-grouping.ts +65 -0
- package/src/components/inspector-widgets/AlignmentGrid.tsx +188 -0
- package/src/components/inspector-widgets/BorderEditor.tsx +305 -0
- package/src/components/inspector-widgets/ColorPicker.tsx +548 -0
- package/src/components/inspector-widgets/FilterEditor.tsx +108 -0
- package/src/components/inspector-widgets/FontPicker.tsx +196 -0
- package/src/components/inspector-widgets/GradientEditor.tsx +277 -0
- package/src/components/inspector-widgets/ScrubbableInput.tsx +152 -0
- package/src/components/inspector-widgets/ShadowEditor.tsx +332 -0
- package/src/components/inspector-widgets/color-utils.ts +202 -0
- package/src/components/inspector-widgets/gallery-main.tsx +167 -0
- package/src/components/inspector-widgets/index.ts +22 -0
- package/src/components/inspector-widgets/shared.tsx +135 -0
- package/src/components/inspectors/AnimationSection.tsx +143 -0
- package/src/components/inspectors/AudioSection.tsx +215 -0
- package/src/components/inspectors/BoneAttachmentSection.tsx +82 -0
- package/src/components/inspectors/CameraSection.tsx +105 -0
- package/src/components/inspectors/ComponentsSection.tsx +358 -0
- package/src/components/inspectors/JointsSection.tsx +255 -0
- package/src/components/inspectors/LightSection.tsx +116 -0
- package/src/components/inspectors/MaterialSection.tsx +1189 -0
- package/src/components/inspectors/MeshSection.tsx +99 -0
- package/src/components/inspectors/NavigationSection.tsx +58 -0
- package/src/components/inspectors/ParticleSection.tsx +681 -0
- package/src/components/inspectors/PhysicsSection.tsx +326 -0
- package/src/components/inspectors/PostProcessingSection.tsx +1290 -0
- package/src/components/inspectors/RenderingSection.tsx +109 -0
- package/src/components/inspectors/ShadowSection.tsx +84 -0
- package/src/components/inspectors/SplineSection.tsx +191 -0
- package/src/components/inspectors/TransformSection.tsx +191 -0
- package/src/components/inspectors/json-schema-fields.ts +281 -0
- package/src/components/inspectors/multi-edit-utils.ts +49 -0
- package/src/components/inspectors/zod-fields.ts +184 -0
- package/src/components/primitives/ColorInput.tsx +109 -0
- package/src/components/primitives/JsonInput.tsx +98 -0
- package/src/components/primitives/NumberInput.tsx +164 -0
- package/src/components/primitives/Panel.tsx +68 -0
- package/src/components/primitives/SectionHeader.tsx +45 -0
- package/src/components/primitives/Tooltip.tsx +82 -0
- package/src/components/primitives/Vec3Input.tsx +62 -0
- package/src/components/world-overlay-gestures.ts +1438 -0
- package/src/doctor/data-checks.ts +285 -0
- package/src/doctor/report.ts +386 -0
- package/src/editor-api.ts +700 -0
- package/src/editor-console.ts +194 -0
- package/src/editor-hotkeys.ts +441 -0
- package/src/editor-layers.ts +2 -0
- package/src/editor-mode.ts +28 -0
- package/src/editor-store.ts +2225 -0
- package/src/editor-viewport.ts +1924 -0
- package/src/entity-factory.ts +221 -0
- package/src/game-globals-prelude.ts +27 -0
- package/src/gated-globals.ts +131 -0
- package/src/generated/setup-by-example.generated.ts +53 -0
- package/src/gizmo-registry.ts +608 -0
- package/src/handle-system.ts +221 -0
- package/src/hierarchy-menu-registry.ts +70 -0
- package/src/hierarchy-rows.ts +73 -0
- package/src/hosted-example.ts +160 -0
- package/src/hotkeys.ts +142 -0
- package/src/ingest/discovery-react.ts +132 -0
- package/src/ingest/discovery.ts +205 -0
- package/src/ingest/discovery2d.ts +204 -0
- package/src/ingest/esm-entry-resolution.ts +102 -0
- package/src/ingest/games/bloom-composer/game.js +99 -0
- package/src/ingest/games/bloom-composer/vgai.game.json +21 -0
- package/src/ingest/games/embed-bundle/embed.html +10 -0
- package/src/ingest/games/embed-bundle/vgai.game.json +21 -0
- package/src/ingest/games/games-fps/assets/collision-world.glb +0 -0
- package/src/ingest/games/games-fps/game.js +479 -0
- package/src/ingest/games/games-fps/vgai.game.json +24 -0
- package/src/ingest/games/iframe-reachable/game-source.js +58 -0
- package/src/ingest/games/iframe-reachable/vgai.game.json +21 -0
- package/src/ingest/games/interactive-cubes/game.js +139 -0
- package/src/ingest/games/interactive-cubes/vgai.game.json +21 -0
- package/src/ingest/games/mismatched-three/fake-three.js +38 -0
- package/src/ingest/games/mismatched-three/game.js +10 -0
- package/src/ingest/games/mismatched-three/vgai.game.json +22 -0
- package/src/ingest/games/own-three-bundled/game.js +43 -0
- package/src/ingest/games/own-three-bundled/vgai.game.json +21 -0
- package/src/ingest/games/pointerlock-maze/game.js +288 -0
- package/src/ingest/games/pointerlock-maze/vgai.game.json +22 -0
- package/src/ingest/games-2d/_fixtures/first-party-scene.scn2d.json +124 -0
- package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +25 -0
- package/src/ingest/games-2d/bunnymark/game.ts +88 -0
- package/src/ingest/games-2d/bunnymark/vgai.game.json +21 -0
- package/src/ingest/games-2d/flappy/game.ts +148 -0
- package/src/ingest/games-2d/flappy/vgai.game.json +21 -0
- package/src/ingest/games-2d/flappy-pixi/vgai.game.json +25 -0
- package/src/ingest/games-2d/puzzling-potions/vgai.game.json +25 -0
- package/src/ingest/games-2d/tilemap-camera/game.ts +115 -0
- package/src/ingest/games-2d/tilemap-camera/vgai.game.json +21 -0
- package/src/ingest/games-react/react-rpg/entry.tsx +185 -0
- package/src/ingest/games-react/react-rpg/shims.d.ts +26 -0
- package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +129 -0
- package/src/ingest/games-react/react-rpg/vgai.game.json +21 -0
- package/src/ingest/host-namespace-registry.ts +196 -0
- package/src/ingest/types.ts +127 -0
- package/src/ingest-hierarchy-rows.ts +207 -0
- package/src/ingest-mode.ts +2092 -0
- package/src/ingest-siblings.ts +466 -0
- package/src/initial-scene.ts +194 -0
- package/src/inspector-section-registry.ts +117 -0
- package/src/interactive-edit-scope.ts +34 -0
- package/src/main.tsx +23 -0
- package/src/manifest-project.ts +43 -0
- package/src/model-thumbnail.ts +156 -0
- package/src/module-mode.ts +513 -0
- package/src/navmesh-handler.ts +94 -0
- package/src/packaged-runtime.ts +49 -0
- package/src/play-mode.ts +1148 -0
- package/src/playground/main.ts +206 -0
- package/src/project-manager.ts +173 -0
- package/src/scene-diff.ts +112 -0
- package/src/scene-serializer.ts +144 -0
- package/src/scene-sync.ts +587 -0
- package/src/scene-ui-mode/active-scene-ui.ts +58 -0
- package/src/scene-ui-mode/scene-ui-palette-panel.tsx +152 -0
- package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +29 -0
- package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +74 -0
- package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +49 -0
- package/src/scene-ui-mode/ui-prefab-io.ts +76 -0
- package/src/script-loader.ts +143 -0
- package/src/storage/fsa-storage.ts +55 -0
- package/src/storage/handle-storage.ts +150 -0
- package/src/storage/handle-store.ts +116 -0
- package/src/storage/http-storage.ts +137 -0
- package/src/storage/index.ts +147 -0
- package/src/storage/mem-storage.ts +135 -0
- package/src/storage/opfs-storage.ts +25 -0
- package/src/storage/paths.ts +26 -0
- package/src/storage/seed.ts +106 -0
- package/src/storage/types.ts +110 -0
- package/src/tool-loader.ts +291 -0
- package/src/ui-editor/inspector.tsx +563 -0
- package/src/ui-editor/node-ops.ts +266 -0
- package/src/ui-editor/overlay.tsx +380 -0
- package/src/ui-editor/palette.tsx +114 -0
- package/src/ui-editor/react-store.ts +78 -0
- package/src/ui-editor/timeline-panel.tsx +443 -0
- package/src/ui-editor/ui-edit-store.ts +552 -0
- package/src/ui-editor/ui-prefab.ts +95 -0
- package/src/ui-source/inspect.ts +544 -0
- package/src/ui-source/oid-transform.ts +133 -0
- package/src/ui-source/source-write-backend.ts +203 -0
- package/src/ui-source/tailwind-map.ts +174 -0
- package/src/ui-source/writer.ts +1175 -0
- package/src/widgets/index.ts +73 -0
- package/template/.claude/skills/editor/SKILL.md +252 -0
- package/template/CLAUDE.md +512 -0
- package/template/LICENSE +30 -0
- package/template/emit-schemas.ts +42 -0
- package/template/index.html +17 -0
- package/template/package.json +53 -0
- package/template/project.json +9 -0
- package/template/public/audio/ambient-arena.wav +0 -0
- package/template/public/audio/ambient-music.wav +0 -0
- package/template/public/audio/ambient-nature.wav +0 -0
- package/template/public/audio/ambient-wind.wav +0 -0
- package/template/public/inputmaps/default.inputmap.json +41 -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/scenes/default.vscn.json +43 -0
- package/template/public/scenes/untitled.vscn.json +29 -0
- package/template/public/textures/waternormals.jpg +0 -0
- package/template/server/colyseus-setup.ts +85 -0
- package/template/server/main.ts +34 -0
- package/template/server/rooms/arena-room.ts +420 -0
- package/template/server/rooms/game-room.ts +162 -0
- package/template/server/rooms.ts +15 -0
- package/template/server/tsconfig.json +19 -0
- package/template/src/data/README.md +40 -0
- package/template/src/data/assets.ts +31 -0
- package/template/src/data/tuning.data.json +5 -0
- package/template/src/data/tuning.schema.json +21 -0
- package/template/src/data/tuning.schema.ts +34 -0
- package/template/src/data/tuning.ts +24 -0
- package/template/src/main.ts +157 -0
- package/template/src/scripts/components/data-spinner.ts +45 -0
- package/template/src/scripts/components/scene-camera.ts +40 -0
- package/template/src/scripts/main.ts +94 -0
- package/template/src/scripts/registry.ts +46 -0
- package/template/src/tools/README.md +14 -0
- package/template/src/tools/example.tool.tsx +91 -0
- package/template/src/tools/spin.tool.tsx +101 -0
- package/template/src/ui/Button.tsx +27 -0
- package/template/src/ui/DefaultHud.tsx +40 -0
- package/template/src/ui/KeyHint.tsx +25 -0
- package/template/src/ui/Panel.tsx +52 -0
- package/template/src/ui/RebindPanel.tsx +129 -0
- package/template/src/ui/Slider.tsx +28 -0
- package/template/src/ui/StatusDot.tsx +22 -0
- package/template/src/ui/Toggle.tsx +19 -0
- package/template/src/ui/game-state.tsx +37 -0
- package/template/src/ui/index.ts +7 -0
- package/template/src/ui/mount-default-hud.tsx +19 -0
- package/template/src/ui/mount-ui.ts +15 -0
- package/template/tsconfig.json +36 -0
- package/template/validate-asset-content.ts +78 -0
- package/template/validate-manifest.ts +55 -0
- package/template/validate-scenes.ts +211 -0
- package/template/vgai.game.json +21 -0
- package/template/vite.config.ts +128 -0
- package/vite-plugin-example-assets.ts +60 -0
- package/vite-plugin-game-globals.ts +46 -0
- package/vite-plugin-game-static.ts +71 -0
- package/vite-plugin-project-game-static.ts +84 -0
- package/vite-plugin-react-game-static.ts +98 -0
- package/vite-plugin-react-world-provider.ts +81 -0
- package/vite-plugin-react-world-runtime.ts +76 -0
- package/vite-plugin-ui-oid.ts +561 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host shim for the vendored react-rpg ingest (Track N, N2 —
|
|
3
|
+
* docs/REACT-INGEST-LANDING-DESIGN.md D-N2/D-N3/D-N7). Composes the vendored
|
|
4
|
+
* game's own `App` + Redux `store`/`persistor` — NO game-source edits, ever
|
|
5
|
+
* (the anti-shim rule). Default-exports the composed component, which
|
|
6
|
+
* `resolveIngestReactAdapter` (`adapter-resolver.ts`, Part G) wraps in
|
|
7
|
+
* `<GameProvider game={game}>` and mounts via `createRoot` into the T6.2
|
|
8
|
+
* react-world host stack — same mechanism `default-react` uses, restricted
|
|
9
|
+
* to the `'deduped'` strategy rung.
|
|
10
|
+
*
|
|
11
|
+
* The vendored game's OWN standalone entry
|
|
12
|
+
* (`vendor/react-games/react-rpg/src/index.jsx`, a React-17 `ReactDOM.render`
|
|
13
|
+
* call) is vendored but NEVER imported here — D-N2 is explicit that entry
|
|
14
|
+
* point must never run through this path. Reading it instead (for reference
|
|
15
|
+
* only) to find exactly what page environment it sets up, this shim
|
|
16
|
+
* replicates the minimum, D-N7:
|
|
17
|
+
*
|
|
18
|
+
* 1. `id="window"` — `features/player/controls.jsx`'s hammerjs binding does
|
|
19
|
+
* `new Hammer(document.getElementById('window'))`. Upstream satisfies
|
|
20
|
+
* this by stamping `id="window"` on the `<html>` tag itself
|
|
21
|
+
* (`index.html`); we can't safely do that to the EDITOR's own `<html>`,
|
|
22
|
+
* so this shim renders an equivalent wrapping element instead.
|
|
23
|
+
* 2. `id="react-rpg"` — a FOURTH host-env assumption beyond D-N7's named
|
|
24
|
+
* three, found by reading `App.jsx` itself (not just `index.jsx`):
|
|
25
|
+
* `App.jsx`'s own `useEffect` calls
|
|
26
|
+
* `disableBodyScroll(document.getElementById('react-rpg'))`
|
|
27
|
+
* (`body-scroll-lock`) against the id upstream's `index.html` gives its
|
|
28
|
+
* React mount target (`<div id="react-rpg">`, matching `index.jsx`'s
|
|
29
|
+
* `ReactDOM.render(<ConnectedApp/>, document.getElementById('react-rpg'))`).
|
|
30
|
+
* Nested exactly like upstream's real DOM (`<html id="window"><body>
|
|
31
|
+
* <div id="react-rpg">`), so both lookups succeed.
|
|
32
|
+
* 3. `react-sound`'s `soundManager` global (`index.jsx`'s
|
|
33
|
+
* `soundManager.setup({...})`) — needed before any `<Sound>` component
|
|
34
|
+
* (`features/game-menus/game-music`, `features/player`) renders. Called
|
|
35
|
+
* at MODULE TOP LEVEL (not inside an effect), mirroring `index.jsx`
|
|
36
|
+
* exactly — a module only ever evaluates once, so this never re-runs on
|
|
37
|
+
* an in-page remount either.
|
|
38
|
+
* 4. `public/tiles/**`/`public/logo-no-bg.png` asset serving — handled
|
|
39
|
+
* SERVER-SIDE (`packages/editor/vite-plugin-react-game-static.ts`), not
|
|
40
|
+
* in this shim; `config/constants.js`'s `GET_REF_URL()` computes an
|
|
41
|
+
* absolute tile-asset base URL from its own `import.meta.url` (locating
|
|
42
|
+
* the literal substring `'src'` in it) — see that plugin's doc comment
|
|
43
|
+
* for exactly which URL this resolves to and why keeping the vendored
|
|
44
|
+
* folder named `src/` (not renamed) is load-bearing for this to even be
|
|
45
|
+
* a VALID URL, not just a differently-located one.
|
|
46
|
+
* 5. The typeface imports (`typeface-montserrat`/`typeface-roboto`/
|
|
47
|
+
* `typeface-roboto-mono`) and the game's global `index.scss` reset —
|
|
48
|
+
* `index.jsx` imports these before mounting; replicated here for visual
|
|
49
|
+
* fidelity (R-N1: accepted global-SCSS-bleed risk, v1).
|
|
50
|
+
*
|
|
51
|
+
* R-N2 (react-ga4) — VERIFIED INERT: `grep -rn react-ga4` over the vendored
|
|
52
|
+
* tree finds exactly ONE reference, `src/index.jsx`'s own
|
|
53
|
+
* `ReactGA.initialize(...)`/`ReactGA.send(...)` calls — that file is vendored
|
|
54
|
+
* but never imported (see above), so `react-ga4` never initializes and never
|
|
55
|
+
* fires a network request through this ingestion path. No stub/neutralization
|
|
56
|
+
* needed; recorded here rather than assumed.
|
|
57
|
+
*
|
|
58
|
+
* TWO DIFFERENT "avoid strict-TS-resolution" idioms are in play below, and
|
|
59
|
+
* they are NOT interchangeable — an empirical finding from the real dev
|
|
60
|
+
* server (a mocked-createRoot unit test can't catch this; only a real
|
|
61
|
+
* browser import actually attempts network resolution):
|
|
62
|
+
* - The vendored game's own `App.jsx`/`config/store.js` are imported via a
|
|
63
|
+
* dynamic `import()` whose specifier is a plain RELATIVE path built from a
|
|
64
|
+
* `const` (not a string literal at the call site, `/* @vite-ignore *\/`)
|
|
65
|
+
* — `tsc` skips module resolution for a non-literal specifier (mirrors
|
|
66
|
+
* every `fsImportPath`-built dynamic import in `adapter-resolver.ts`), and
|
|
67
|
+
* the BROWSER resolves a relative URL natively with no bundler help
|
|
68
|
+
* needed — both sides work.
|
|
69
|
+
* - `react-sound` and `redux-persist/integration/react` are BARE package
|
|
70
|
+
* specifiers instead — a bare specifier has NO meaning to a browser's
|
|
71
|
+
* native `import()` at all (unlike a relative URL) unless Vite's dev
|
|
72
|
+
* server rewrites it to `/node_modules/.vite/deps/...`, which Vite only
|
|
73
|
+
* does for imports it can STATICALLY analyze. `/* @vite-ignore *\/`
|
|
74
|
+
* explicitly tells Vite to skip that analysis — so applying the SAME
|
|
75
|
+
* dynamic-import trick to these two bare specifiers throws
|
|
76
|
+
* `Failed to resolve module specifier` at runtime (verified against the
|
|
77
|
+
* real dev server). The fix: import these two STATICALLY (letting Vite's
|
|
78
|
+
* normal analysis/rewrite handle them) and silence `tsc`'s missing-`.d.ts`
|
|
79
|
+
* complaint with the ambient module declarations in `./shims.d.ts`
|
|
80
|
+
* instead of a specifier trick.
|
|
81
|
+
*/
|
|
82
|
+
import { type ComponentType, type CSSProperties, useEffect, useState } from 'react';
|
|
83
|
+
import { Provider } from 'react-redux';
|
|
84
|
+
import { PersistGate } from 'redux-persist/integration/react';
|
|
85
|
+
import 'react-sound';
|
|
86
|
+
import 'typeface-montserrat';
|
|
87
|
+
import 'typeface-roboto';
|
|
88
|
+
import 'typeface-roboto-mono';
|
|
89
|
+
import '../../../../../../vendor/react-games/react-rpg/src/index.scss';
|
|
90
|
+
|
|
91
|
+
const GAME_ROOT = '../../../../../../vendor/react-games/react-rpg/src';
|
|
92
|
+
|
|
93
|
+
const FULL_SIZE: CSSProperties = { width: '100%', height: '100%' };
|
|
94
|
+
// The T6.2 host stack's per-world DOM-root layer defaults to
|
|
95
|
+
// `pointer-events: none` (mountOneReactWorld, create-runtime.ts) — the right
|
|
96
|
+
// default for a HUD overlaid on a canvas world, letting clicks fall through
|
|
97
|
+
// to the canvas below by default and opting specific elements back IN. An
|
|
98
|
+
// INGESTED full-game react world has no canvas underneath it to fall through
|
|
99
|
+
// to — nothing in react-rpg's own foreign JSX knows about vgai's opt-in
|
|
100
|
+
// convention, so without this the entire game is unclickable. This is the
|
|
101
|
+
// documented mechanism (create-runtime.ts: "the mounted react tree opts
|
|
102
|
+
// specific elements back in with pointer-events:auto") applied at the
|
|
103
|
+
// shim's own outermost element — opts the WHOLE ingested tree back in, no
|
|
104
|
+
// engine change needed.
|
|
105
|
+
const OUTER_STYLE: CSSProperties = { ...FULL_SIZE, pointerEvents: 'auto' };
|
|
106
|
+
|
|
107
|
+
interface ReactRpgModules {
|
|
108
|
+
App: ComponentType;
|
|
109
|
+
store: unknown;
|
|
110
|
+
persistor: { persist: () => void };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// D-N7 item 3 — see module doc comment: called once, at module evaluation
|
|
114
|
+
// time, exactly mirroring `index.jsx`'s own top-level
|
|
115
|
+
// `import 'react-sound'; soundManager.setup({...});` sequence.
|
|
116
|
+
(globalThis as unknown as { soundManager?: { setup: (o: object) => void } }).soundManager?.setup({
|
|
117
|
+
debugMode: false,
|
|
118
|
+
ignoreMobileRestrictions: true,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const APP_SPECIFIER = `${GAME_ROOT}/App.jsx`;
|
|
122
|
+
const STORE_SPECIFIER = `${GAME_ROOT}/config/store.js`;
|
|
123
|
+
|
|
124
|
+
let modulesPromise: Promise<ReactRpgModules> | null = null;
|
|
125
|
+
/** Import the vendored game's own `App` + `store`/`persistor` — cached so a
|
|
126
|
+
* dispose -> remount cycle doesn't re-fetch. */
|
|
127
|
+
function loadReactRpgModules(): Promise<ReactRpgModules> {
|
|
128
|
+
if (!modulesPromise) {
|
|
129
|
+
modulesPromise = (async () => {
|
|
130
|
+
const [appMod, storeMod] = await Promise.all([
|
|
131
|
+
import(/* @vite-ignore */ APP_SPECIFIER) as Promise<{
|
|
132
|
+
default: ComponentType;
|
|
133
|
+
}>,
|
|
134
|
+
import(/* @vite-ignore */ STORE_SPECIFIER) as Promise<{
|
|
135
|
+
default: unknown;
|
|
136
|
+
persistor: { persist: () => void };
|
|
137
|
+
}>,
|
|
138
|
+
]);
|
|
139
|
+
return {
|
|
140
|
+
App: appMod.default,
|
|
141
|
+
store: storeMod.default,
|
|
142
|
+
persistor: storeMod.persistor,
|
|
143
|
+
};
|
|
144
|
+
})();
|
|
145
|
+
}
|
|
146
|
+
return modulesPromise;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** The host shim, default-exported (D-N2's contract — a react world's `entry`
|
|
150
|
+
* module default-exports a component, `loadReactEntryComponent`). Renders
|
|
151
|
+
* `null` until the vendored modules resolve (they're ordinary same-origin
|
|
152
|
+
* Vite-served modules — no capture/timeout machinery needed, unlike the
|
|
153
|
+
* three/pixi ingest tiers). */
|
|
154
|
+
export default function ReactRpgHostShim() {
|
|
155
|
+
const [mods, setMods] = useState<ReactRpgModules | null>(null);
|
|
156
|
+
|
|
157
|
+
useEffect(() => {
|
|
158
|
+
let cancelled = false;
|
|
159
|
+
void loadReactRpgModules().then((m) => {
|
|
160
|
+
if (!cancelled) setMods(m);
|
|
161
|
+
});
|
|
162
|
+
return () => {
|
|
163
|
+
cancelled = true;
|
|
164
|
+
};
|
|
165
|
+
}, []);
|
|
166
|
+
|
|
167
|
+
if (!mods) return null;
|
|
168
|
+
const { App, store, persistor } = mods;
|
|
169
|
+
|
|
170
|
+
// D-N7 items 1/2: nested id="window" > id="react-rpg", mirroring upstream's
|
|
171
|
+
// real <html id="window"><body><div id="react-rpg"> structure so both
|
|
172
|
+
// `document.getElementById('window')` (hammerjs) and
|
|
173
|
+
// `document.getElementById('react-rpg')` (body-scroll-lock, App.jsx) resolve.
|
|
174
|
+
return (
|
|
175
|
+
<div id="window" style={OUTER_STYLE}>
|
|
176
|
+
<div id="react-rpg" style={FULL_SIZE}>
|
|
177
|
+
<Provider store={store as never}>
|
|
178
|
+
<PersistGate loading={null} persistor={persistor}>
|
|
179
|
+
<App />
|
|
180
|
+
</PersistGate>
|
|
181
|
+
</Provider>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient module declarations for two bare packages `entry.tsx` imports
|
|
3
|
+
* STATICALLY (Track N, N2 — see that file's doc comment for why these two
|
|
4
|
+
* specifically must be static, not the dynamic-`/* @vite-ignore *\/` idiom
|
|
5
|
+
* used for the vendored game's own `App.jsx`/`config/store.js`):
|
|
6
|
+
*
|
|
7
|
+
* - `react-sound` ships no types at all (no `@types/react-sound` on npm) —
|
|
8
|
+
* imported only for its side effect (attaching `window.soundManager`).
|
|
9
|
+
* - `redux-persist`'s root package ships types (`types:
|
|
10
|
+
* './types/index.d.ts'`) but has no `exports`/`typesVersions` map for
|
|
11
|
+
* this subpath, so `tsc` can't find a declaration file for it even though
|
|
12
|
+
* one exists on disk (`redux-persist/types/integration/react.d.ts`).
|
|
13
|
+
*/
|
|
14
|
+
declare module 'react-sound';
|
|
15
|
+
|
|
16
|
+
declare module 'redux-persist/integration/react' {
|
|
17
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
18
|
+
|
|
19
|
+
export interface PersistGateProps {
|
|
20
|
+
loading?: ReactNode;
|
|
21
|
+
persistor: unknown;
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
onBeforeLift?: () => void | Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export const PersistGate: ComponentType<PersistGateProps>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Track N, N2 — verbatim copy of the template's `GameProvider` seam
|
|
3
|
+
* (`packages/editor/template/src/ui/game-state.tsx`), present here
|
|
4
|
+
* ONLY because `adapter-resolver.ts`'s `loadProjectGameProvider` (shared by
|
|
5
|
+
* `default-react` and `ingest-react`, T6.2/Track N) hard-requires
|
|
6
|
+
* `src/ui/game-state.tsx` under whatever `projectRoot` an
|
|
7
|
+
* `ingest-react` world resolves against — see
|
|
8
|
+
* `vite-plugin-react-world-provider.ts`'s literal `/src/ui/
|
|
9
|
+
* game-state.tsx` path. This folder (`games-react/react-rpg/`) IS that
|
|
10
|
+
* world's `projectRoot` (its `vgai.game.json`'s `entry` — `../entry.tsx` —
|
|
11
|
+
* resolves relative to it too), so it needs its own copy, exactly like every
|
|
12
|
+
* scaffolded project gets one (`create-vgai-project`'s `scaffoldProject`).
|
|
13
|
+
*
|
|
14
|
+
* The vendored react-rpg game itself never reads `useGameState`/`useGame` —
|
|
15
|
+
* D-N2's host shim (`../../entry.tsx`) only composes the vendored game's OWN
|
|
16
|
+
* `<Provider store><PersistGate persistor><App/></PersistGate></Provider>`,
|
|
17
|
+
* with `<GameProvider>` wrapped around that AUTOMATICALLY by the resolver
|
|
18
|
+
* (context-only, harmless to a foreign tree, per D-N2). This file is
|
|
19
|
+
* therefore present purely to satisfy the resolver's lookup, not because the
|
|
20
|
+
* ingested game consumes it — kept byte-identical to the template's copy so
|
|
21
|
+
* a future react-ingest game that DOES want the state bridge (e.g. an
|
|
22
|
+
* ingest-authoring follow-on, D-N8) gets it for free.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import type { WorldStateObserver } from '@engine/adapter';
|
|
26
|
+
import {
|
|
27
|
+
createFrameSelectorCache,
|
|
28
|
+
type Equals,
|
|
29
|
+
shallow,
|
|
30
|
+
} from '@engine/runtime/frame-selector-cache';
|
|
31
|
+
import type { Game } from '@engine/runtime/game';
|
|
32
|
+
import { createContext, type ReactNode, useContext, useRef, useSyncExternalStore } from 'react';
|
|
33
|
+
|
|
34
|
+
/** Re-exported for convenience — the opt-in equality for selectors that
|
|
35
|
+
* return a fresh object/array/tuple every call (default is `Object.is`). */
|
|
36
|
+
export { shallow };
|
|
37
|
+
|
|
38
|
+
const GameContext = createContext<Game | null>(null);
|
|
39
|
+
|
|
40
|
+
/** Provide the `Game` to `useGameState`/`useGame` for everything mounted
|
|
41
|
+
* beneath it. Does not replace or wrap `mountUI` — compose it around the
|
|
42
|
+
* element passed to `mountUI` (see the module doc comment above). */
|
|
43
|
+
export function GameProvider({ game, children }: { game: Game; children: ReactNode }) {
|
|
44
|
+
return <GameContext.Provider value={game}>{children}</GameContext.Provider>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Read the `Game` provided by the nearest `GameProvider`. Throws
|
|
48
|
+
* descriptively when called outside one — matching the repo's loud-failure
|
|
49
|
+
* habit rather than silently returning `null`. */
|
|
50
|
+
export function useGame(): Game {
|
|
51
|
+
const game = useContext(GameContext);
|
|
52
|
+
if (!game) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
'useGame: no Game in context — wrap this component in <GameProvider game={ctx.game!}>.',
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
return game;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Subscribe to a selected slice of game state (`docs/REACT-STATE-BRIDGE.md`
|
|
62
|
+
* §3). Re-renders only when the selected value changes: the selector re-runs
|
|
63
|
+
* at most once per completed frame (`game.state.frameVersion`), and
|
|
64
|
+
* `equals` (default `Object.is`; pass {@link shallow} for tuples/objects)
|
|
65
|
+
* gates whether the fresh result actually counts as a change.
|
|
66
|
+
*/
|
|
67
|
+
export function useGameState<T>(selector: (game: Game) => T, equals: Equals<T> = Object.is): T {
|
|
68
|
+
const game = useGame();
|
|
69
|
+
const cacheRef = useRef<ReturnType<typeof createFrameSelectorCache<T>> | null>(null);
|
|
70
|
+
if (cacheRef.current === null) {
|
|
71
|
+
cacheRef.current = createFrameSelectorCache<T>(equals);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return useSyncExternalStore(
|
|
75
|
+
(onStoreChange) => game.state.subscribe(onStoreChange),
|
|
76
|
+
() => cacheRef.current!.get(game.state.frameVersion, () => selector(game)),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Pure, react-free lookup for the `useWorldObservation` hook below — see the
|
|
82
|
+
* template's copy of this file for the full doc comment (byte-identical
|
|
83
|
+
* logic, kept here only so this folder's `GameProvider` lookup resolves).
|
|
84
|
+
*/
|
|
85
|
+
export function requireWorldObserver(game: Game, worldId: string): WorldStateObserver {
|
|
86
|
+
const world = game.world(worldId);
|
|
87
|
+
if (!world) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`useWorldObservation: no world registered with id "${worldId}" — check game.worlds for the ` +
|
|
90
|
+
'ids actually registered.',
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
const observer = world.mounted.observe;
|
|
94
|
+
if (!observer) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`useWorldObservation: world "${worldId}" (kind: ${world.kind}, adapter: "${world.adapter.id}") ` +
|
|
97
|
+
'has no state bridge — its mount has no `observe` (WorldStateObserver). This world cannot ' +
|
|
98
|
+
'be observed from React (docs/REACT-STATE-BRIDGE.md §4).',
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
return observer;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Subscribe to a selected slice of a FOREIGN (non-first-party) world's
|
|
106
|
+
* observed state — see the template's copy for the full doc comment.
|
|
107
|
+
*/
|
|
108
|
+
export function useWorldObservation<T>(
|
|
109
|
+
worldId: string,
|
|
110
|
+
selector: (snapshot: unknown) => T,
|
|
111
|
+
equals: Equals<T> = Object.is,
|
|
112
|
+
): T {
|
|
113
|
+
const game = useGame();
|
|
114
|
+
const observer = requireWorldObserver(game, worldId);
|
|
115
|
+
const cacheRef = useRef<ReturnType<typeof createFrameSelectorCache<T>> | null>(null);
|
|
116
|
+
if (cacheRef.current === null) {
|
|
117
|
+
cacheRef.current = createFrameSelectorCache<T>(equals);
|
|
118
|
+
}
|
|
119
|
+
const versionRef = useRef(0);
|
|
120
|
+
|
|
121
|
+
return useSyncExternalStore(
|
|
122
|
+
(onStoreChange) =>
|
|
123
|
+
observer.subscribe(() => {
|
|
124
|
+
versionRef.current++;
|
|
125
|
+
onStoreChange();
|
|
126
|
+
}),
|
|
127
|
+
() => cacheRef.current!.get(versionRef.current, () => selector(observer.snapshot())),
|
|
128
|
+
);
|
|
129
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifestVersion": 1,
|
|
3
|
+
"name": "React RPG: 2e (real OSS game)",
|
|
4
|
+
"version": "2.0.0",
|
|
5
|
+
"engine": {
|
|
6
|
+
"version": "0.1.0"
|
|
7
|
+
},
|
|
8
|
+
"worlds": [
|
|
9
|
+
{
|
|
10
|
+
"id": "react-rpg",
|
|
11
|
+
"kind": "react",
|
|
12
|
+
"description": "REAL unmodified native-React OSS game — ASteinheiser/react-rpg.com, vendored byte-for-byte under vendor/react-games/react-rpg (MIT) and mounted via the ingest-react identity (Track N, D-N1/D-N2/D-N3). No authoring in v1 (D-N8) — this world is ingested read-only, no scene/write-back surface.",
|
|
13
|
+
"adapter": {
|
|
14
|
+
"ingest": {
|
|
15
|
+
"strategy": "deduped"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"entry": "entry.tsx"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-namespace registry — Track P (docs/PIXI-INGEST-LANDING-DESIGN.md §2,
|
|
3
|
+
* D-P1): the editor-side half of `extraDeps` being DATA, not code. A manifest
|
|
4
|
+
* can only carry `extraDeps: string[]` (bare specifiers) — a JSON value has
|
|
5
|
+
* no way to carry a live ES module namespace object. This module owns the
|
|
6
|
+
* ONE static, known mapping from a bare specifier to a dynamically-imported
|
|
7
|
+
* HOST module namespace (the same instance the trapped pixi's extensions
|
|
8
|
+
* register against — see `ingest-iframe-2d.ts`'s `IframeReachableMultiOpts.
|
|
9
|
+
* extraDeps` doc comment), so `resolveIngest2DDescriptor`/`discovery2d.ts`
|
|
10
|
+
* can turn a manifest's `extraDeps` into the `ExtraDepsResolution2D` shape
|
|
11
|
+
* `mountIngestGame2DIframeReachableMulti` actually takes.
|
|
12
|
+
*
|
|
13
|
+
* Anti-shim (repo rule): a manifest naming a specifier this registry doesn't
|
|
14
|
+
* know THROWS at resolve, naming the specifier and listing every known one —
|
|
15
|
+
* never a silent stub/no-op namespace.
|
|
16
|
+
*
|
|
17
|
+
* Dynamic `import()` (not a static top-level import) for every entry: most
|
|
18
|
+
* editor sessions never ingest a pixi game that needs `@pixi/sound`/
|
|
19
|
+
* `@pixi/ui`/`gsap`/spine at all, so a static import would pull all four into
|
|
20
|
+
* every editor bundle. The registry of KNOWN specifiers below is still
|
|
21
|
+
* static (a plain object/Set of importer functions) — only the actual module
|
|
22
|
+
* evaluation is deferred to first use.
|
|
23
|
+
*
|
|
24
|
+
* D-Z3 (docs/WAVE3-ADAPTER-PLUMBING-DESIGN.md) — the registry pins stay
|
|
25
|
+
* authoritative and UNCHANGED (resolution order step 1 below); a specifier
|
|
26
|
+
* this registry doesn't know is no longer an immediate throw — it FALLS BACK
|
|
27
|
+
* to probing the OPEN PROJECT's own `node_modules/<specifier>/package.json`
|
|
28
|
+
* through the dev-server-only `/project-game-static` route (step 2), and
|
|
29
|
+
* only throws the anti-shim error if that fallback also comes up empty (step
|
|
30
|
+
* 3). This keeps the anti-shim doctrine (never fabricate/stub a dep) while
|
|
31
|
+
* admitting an external unmodified game's OWN deps beyond the four-entry
|
|
32
|
+
* registry, resolved as verbatim iframe importmap URL entries (never
|
|
33
|
+
* imported host-side — see `ingest-iframe-2d.ts`'s `extraDepUrls`).
|
|
34
|
+
*
|
|
35
|
+
* D-Z4 (docs/WAVE3-ADAPTER-PLUMBING-DESIGN.md §1) — `vgai bundle` needs the
|
|
36
|
+
* SAME two questions ("is this specifier registry-known?" / "does the
|
|
37
|
+
* project's own node_modules have a resolvable ESM entry for it?") answered
|
|
38
|
+
* from a plain Node CLI script, not a browser realm — see
|
|
39
|
+
* `knownHostNamespaceSpecifiers`/`isKnownHostNamespaceSpecifier` (pure, no
|
|
40
|
+
* I/O) and `packages/editor/scripts/run-bundle.ts`'s own fs-based sibling of
|
|
41
|
+
* `probeProjectNodeModules`, below. The exports-subset parsing itself lives
|
|
42
|
+
* in `./esm-entry-resolution` so both the fetch-based (here) and fs-based
|
|
43
|
+
* (there) probes share byte-identical semantics.
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
import type { ExtraDepsResolution2D } from '@engine/world2d/ingest2d';
|
|
47
|
+
import { probePackageJsonForEsmEntry } from './esm-entry-resolution';
|
|
48
|
+
|
|
49
|
+
/** Every specifier this registry can resolve, and how to import it. */
|
|
50
|
+
const KNOWN_IMPORTERS: Readonly<Record<string, () => Promise<Record<string, unknown>>>> = {
|
|
51
|
+
'@pixi/sound': () => import('@pixi/sound'),
|
|
52
|
+
'@pixi/ui': () => import('@pixi/ui'),
|
|
53
|
+
gsap: () => import('gsap'),
|
|
54
|
+
// Pinned EXACTLY 4.2.95 (packages root package.json) — 4.3.x fails to parse
|
|
55
|
+
// the puzzling-potions vendored game's skeleton data (docs/PIXI-INGEST-
|
|
56
|
+
// LANDING-DESIGN.md §3 D-P1). Do not bump without re-verifying that fixture.
|
|
57
|
+
'@esotericsoftware/spine-pixi-v8': () => import('@esotericsoftware/spine-pixi-v8'),
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** Every specifier this registry knows how to resolve (for error messages / introspection). */
|
|
61
|
+
export function knownHostNamespaceSpecifiers(): string[] {
|
|
62
|
+
return Object.keys(KNOWN_IMPORTERS);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Pure membership check (no dynamic `import()`, no side effect) — D-Z4's
|
|
67
|
+
* `vgai bundle` pre-build extraDeps validation needs to know whether a
|
|
68
|
+
* specifier is registry-known WITHOUT actually loading the module (it never
|
|
69
|
+
* needs the namespace, only "is this specifier legal to externalize").
|
|
70
|
+
*/
|
|
71
|
+
export function isKnownHostNamespaceSpecifier(specifier: string): boolean {
|
|
72
|
+
return specifier in KNOWN_IMPORTERS;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Resolve ONE bare specifier to its host module namespace. Throws, naming the
|
|
77
|
+
* specifier and the known list, if `specifier` isn't in the static registry
|
|
78
|
+
* above (anti-shim: never silently stub an unknown dep). Registry-only — no
|
|
79
|
+
* project-node_modules fallback here; that lives in `resolveExtraDeps` below
|
|
80
|
+
* (this function's contract — "a KNOWN specifier's host namespace" — stays
|
|
81
|
+
* exactly what it was before D-Z3).
|
|
82
|
+
*/
|
|
83
|
+
export async function resolveHostNamespace(specifier: string): Promise<Record<string, unknown>> {
|
|
84
|
+
const importer = KNOWN_IMPORTERS[specifier];
|
|
85
|
+
if (!importer) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`host-namespace-registry: unknown extraDeps specifier "${specifier}" — known specifiers ` +
|
|
88
|
+
`are: ${knownHostNamespaceSpecifiers().join(', ')}. A manifest naming an unregistered ` +
|
|
89
|
+
'specifier must not silently mount without it (anti-shim); register it here first.',
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return importer();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const PROJECT_STATIC_NODE_MODULES_PREFIX = '/project-game-static/node_modules/';
|
|
96
|
+
|
|
97
|
+
type ProbeResult =
|
|
98
|
+
| { kind: 'not-found' }
|
|
99
|
+
| { kind: 'cjs-only'; found: Record<string, unknown> }
|
|
100
|
+
| { kind: 'url'; url: string };
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Probe the OPEN project's own `node_modules/<specifier>/package.json`
|
|
104
|
+
* through the dev-server-only `/project-game-static` route (D-Z3 fallback,
|
|
105
|
+
* resolution-order step 2) and resolve its ESM entry. `specifier` may be a
|
|
106
|
+
* scoped package (`@scope/name`, one embedded slash) — the URL path segment
|
|
107
|
+
* is built straight from the specifier, which already contains the correct
|
|
108
|
+
* `@scope/name` shape for a `node_modules/@scope/name/...` filesystem path.
|
|
109
|
+
* Never throws: every failure mode (no project open, dep not installed,
|
|
110
|
+
* network error, unparsable JSON) collapses to `{ kind: 'not-found' }` — the
|
|
111
|
+
* caller (`resolveExtraDeps`) decides how to report "not installed" vs
|
|
112
|
+
* "installed but CJS-only" (only the latter came from an actually-parsed
|
|
113
|
+
* package.json, hence the two distinct named errors, D-Z3 step 3). The
|
|
114
|
+
* exports-subset parsing itself is shared with `run-bundle.ts`'s fs-based
|
|
115
|
+
* sibling via `./esm-entry-resolution` (D-Z4).
|
|
116
|
+
*/
|
|
117
|
+
async function probeProjectNodeModules(specifier: string): Promise<ProbeResult> {
|
|
118
|
+
if (typeof fetch !== 'function') return { kind: 'not-found' };
|
|
119
|
+
const pkgUrl = `${PROJECT_STATIC_NODE_MODULES_PREFIX}${specifier}/package.json`;
|
|
120
|
+
let pkg: Record<string, unknown>;
|
|
121
|
+
try {
|
|
122
|
+
const res = await fetch(pkgUrl);
|
|
123
|
+
if (!res.ok) return { kind: 'not-found' };
|
|
124
|
+
pkg = (await res.json()) as Record<string, unknown>;
|
|
125
|
+
} catch {
|
|
126
|
+
return { kind: 'not-found' };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const probed = probePackageJsonForEsmEntry(pkg);
|
|
130
|
+
if (probed.kind === 'cjs-only') return probed;
|
|
131
|
+
return {
|
|
132
|
+
kind: 'url',
|
|
133
|
+
url: `${PROJECT_STATIC_NODE_MODULES_PREFIX}${specifier}/${probed.entryPath}`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Resolve ONE specifier that ISN'T in the static registry via the D-Z3
|
|
139
|
+
* project-node_modules fallback (resolution-order steps 2/3): a
|
|
140
|
+
* `/project-game-static/node_modules/<spec>/<esm entry>` URL on success; the
|
|
141
|
+
* SAME named anti-shim throw as before (extended to say the project
|
|
142
|
+
* node_modules was probed too) when nothing usable was found ANYWHERE; a
|
|
143
|
+
* DISTINCT named throw when the dep IS installed but has no ESM entry
|
|
144
|
+
* (never silently serve CJS as ESM).
|
|
145
|
+
*/
|
|
146
|
+
async function resolveProjectNodeModulesUrl(specifier: string): Promise<string> {
|
|
147
|
+
const probe = await probeProjectNodeModules(specifier);
|
|
148
|
+
|
|
149
|
+
if (probe.kind === 'url') return probe.url;
|
|
150
|
+
|
|
151
|
+
if (probe.kind === 'cjs-only') {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`host-namespace-registry: extraDeps specifier "${specifier}" is installed in the open ` +
|
|
154
|
+
"project's node_modules but has no ESM entry — checked package.json's " +
|
|
155
|
+
'`exports["."]` import/module/default conditions (string or object form) and the ' +
|
|
156
|
+
`top-level \`module\` field; found: ${JSON.stringify(probe.found)}. Never silently serve ` +
|
|
157
|
+
'CJS as ESM (anti-shim, degrade loudly): ship/vendor an ESM build of ' +
|
|
158
|
+
`"${specifier}", or register it in host-namespace-registry.ts if it should resolve to a ` +
|
|
159
|
+
'host-provided namespace instead.',
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
throw new Error(
|
|
164
|
+
`host-namespace-registry: unknown extraDeps specifier "${specifier}" — known specifiers are: ` +
|
|
165
|
+
`${knownHostNamespaceSpecifiers().join(', ')}. Also probed the open project's own ` +
|
|
166
|
+
`\`node_modules/${specifier}/package.json\` (via /project-game-static, D-Z3 fallback) and ` +
|
|
167
|
+
'found nothing usable there either. A manifest naming an unregistered/uninstalled ' +
|
|
168
|
+
'specifier must not silently mount without it (anti-shim); register it in ' +
|
|
169
|
+
"host-namespace-registry.ts, or add it to the open project's own node_modules with a " +
|
|
170
|
+
'resolvable ESM entry.',
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Resolve every specifier in `specifiers` (a manifest's `ingest.extraDeps`)
|
|
176
|
+
* into the `ExtraDepsResolution2D` shape
|
|
177
|
+
* `mountIngestGame2DIframeReachableMulti`'s `extraDeps`/`extraDepUrls`
|
|
178
|
+
* options take: registry-known specifiers resolve to `namespaces` (unchanged
|
|
179
|
+
* from before D-Z3 — zero behavior change), everything else resolves via the
|
|
180
|
+
* D-Z3 project-node_modules fallback into `urls` (or throws, see
|
|
181
|
+
* `resolveProjectNodeModulesUrl`).
|
|
182
|
+
*/
|
|
183
|
+
export async function resolveExtraDeps(
|
|
184
|
+
specifiers: readonly string[],
|
|
185
|
+
): Promise<ExtraDepsResolution2D> {
|
|
186
|
+
const namespaces: Record<string, Record<string, unknown>> = {};
|
|
187
|
+
const urls: Record<string, string> = {};
|
|
188
|
+
for (const spec of specifiers) {
|
|
189
|
+
if (spec in KNOWN_IMPORTERS) {
|
|
190
|
+
namespaces[spec] = await resolveHostNamespace(spec);
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
urls[spec] = await resolveProjectNodeModulesUrl(spec);
|
|
194
|
+
}
|
|
195
|
+
return { namespaces, urls };
|
|
196
|
+
}
|