10 KiB
10 KiB
Current Architecture
This document describes the code that exists today in the repository.
Runtime Structure
src/main.tsxmounts React.src/App.tsxmounts the TanStackRouterProvider.src/router.tsxdeclares the top-level routes:/mounts the playable 3D scene, debug perf overlay, and HTML overlays./editormounts the map editor page.
src/world/World.tsxcomposes the active scene, including:- environment and lighting
- debug helpers and debug camera mode
- either the map scene or the debug physics test scene
- the player rig when the active camera mode is
player
src/hooks/world/useWorldSceneLoading.tsowns the production scene loading state shared byWorld,GameMap, and the player octree readiness.src/world/GameMap.tsxloads map nodes frompublic/map.json, resolves available models, renders them progressively, and shows fallback cubes for missing models.src/world/GameMapCollision.tsxbuilds the player collision octree from dedicated collision nodes only.src/world/GameStageContent.tsxis wrapped in RapierPhysicsin the production game scene so stage gameplay objects can use physics without moving the map or player to Rapier. It now mounts reusableRepairGameinstances forbike,pylone, andfermemission states.src/world/debug/TestMap.tsxprovides a debug-oriented interaction and physics map with the existing grab/trigger/model-preview objects plus separateBike,Pylone, andFarmrepair playground zones.src/world/player/Player.tsxmounts the camera and controller.src/world/player/PlayerController.tsxowns pointer lock movement, jump handling, repair-step movement locking, and interaction input.
Physics Boundaries
The project currently uses two collision layers with separate responsibilities:
GameMapCollisionbuilds an octree used by the player controller for map collision.- The player octree must be built from a small collision-only subset of map nodes. It currently uses the
terrainnode only instead of traversing the full visible map, because building an octree from all rendered props can overload the browser renderer. GameStageContentis wrapped in RapierPhysicsfor gameplay objects such as repair triggers, cases, grabbables, and future mission-specific objects.TestMapowns its own RapierPhysicsplayground so repair gameplay can be tuned per mission state without depending on the production map layout.
Keep the player and map octree outside the Rapier provider until there is a deliberate migration plan. This avoids mixing player movement rules with object physics before the gameplay systems need it.
Interaction Model
src/managers/InteractionManager.tsis the current interaction state source.src/components/three/interaction/InteractableObject.tsxhandles focus detection through distance and raycasting.src/components/three/interaction/TriggerObject.tsximplements trigger-style interactions.src/components/three/interaction/GrabbableObject.tsximplements hold-and-release interactions.src/hooks/interaction/useInteraction.tsexposes the interaction snapshot to React UI.src/components/ui/InteractPrompt.tsxshows theEprompt for trigger interactions.
Audio
src/managers/AudioManager.tsprovides pooled one-shot playback, looped music playback, category volumes, and optional stereo pan for one-shot sounds.- Supported audio categories are
music,sfx, anddialogue. - Trigger interactions may play SFX directly through
AudioManager.
Settings Menu
src/managers/stores/useSettingsStore.tsstores settings for music volume, SFX volume, dialogue volume, subtitle visibility, subtitle language, repair runtime, and menu visibility.src/components/ui/GameSettingsMenu.tsxrenders the in-game options menu.src/components/ui/GameUI.tsxmounts the settings menu as an HTML overlay outside the canvas.Escopens and closes the menu, andsrc/world/player/PlayerController.tsxignores player input while the menu is open.- Volume changes are forwarded to
AudioManagerby category.
Dialogues And Subtitles
public/sounds/dialogue/dialogues.jsonis the runtime dialogue manifest.- Dialogue audio files live under
public/sounds/dialogue/. - Subtitle files live under
public/sounds/dialogue/subtitles/{fr|en}/. - The current subtitle model is one SRT file per voice and language.
src/types/dialogues/dialogues.tscontains the dialogue manifest types.src/utils/dialogues/dialogueManifestValidation.tsvalidates manifest shape at runtime.src/utils/dialogues/loadDialogueManifest.tsloads the manifest and SRT cues, with French fallback when the selected language is missing.src/utils/subtitles/parseSrt.tsparses SRT blocks and timecodes.src/utils/dialogues/playDialogue.tsplays dialogue audio and synchronizes the active subtitle against the audio element time.src/managers/stores/useSubtitleStore.tsstores the currently displayed subtitle cue.src/components/ui/Subtitles.tsxrenders the subtitle overlay.src/world/GameDialogues.tsxcurrently triggers dialogue entries that define atimecode.- Dialogue playback is queued so multiple dialogue requests do not overlap.
Cinematics
public/cinematics.jsonis the runtime cinematic manifest.src/types/cinematics/cinematics.tscontains cinematic manifest types.src/utils/cinematics/cinematicManifestValidation.tsvalidates manifest shape at runtime.src/utils/cinematics/loadCinematicManifest.tsloads/cinematics.json.src/world/GameCinematics.tsxtriggers cinematics that define a globaltimecode.- Cinematics use GSAP timelines to animate the active camera position and look target.
dialogueCueson a cinematic trigger dialogue IDs at times relative to the cinematic start.src/managers/stores/useGameStore.tsexposesisCinematicPlaying, used to lock player input during cinematics.
Debug System
- Debug mode is enabled with
?debug. src/utils/debug/Debug.tsowns thelil-guiinstance and debug controls.src/hooks/debug/useCameraMode.tsandsrc/hooks/debug/useSceneMode.tssubscribe to debug state.src/components/debug/DebugPerf.tsxlazily mountsr3f-perfin debug mode.src/components/ui/debug/DebugOverlayLayout.tsxmounts the compact HTML debug overlay when enabled fromlil-gui.src/components/ui/debug/GameStateDebugPanel.tsxexposes current game state, main/sub-state switching, previous/next step controls, and reset.src/components/ui/debug/HandTrackingDebugPanel.tsxshows hand tracking status, usage, loaded glove model, hand count, and fist state while hand tracking is active.src/components/ui/SceneLoadingOverlay.tsxdisplays the fullscreen loading state for 3D scenes, including the production game scene, debug physics scene, and editor scene.src/components/three/handTracking/HandTrackingGlove.tsxplaces the riggedgant_landgant_rmodels on detected hands in the debug physics scene.src/components/debug/scene/DebugHelpers.tsxmounts debug helpers.src/components/debug/scene/DebugCameraControls.tsxmounts the free debug camera.lil-guiglobal debug controls include camera mode, scene mode,R3F Perf, andDebug Overlay; interaction-specific controls live in theInteractionfolder.
3D Component Domains
src/components/three/models/contains reusable model helpers such asExplodableModel.src/components/three/interaction/contains reusable interaction wrappers such asInteractableObject,TriggerObject, andGrabbableObject.src/components/three/handTracking/contains R3F hand tracking debug models such as the glove overlays.src/components/three/gameplay/contains the reusable productionRepairGameflow, repair case, repair steps, and repair prompt components.src/components/three/world/contains reusable world/environment objects such asSkyModel.
Editor System
src/pages/editor/page.tsxis the route-level editor page for/editor.src/components/editor/EditorControls.tsxrenders the HTML editor control panel.src/components/editor/EditorDialogueManifestPanel.tsxeditspublic/sounds/dialogue/dialogues.json.src/components/editor/EditorCinematicManifestPanel.tsxeditspublic/cinematics.json.src/components/editor/EditorSrtPanel.tsxrenders the dialogue SRT editor inside the editor control panel.src/components/editor/scene/EditorScene.tsxcomposes the editor canvas scene, camera controls, lights, shortcuts, and map rendering.src/components/editor/scene/EditorMap.tsxrenders map nodes, fallback cubes, selection highlighting, and transform controls.src/controls/editor/FlyController.tsxprovides player-style editor navigation.src/hooks/editor/useEditorSceneData.tsloads scene data and handles folder upload fallback.src/hooks/editor/useEditorHistory.tsowns editor undo and redo state.src/utils/editor/loadEditorScene.tshandles editor-only folder upload parsing.src/utils/map/loadMapSceneData.tsis shared by the game scene and editor to loadpublic/map.jsonand resolve model URLs.src/types/editor/editor.tscontains the sharedMapNode,SceneData, andTransformModetypes.src/types/gameplay/repairMission.tscontains shared repair mission ids, mission steps, and guards used across store, config, debug UI, and gameplay components.
Map Data
public/map.jsonis expected to be aMapNode[].- Each map node
namemaps topublic/models/{name}/model.glbwhen available, withpublic/models/{name}/model.gltfkept as fallback. - The editor renders a fallback cube for missing models.
- The game scene renders fallback cubes for nodes whose model cannot be resolved.
- The game scene currently uses
terrainas the collision source for the player octree. Additional collision nodes should be explicit lightweight collision assets, not arbitrary visible decoration models.
Current Limitations
- The repository is a prototype, not the full intended game runtime.
src/world/debug/TestMap.tsxis part of the active scene composition.- There is no central gameplay orchestrator such as
GameManager. - Mission state exists in Zustand and the repair flow is implemented as a prototype for the current repair missions.
- Cinematics and dialogues exist as prototype timecode-driven systems; dialogue branching and broader gameplay orchestration are still limited.
- The player uses octree collision and simple movement rules, not a complete gameplay physics stack.
- Editor save-to-server is implemented as a Vite dev-server plugin, not a production backend API.