1
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-20 09:54:17 +08:00
parent 67c584b4df
commit 50759f3c1e
159 changed files with 16938 additions and 16925 deletions

View File

@@ -16,7 +16,7 @@ import type {
} from '../persistence/runtimeSnapshotTypes';
import type { GameState, StoryMoment, StoryOption } from '../types';
import { AnimationState } from '../types';
import { type ApiRetryOptions,requestJson } from './apiClient';
import { type ApiRetryOptions, requestJson } from './apiClient';
const RUNTIME_STORY_API_BASE = '/api/runtime/story';
const DEFAULT_SESSION_ID = 'runtime-main';
@@ -62,46 +62,9 @@ function requestRuntimeStoryJson<T>(
);
}
function buildRuntimeOptionInteraction(
option: RuntimeStoryOptionView,
gameState?: Pick<GameState, 'currentEncounter'>,
): StoryOption['interaction'] {
const encounter = gameState?.currentEncounter;
if (encounter?.kind === 'npc') {
const npcId = encounter.id ?? encounter.npcName;
const npcActionMap: Record<string, StoryOption['interaction']> = {
npc_chat: { kind: 'npc', npcId, action: 'chat' },
npc_help: { kind: 'npc', npcId, action: 'help' },
npc_fight: { kind: 'npc', npcId, action: 'fight' },
npc_leave: { kind: 'npc', npcId, action: 'leave' },
npc_recruit: { kind: 'npc', npcId, action: 'recruit' },
npc_spar: { kind: 'npc', npcId, action: 'spar' },
npc_trade: { kind: 'npc', npcId, action: 'trade' },
npc_gift: { kind: 'npc', npcId, action: 'gift' },
npc_quest_accept: { kind: 'npc', npcId, action: 'quest_accept' },
npc_quest_turn_in: { kind: 'npc', npcId, action: 'quest_turn_in' },
};
return npcActionMap[option.functionId];
}
if (encounter?.kind === 'treasure') {
const treasureActionMap: Record<string, StoryOption['interaction']> = {
treasure_secure: { kind: 'treasure', action: 'secure' },
treasure_inspect: { kind: 'treasure', action: 'inspect' },
treasure_leave: { kind: 'treasure', action: 'leave' },
};
return treasureActionMap[option.functionId];
}
return undefined;
}
function createRuntimeStoryOption(
option: RuntimeStoryOptionView,
gameState?: Pick<GameState, 'currentEncounter'>,
_gameState?: Pick<GameState, 'currentEncounter'>,
): StoryOption {
return {
functionId: option.functionId,
@@ -116,14 +79,16 @@ function createRuntimeStoryOption(
scrollWorld: false,
monsterChanges: [],
},
interaction: buildRuntimeOptionInteraction(option, gameState),
interaction: option.interaction as StoryOption['interaction'] | undefined,
runtimePayload: option.payload,
disabled: option.disabled,
disabledReason: option.reason,
};
}
export function getRuntimeSessionId(gameState: Pick<GameState, 'runtimeSessionId'>) {
export function getRuntimeSessionId(
gameState: Pick<GameState, 'runtimeSessionId'>,
) {
return gameState.runtimeSessionId?.trim() || DEFAULT_SESSION_ID;
}
@@ -158,7 +123,7 @@ export function buildStoryMomentFromRuntimeOptions(params: {
storyText: string;
options: RuntimeStoryOptionView[];
gameState?: Pick<GameState, 'currentEncounter'>;
}) {
}): StoryMoment {
return {
text: params.storyText,
options: params.options.map((option) =>
@@ -170,11 +135,9 @@ export function buildStoryMomentFromRuntimeOptions(params: {
function shouldPreferSnapshotStory(story: StoryMoment | null) {
return Boolean(
story &&
(
story.displayMode === 'dialogue' ||
(story.displayMode === 'dialogue' ||
story.deferredOptions?.length ||
story.dialogue?.length
),
story.dialogue?.length),
);
}
@@ -219,7 +182,9 @@ export async function getRuntimeStoryState(
return {
...response,
snapshot: rehydrateSavedSnapshot(response.snapshot as HydratedSavedGameSnapshot),
snapshot: rehydrateSavedSnapshot(
response.snapshot as HydratedSavedGameSnapshot,
),
} satisfies RuntimeStoryResponse;
}
@@ -258,12 +223,12 @@ export async function resolveRuntimeStoryAction(
return {
...response,
snapshot: rehydrateSavedSnapshot(response.snapshot as HydratedSavedGameSnapshot),
snapshot: rehydrateSavedSnapshot(
response.snapshot as HydratedSavedGameSnapshot,
),
} satisfies RuntimeStoryResponse;
}
export function getRuntimeActionSnapshot(response: RuntimeStoryResponse) {
return rehydrateSavedSnapshot(
response.snapshot as HydratedSavedGameSnapshot,
);
return rehydrateSavedSnapshot(response.snapshot as HydratedSavedGameSnapshot);
}