154 lines
4.0 KiB
TypeScript
154 lines
4.0 KiB
TypeScript
import { ASSET_API_PATHS } from '../../editor/shared/editorApiClient';
|
||
import type {
|
||
CustomWorldLandmark,
|
||
CustomWorldNpc,
|
||
CustomWorldPlayableNpc,
|
||
CustomWorldProfile,
|
||
} from '../../types';
|
||
import type {
|
||
CustomWorldSceneImageRequest,
|
||
CustomWorldSceneImageResult,
|
||
} from '../aiTypes';
|
||
import { requestJson } from '../apiClient';
|
||
import {
|
||
generateCustomWorldCoverImage,
|
||
uploadCustomWorldCoverImage,
|
||
} from '../customWorldCoverAssetService';
|
||
import { requestRpgCreationPostJson } from './rpgCreationRequestHelpers';
|
||
|
||
const RPG_CREATION_ASSET_API_BASE = '/api/runtime/custom-world';
|
||
|
||
export type RpgCreationHistoryAssetKind = 'character_visual' | 'scene_image';
|
||
|
||
export type RpgCreationHistoryAsset = {
|
||
assetObjectId: string;
|
||
assetKind: RpgCreationHistoryAssetKind;
|
||
imageSrc: string;
|
||
ownerUserId?: string | null;
|
||
ownerLabel: string;
|
||
profileId?: string | null;
|
||
entityId?: string | null;
|
||
createdAt: string;
|
||
updatedAt: string;
|
||
};
|
||
|
||
export async function generateRpgWorldSceneImage(
|
||
payload: CustomWorldSceneImageRequest,
|
||
) {
|
||
return requestJson<CustomWorldSceneImageResult>(
|
||
`${RPG_CREATION_ASSET_API_BASE}/scene-image`,
|
||
{
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify(payload),
|
||
},
|
||
'生成自定义世界场景图失败',
|
||
);
|
||
}
|
||
|
||
export async function listRpgCreationHistoryAssets(payload: {
|
||
kind: RpgCreationHistoryAssetKind;
|
||
limit?: number;
|
||
}) {
|
||
const params = new URLSearchParams({ kind: payload.kind });
|
||
if (payload.limit) {
|
||
params.set('limit', String(payload.limit));
|
||
}
|
||
|
||
const response = await requestJson<{ assets: RpgCreationHistoryAsset[] }>(
|
||
`${ASSET_API_PATHS.assetHistory}?${params.toString()}`,
|
||
{ method: 'GET' },
|
||
'读取历史素材失败',
|
||
);
|
||
|
||
return response.assets;
|
||
}
|
||
|
||
export async function generateRpgWorldSceneNpc(payload: {
|
||
profile: CustomWorldProfile;
|
||
landmarkId: string;
|
||
}) {
|
||
const response = await requestRpgCreationPostJson<{ npc: CustomWorldNpc }>(
|
||
`${RPG_CREATION_ASSET_API_BASE}/scene-npc`,
|
||
payload,
|
||
'生成场景 NPC 失败',
|
||
);
|
||
|
||
return response.npc;
|
||
}
|
||
|
||
async function requestRpgWorldEntity<T>(
|
||
payload: {
|
||
profile: CustomWorldProfile;
|
||
kind: 'playable' | 'story' | 'landmark';
|
||
},
|
||
fallbackMessage: string,
|
||
) {
|
||
return requestRpgCreationPostJson<{
|
||
kind: 'playable' | 'story' | 'landmark';
|
||
entity: T;
|
||
}>(`${RPG_CREATION_ASSET_API_BASE}/entity`, payload, fallbackMessage);
|
||
}
|
||
|
||
export async function generateRpgWorldPlayableNpc(payload: {
|
||
profile: CustomWorldProfile;
|
||
}) {
|
||
const response = await requestRpgWorldEntity<CustomWorldPlayableNpc>(
|
||
{
|
||
...payload,
|
||
kind: 'playable',
|
||
},
|
||
'生成可扮演角色失败',
|
||
);
|
||
|
||
return response.entity;
|
||
}
|
||
|
||
export async function generateRpgWorldStoryNpc(payload: {
|
||
profile: CustomWorldProfile;
|
||
}) {
|
||
const response = await requestRpgWorldEntity<CustomWorldNpc>(
|
||
{
|
||
...payload,
|
||
kind: 'story',
|
||
},
|
||
'生成场景角色失败',
|
||
);
|
||
|
||
return response.entity;
|
||
}
|
||
|
||
export async function generateRpgWorldLandmark(payload: {
|
||
profile: CustomWorldProfile;
|
||
}) {
|
||
const response = await requestRpgWorldEntity<CustomWorldLandmark>(
|
||
{
|
||
...payload,
|
||
kind: 'landmark',
|
||
},
|
||
'生成场景失败',
|
||
);
|
||
|
||
return response.entity;
|
||
}
|
||
|
||
/**
|
||
* 工作包 D 把结果页与编辑器依赖的资产请求迁入 RPG 创作域 client,
|
||
* 保留封面资产服务的既有边界,不把逻辑重新塞回 `aiService.ts`。
|
||
*/
|
||
export const rpgCreationAssetClient = {
|
||
listHistoryAssets: listRpgCreationHistoryAssets,
|
||
generateSceneImage: generateRpgWorldSceneImage,
|
||
generateSceneNpc: generateRpgWorldSceneNpc,
|
||
generatePlayableNpc: generateRpgWorldPlayableNpc,
|
||
generateStoryNpc: generateRpgWorldStoryNpc,
|
||
generateLandmark: generateRpgWorldLandmark,
|
||
generateCoverImage: generateCustomWorldCoverImage,
|
||
uploadCoverImage: uploadCustomWorldCoverImage,
|
||
};
|
||
|
||
export {
|
||
generateCustomWorldCoverImage as generateRpgWorldCoverImage,
|
||
uploadCustomWorldCoverImage as uploadRpgWorldCoverImage,
|
||
};
|