import { useEffect } from 'react'; import { GameShellRuntime } from './components/game-shell/GameShellRuntime.tsx'; import { activateRosterCompanion, benchActiveCompanion } from './data/companionRoster'; import { syncGameStatePlayTime } from './data/runtimeStats'; import { useBackgroundMusic } from './hooks/useBackgroundMusic'; import { useCombatFlow } from './hooks/useCombatFlow'; import { useGameFlow } from './hooks/useGameFlow'; import { useGamePersistence } from './hooks/useGamePersistence'; import { useGameSettings } from './hooks/useGameSettings'; import { useNpcInteractionFlow } from './hooks/useNpcInteractionFlow'; import { useStoryGeneration } from './hooks/useStoryGeneration'; export default function App() { const { gameState, setGameState, bottomTab, setBottomTab, isMapOpen, setIsMapOpen, resetGame, handleCustomWorldSelect: selectCustomWorld, handleBackToWorldSelect: backToWorldSelect, handleCharacterSelect: selectCharacter, } = useGameFlow(); const combatFlow = useCombatFlow({ setGameState, }); const storyFlow = useStoryGeneration({ gameState, setGameState, buildResolvedChoiceState: combatFlow.buildResolvedChoiceState, playResolvedChoice: combatFlow.playResolvedChoice, }); const { companionRenderStates, buildCompanionRenderStates } = useNpcInteractionFlow(gameState); const settings = useGameSettings(); const persistence = useGamePersistence({ gameState, bottomTab, currentStory: storyFlow.currentStory, isLoading: storyFlow.isLoading, setGameState, setBottomTab, hydrateStoryState: storyFlow.hydrateStoryState, resetStoryState: storyFlow.resetStoryState, }); useBackgroundMusic({ active: Boolean(gameState.playerCharacter && gameState.currentScene === 'Story'), volume: settings.musicVolume, }); useEffect(() => { if (!gameState.playerCharacter || gameState.currentScene !== 'Story') { return; } const intervalId = window.setInterval(() => { setGameState(currentState => { if (!currentState.playerCharacter || currentState.currentScene !== 'Story') { return currentState; } return syncGameStatePlayTime(currentState); }); }, 15000); return () => window.clearInterval(intervalId); }, [gameState.currentScene, gameState.playerCharacter, setGameState]); const handleCustomWorldSelect = ( customWorldProfile: Parameters[0], ) => { storyFlow.resetStoryState(); selectCustomWorld(customWorldProfile); }; const handleCharacterSelect = ( character: Parameters[0], ) => { storyFlow.resetStoryState(); selectCharacter(character); }; const handleBackToWorldSelect = () => { storyFlow.resetStoryState(); backToWorldSelect(); }; const handleContinueGame = () => { persistence.continueSavedGame(); }; const handleStartNewGame = () => { persistence.clearSavedGame(); storyFlow.resetStoryState(); resetGame(); }; const handleSaveAndExit = () => { const syncedGameState = syncGameStatePlayTime(gameState); persistence.saveCurrentGame({ gameState: syncedGameState, bottomTab, currentStory: storyFlow.currentStory, }); storyFlow.resetStoryState(); resetGame(); }; const handleBenchCompanion = (npcId: string) => { setGameState(currentState => benchActiveCompanion(currentState, npcId)); }; const handleActivateRosterCompanion = (npcId: string, swapNpcId?: string | null) => { setGameState(currentState => activateRosterCompanion(currentState, npcId, swapNpcId)); }; const gameShellSession = { gameState, currentStory: storyFlow.currentStory, isLoading: storyFlow.isLoading, aiError: storyFlow.aiError, bottomTab, setBottomTab, isMapOpen, setIsMapOpen, }; const gameShellStory = { displayedOptions: storyFlow.displayedOptions, canRefreshOptions: storyFlow.canRefreshOptions, handleRefreshOptions: storyFlow.handleRefreshOptions, handleChoice: storyFlow.handleChoice, handleMapTravelToScene: storyFlow.travelToSceneFromMap, npcUi: storyFlow.npcUi, characterChatUi: storyFlow.characterChatUi, inventoryUi: storyFlow.inventoryUi, battleRewardUi: storyFlow.battleRewardUi, questUi: storyFlow.questUi, goalUi: storyFlow.goalUi, }; const gameShellEntry = { hasSavedGame: persistence.hasSavedGame, handleContinueGame, handleStartNewGame, handleSaveAndExit, handleCustomWorldSelect, handleBackToWorldSelect, handleCharacterSelect, }; const gameShellCompanions = { companionRenderStates, buildCompanionRenderStates, onBenchCompanion: handleBenchCompanion, onActivateRosterCompanion: handleActivateRosterCompanion, }; const gameShellAudio = { musicVolume: settings.musicVolume, onMusicVolumeChange: settings.setMusicVolume, }; return ( ); }