Files
Genarrative/src/hooks/useTreasureFlow.ts
T
kdletters 071faa482c 统一 Rust 与 TypeScript 格式化门禁
纳入 AGC Cargo workspace 的统一 rustfmt 检查与格式化入口

完成项目 TypeScript/Prettier 与 Rust 全量格式化

修复 Pingora expected executable 门禁的空白敏感误报

同步开发运维文档与 AGC skill pack 格式化忽略规则
2026-09-01 16:28:34 +08:00

75 lines
1.9 KiB
TypeScript

import { useCallback } from 'react';
import { Character, GameState, StoryMoment, StoryOption } from '../types';
import { resolveRpgRuntimeChoice } from './rpg-runtime-story';
export function useTreasureFlow({
gameState,
runtime,
}: {
gameState: GameState;
runtime: {
currentStory: StoryMoment | null;
setGameState: (state: GameState) => void;
setCurrentStory: (story: StoryMoment) => void;
setAiError: (message: string | null) => void;
setIsLoading: (loading: boolean) => void;
buildFallbackStoryForState: (
state: GameState,
character: Character,
fallbackText?: string,
) => StoryMoment;
};
}) {
const handleTreasureInteraction = useCallback(
async (option: StoryOption) => {
if (
!gameState.playerCharacter ||
option.interaction?.kind !== 'treasure' ||
gameState.currentEncounter?.kind !== 'treasure'
) {
return false;
}
runtime.setAiError(null);
runtime.setIsLoading(true);
try {
const { hydratedSnapshot, nextStory } = await resolveRpgRuntimeChoice({
gameState,
currentStory: runtime.currentStory,
option,
});
runtime.setGameState(hydratedSnapshot.gameState);
runtime.setCurrentStory(nextStory);
return true;
} catch (error) {
console.error(
'Failed to resolve treasure runtime action on the server:',
error,
);
runtime.setAiError(
error instanceof Error ? error.message : '宝藏动作执行失败',
);
if (!runtime.currentStory) {
runtime.setCurrentStory(
runtime.buildFallbackStoryForState(
gameState,
gameState.playerCharacter,
),
);
}
return false;
} finally {
runtime.setIsLoading(false);
}
},
[gameState, runtime],
);
return {
handleTreasureInteraction,
};
}