110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
import { useCallback } from 'react';
|
||
|
||
import type { CustomWorldAgentSessionSnapshot } from '../../../packages/shared/src/contracts/customWorldAgent';
|
||
import { rpgCreationPreviewAdapter } from '../../services/rpg-creation/rpgCreationPreviewAdapter';
|
||
import type { CustomWorldProfile } from '../../types';
|
||
|
||
type UseRpgCreationEnterWorldParams = {
|
||
isAgentDraftResultView: boolean;
|
||
activeAgentSessionId: string | null;
|
||
generatedCustomWorldProfile: CustomWorldProfile | null;
|
||
agentSessionProfile: CustomWorldProfile | null;
|
||
agentSession: CustomWorldAgentSessionSnapshot | null;
|
||
handleCustomWorldSelect: (customWorldProfile: CustomWorldProfile) => void;
|
||
executePublishWorld: () => Promise<CustomWorldAgentSessionSnapshot | null>;
|
||
setGeneratedCustomWorldProfile: (profile: CustomWorldProfile | null) => void;
|
||
};
|
||
|
||
/**
|
||
* 统一“进入世界”前的最终同步策略。
|
||
* Agent 草稿结果进入游戏时只读 session.draftProfile,不再把结果页快照回写成新的运行时 profile。
|
||
*/
|
||
export function useRpgCreationEnterWorld(
|
||
params: UseRpgCreationEnterWorldParams,
|
||
) {
|
||
const {
|
||
isAgentDraftResultView,
|
||
activeAgentSessionId,
|
||
generatedCustomWorldProfile,
|
||
agentSessionProfile,
|
||
agentSession,
|
||
handleCustomWorldSelect,
|
||
executePublishWorld,
|
||
setGeneratedCustomWorldProfile,
|
||
} = params;
|
||
|
||
const enterWorldForTestFromCurrentResult = useCallback(async () => {
|
||
if (!generatedCustomWorldProfile) {
|
||
return;
|
||
}
|
||
|
||
if (!isAgentDraftResultView || !activeAgentSessionId) {
|
||
handleCustomWorldSelect(generatedCustomWorldProfile);
|
||
return;
|
||
}
|
||
|
||
const latestProfile = agentSessionProfile ?? generatedCustomWorldProfile;
|
||
setGeneratedCustomWorldProfile(latestProfile);
|
||
handleCustomWorldSelect(latestProfile);
|
||
}, [
|
||
activeAgentSessionId,
|
||
agentSessionProfile,
|
||
generatedCustomWorldProfile,
|
||
handleCustomWorldSelect,
|
||
isAgentDraftResultView,
|
||
setGeneratedCustomWorldProfile,
|
||
]);
|
||
|
||
const publishCurrentResult = useCallback(async () => {
|
||
if (!generatedCustomWorldProfile) {
|
||
return null;
|
||
}
|
||
|
||
if (!isAgentDraftResultView || !activeAgentSessionId) {
|
||
return generatedCustomWorldProfile;
|
||
}
|
||
|
||
const latestProfile = agentSessionProfile ?? generatedCustomWorldProfile;
|
||
setGeneratedCustomWorldProfile(latestProfile);
|
||
|
||
const latestSession = agentSession;
|
||
const canEnterPublishedWorld =
|
||
latestSession?.stage === 'published' &&
|
||
latestSession.resultPreview?.canEnterWorld;
|
||
|
||
if (canEnterPublishedWorld) {
|
||
return latestProfile;
|
||
}
|
||
|
||
const publishedSession = await executePublishWorld();
|
||
const publishedProfile =
|
||
rpgCreationPreviewAdapter.buildPreviewFromSession(publishedSession) ??
|
||
latestProfile;
|
||
|
||
setGeneratedCustomWorldProfile(publishedProfile);
|
||
return publishedProfile;
|
||
}, [
|
||
activeAgentSessionId,
|
||
agentSession,
|
||
agentSessionProfile,
|
||
executePublishWorld,
|
||
generatedCustomWorldProfile,
|
||
handleCustomWorldSelect,
|
||
isAgentDraftResultView,
|
||
setGeneratedCustomWorldProfile,
|
||
]);
|
||
|
||
const enterWorldFromCurrentResult = useCallback(async () => {
|
||
const publishedProfile = await publishCurrentResult();
|
||
if (publishedProfile) {
|
||
handleCustomWorldSelect(publishedProfile);
|
||
}
|
||
}, [handleCustomWorldSelect, publishCurrentResult]);
|
||
|
||
return {
|
||
enterWorldFromCurrentResult,
|
||
enterWorldForTestFromCurrentResult,
|
||
publishCurrentResult,
|
||
};
|
||
}
|