This commit is contained in:
2026-04-21 19:18:26 +08:00
parent 4372ab5be1
commit 48957311bc
78 changed files with 643 additions and 3801 deletions

View File

@@ -1,13 +0,0 @@
/**
* 兼容期 façade
* 旧的 runtimeProfileCompiler 文件名暂时保留,避免工作包 G 完整拆分后影响仍未迁移的局部导入。
* 新实现已经拆到目录模块中,后续新增逻辑禁止继续回写到这个文件。
*/
export * from './buildAttributeSchema.js';
export * from './buildCompiledProfile.js';
export * from './creatorIntentBridge.js';
export * from './normalizeCamp.js';
export * from './normalizeLandmark.js';
export * from './normalizeRole.js';
export * from './normalizeSceneChapter.js';
export * from './normalizeShared.js';

View File

@@ -1 +0,0 @@
export * from './inventoryMutationService.js';

View File

@@ -1,2 +0,0 @@
export * from './questProgressionService.js';
export { generateQuestForNpcEncounter } from '../../services/questService.js';

View File

@@ -1,35 +0,0 @@
export {
buildRpgRuntimeAvailableOptions,
buildRpgRuntimeLegacyCurrentStory,
buildRpgRuntimeViewModel,
} from './RpgRuntimeOptionCompiler.js';
export {
appendStoryHistory,
getEncounterKey,
getEncounterNpcState,
getPlayerCharacter,
getPlayerSkillCooldowns,
isCombatFunctionId,
isNpcFunctionId,
isStoryFunctionId,
isTask5FunctionId,
isTask6RuntimeFunctionId,
MAX_TASK5_COMPANIONS,
setEncounterNpcState,
TASK6_DEFERRED_FUNCTION_IDS,
type RuntimeEncounter,
type RuntimeNpcState,
type RuntimeSession as RuntimeSessionPrimitives,
} from './RpgRuntimeSessionPrimitives.js';
export {
loadRpgRuntimeSession,
type RuntimeSession,
} from './RpgRuntimeSessionLoader.js';
export {
replaceRpgRuntimeSessionRawGameState,
syncRpgRuntimeSnapshot,
} from './RpgRuntimeSnapshotSync.js';
export {
resolveRpgRuntimeStoryAction,
} from './RpgRuntimeStoryActionService.js';
export { getRpgRuntimeStoryState } from './RpgRuntimeStoryStateService.js';

View File

@@ -1,2 +0,0 @@
export * from './runtimeItemResolutionService.js';
export { generateRuntimeItemIntents } from '../../services/runtimeItemService.js';

View File

@@ -1,96 +0,0 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import {
buildLooseRuntimeItemGenerationContext,
buildQuestRuntimeItemGenerationContext,
} from '../../bridges/legacyRuntimeItemResolutionBridge.js';
import {
resolveDirectedReward,
resolveRuntimeInventoryStock,
} from './runtimeItemResolutionService.js';
const TEST_WUXIA_WORLD = 'WUXIA' as Parameters<
typeof buildLooseRuntimeItemGenerationContext
>[0]['worldType'];
const TEST_XIANXIA_WORLD = 'XIANXIA' as NonNullable<
Parameters<typeof buildQuestRuntimeItemGenerationContext>[0]['context']['worldType']
>;
test('resolveDirectedReward returns flattened runtime reward items on the server side', () => {
const context = buildLooseRuntimeItemGenerationContext({
worldType: TEST_WUXIA_WORLD,
scene: {
id: 'scene-ruins',
name: '断碑古道',
description: '碎碑与旧誓散落在路旁。',
treasureHints: ['残匣', '旧祭火'],
},
encounter: {
id: 'treasure-altar',
kind: 'treasure',
npcName: '断誓秘匣',
npcDescription: '匣盖上留着未熄的旧印。',
npcAvatar: '',
context: '古道祭坛',
},
playerCharacterId: 'hero',
playerBuildTags: ['快剑', '追击'],
generationChannel: 'treasure',
});
const result = resolveDirectedReward(context, {
seedKey: 'task6:treasure',
fixedKinds: ['relic', 'consumable'],
fixedPermanence: ['permanent', 'timed'],
itemCount: 2,
});
assert.equal(result.items.length, 2);
assert.equal(
result.reward.primaryItem?.runtimeMetadata?.generationChannel,
'treasure',
);
assert.equal(result.items[0]?.id, result.reward.primaryItem?.id);
assert.ok(result.reward.primaryItem?.description?.includes('构筑'));
});
test('resolveRuntimeInventoryStock builds quest-flavored stock without browser fallback', () => {
const context = buildQuestRuntimeItemGenerationContext({
context: {
worldType: TEST_XIANXIA_WORLD,
currentSceneId: 'scene-cloud',
currentSceneName: '云阙旧渡',
currentSceneDescription: '旧渡口残留着灵潮和巡守痕迹。',
issuerNpcId: 'npc-issuer',
issuerNpcName: '巡守使',
issuerNpcContext: '巡守',
issuerAffinity: 24,
recentStoryMoments: [],
playerCharacter: null,
},
issuerNpcId: 'npc-issuer',
issuerNpcName: '巡守使',
roleText: '巡守',
scene: {
id: 'scene-cloud',
name: '云阙旧渡',
description: '旧渡口残留着灵潮和巡守痕迹。',
treasureHints: ['旧印'],
},
});
const items = resolveRuntimeInventoryStock(context, {
seedKey: 'task6:quest',
fixedKinds: ['equipment', 'consumable'],
fixedPermanence: ['permanent', 'timed'],
itemCount: 2,
});
assert.equal(items.length, 2);
assert.equal(
items.every((item) => item.runtimeMetadata?.generationChannel === 'quest_reward'),
true,
);
assert.equal(items.some((item) => Boolean(item.buildProfile || item.useProfile)), true);
});

View File

@@ -1,39 +0,0 @@
import {
buildDirectedRuntimeReward,
buildRuntimeInventoryStock,
flattenDirectedRuntimeRewardItems,
} from '../../bridges/legacyRuntimeItemResolutionBridge.js';
export type RuntimeItemGenerationContext = Parameters<
typeof buildDirectedRuntimeReward
>[0];
export type RuntimeRewardOptions = Parameters<
typeof buildDirectedRuntimeReward
>[1];
export type DirectedRuntimeReward = ReturnType<typeof buildDirectedRuntimeReward>;
export type ResolvedRuntimeRewardItem = ReturnType<
typeof buildRuntimeInventoryStock
>[number];
export type RuntimeRewardResolution = {
reward: DirectedRuntimeReward;
items: ResolvedRuntimeRewardItem[];
};
export function resolveDirectedReward(
context: RuntimeItemGenerationContext,
options: RuntimeRewardOptions,
): RuntimeRewardResolution {
const reward = buildDirectedRuntimeReward(context, options);
return {
reward,
items: flattenDirectedRuntimeRewardItems(reward),
};
}
export function resolveRuntimeInventoryStock(
context: RuntimeItemGenerationContext,
options: RuntimeRewardOptions,
): ResolvedRuntimeRewardItem[] {
return buildRuntimeInventoryStock(context, options);
}