Files
Genarrative/src/components/game-shell/GameShellRuntime.tsx
victo 3d6f31433a
Some checks failed
CI / verify (push) Has been cancelled
update: 表改动 主页改动
2026-04-14 18:58:33 +08:00

203 lines
6.5 KiB
TypeScript

import { lazy, Suspense, useEffect } from 'react';
import { UI_CHROME } from '../../uiAssets';
import { useAuthUi } from '../auth/AuthUiContext';
import { GameShellMainContent } from './GameShellMainContent';
import type { GameShellProps } from './types';
import { useGameShellRuntimeViewModel } from './useGameShellRuntimeViewModel';
const GameShellOverlays = lazy(async () => {
const module = await import('./GameShellOverlays');
return {
default: module.GameShellOverlays,
};
});
const GameShellCanvasStage = lazy(async () => {
const module = await import('./GameShellCanvasStage');
return {
default: module.GameShellCanvasStage,
};
});
export function GameShellRuntime({session, story, entry, companions, audio}: GameShellProps) {
const authUi = useAuthUi();
const {
gameState,
isLoading,
aiError,
bottomTab,
setBottomTab,
isMapOpen,
setIsMapOpen,
} = session;
const {
displayedOptions,
canRefreshOptions,
handleRefreshOptions,
handleMapTravelToScene,
npcUi,
characterChatUi,
inventoryUi,
battleRewardUi,
questUi,
goalUi,
} = story;
const {
hasSavedGame,
savedSnapshot,
handleContinueGame,
handleStartNewGame,
handleSaveAndExit,
handleCustomWorldSelect,
handleBackToWorldSelect,
handleCharacterSelect,
} = entry;
const {
companionRenderStates,
onBenchCompanion,
onActivateRosterCompanion,
} = companions;
const {musicVolume, onMusicVolumeChange} = audio;
const {
selectionStage,
setSelectionStage,
overlayPanel,
openOverlayPanel,
closeOverlayPanel,
selectedSceneEntity,
setSelectedSceneEntity,
openPartyMemberDetails,
closeAdventureEntityModal,
showTeamModal,
openCampModal,
closeCampModal,
resetForSaveAndExit,
shouldMountAdventureEntityModal,
shouldMountCampModal,
shouldMountMapModal,
shouldMountCharacterChatModal,
shouldMountNpcModals,
visibleGameState,
visibleCurrentStory,
sceneTransitionPhase,
sceneTransitionToken,
setSceneTransitionDurations,
isCharacterSelectionStage,
shouldHideStoryOptions,
hideSelectionHero,
dialogueIndicator,
characterChatSummaries,
canvasCompanionRenderStates,
adventureStatistics,
handleSceneTransitionChoice,
} = useGameShellRuntimeViewModel({
session,
story,
companions,
});
useEffect(() => {
authUi?.setGlobalAccountActionsVisible(Boolean(gameState.playerCharacter));
return () => {
authUi?.setGlobalAccountActionsVisible(true);
};
}, [authUi, gameState.playerCharacter]);
return (
<div
className="fusion-pixel-app pixel-root-shell flex h-screen max-h-screen flex-col overflow-hidden font-sans text-zinc-100"
style={{
backgroundImage: `linear-gradient(rgba(8, 10, 14, 0.82), rgba(8, 10, 14, 0.82)), url("${UI_CHROME.appBackground}")`,
backgroundPosition: 'center',
backgroundRepeat: 'repeat',
}}
>
<Suspense fallback={null}>
<GameShellCanvasStage
gameState={gameState}
visibleGameState={visibleGameState}
hideSelectionHero={hideSelectionHero}
canvasCompanionRenderStates={canvasCompanionRenderStates}
dialogueIndicator={dialogueIndicator}
sceneTransitionPhase={sceneTransitionPhase}
sceneTransitionToken={sceneTransitionToken}
setSelectedSceneEntity={setSelectedSceneEntity}
setIsMapOpen={setIsMapOpen}
setSceneTransitionDurations={setSceneTransitionDurations}
/>
</Suspense>
<GameShellMainContent
gameState={gameState}
visibleGameState={visibleGameState}
visibleCurrentStory={visibleCurrentStory}
isLoading={isLoading}
aiError={aiError}
bottomTab={bottomTab}
setBottomTab={setBottomTab}
selectionStage={selectionStage}
setSelectionStage={setSelectionStage}
isCharacterSelectionStage={isCharacterSelectionStage}
hasSavedGame={hasSavedGame}
savedSnapshot={savedSnapshot}
handleContinueGame={handleContinueGame}
handleStartNewGame={handleStartNewGame}
handleCustomWorldSelect={handleCustomWorldSelect}
handleBackToWorldSelect={handleBackToWorldSelect}
handleCharacterSelect={handleCharacterSelect}
displayedOptions={displayedOptions}
hideStoryOptions={shouldHideStoryOptions}
canRefreshOptions={canRefreshOptions}
handleRefreshOptions={handleRefreshOptions}
handleSceneTransitionChoice={handleSceneTransitionChoice}
characterChatUi={characterChatUi}
inventoryUi={inventoryUi}
battleRewardUi={battleRewardUi}
questUi={questUi}
goalUi={goalUi}
companionRenderStates={companionRenderStates}
characterChatSummaries={characterChatSummaries}
openOverlayPanel={openOverlayPanel}
openCampModal={openCampModal}
openPartyMemberDetails={openPartyMemberDetails}
adventureStatistics={adventureStatistics}
musicVolume={musicVolume}
onMusicVolumeChange={onMusicVolumeChange}
resetForSaveAndExit={resetForSaveAndExit}
handleSaveAndExit={handleSaveAndExit}
/>
<Suspense fallback={null}>
<GameShellOverlays
gameState={gameState}
isLoading={isLoading}
isMapOpen={isMapOpen}
setIsMapOpen={setIsMapOpen}
npcUi={npcUi}
characterChatUi={characterChatUi}
inventoryUi={inventoryUi}
companionRenderStates={companionRenderStates}
characterChatSummaries={characterChatSummaries}
overlayPanel={overlayPanel}
closeOverlayPanel={closeOverlayPanel}
openCampModal={openCampModal}
openPartyMemberDetails={openPartyMemberDetails}
shouldMountAdventureEntityModal={shouldMountAdventureEntityModal}
selectedSceneEntity={selectedSceneEntity}
closeAdventureEntityModal={closeAdventureEntityModal}
shouldMountCampModal={shouldMountCampModal}
showTeamModal={showTeamModal}
closeCampModal={closeCampModal}
onBenchCompanion={onBenchCompanion}
onActivateRosterCompanion={onActivateRosterCompanion}
shouldMountMapModal={shouldMountMapModal}
handleMapTravelToScene={handleMapTravelToScene}
shouldMountCharacterChatModal={shouldMountCharacterChatModal}
shouldMountNpcModals={shouldMountNpcModals}
/>
</Suspense>
</div>
);
}