@@ -19,6 +19,106 @@ function readImageSrc(value: unknown) {
|
||||
return readString(value) || null;
|
||||
}
|
||||
|
||||
type CustomWorldCoverRenderMode = 'image' | 'scene_with_roles';
|
||||
|
||||
function normalizeCoverCharacterRoleIds(
|
||||
value: unknown,
|
||||
playableRoles: Record<string, unknown>[],
|
||||
) {
|
||||
const availableIds = new Set(
|
||||
playableRoles.map((role) => readString(role.id)).filter(Boolean),
|
||||
);
|
||||
const selectedIds = readArray(value)
|
||||
.map((entry) => readString(entry))
|
||||
.filter((entry) => entry && availableIds.has(entry));
|
||||
|
||||
if (selectedIds.length > 0) {
|
||||
return [...new Set(selectedIds)].slice(0, 3);
|
||||
}
|
||||
|
||||
return [...availableIds].slice(0, 3);
|
||||
}
|
||||
|
||||
function resolveOpeningSceneImageSrc(profile: CustomWorldProfileRecord) {
|
||||
const campImage = isRecord(profile.camp)
|
||||
? readImageSrc(profile.camp.imageSrc)
|
||||
: null;
|
||||
if (campImage) {
|
||||
return campImage;
|
||||
}
|
||||
|
||||
return (
|
||||
readArray(profile.landmarks)
|
||||
.map((landmark) =>
|
||||
isRecord(landmark) ? readImageSrc(landmark.imageSrc) : null,
|
||||
)
|
||||
.find(Boolean) || null
|
||||
);
|
||||
}
|
||||
|
||||
function resolveLeadPlayableImageSrc(playableRoles: Record<string, unknown>[]) {
|
||||
return (
|
||||
playableRoles
|
||||
.map((role) => readImageSrc(role.imageSrc))
|
||||
.find(Boolean) || null
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveCustomWorldCoverPresentation(
|
||||
profile: CustomWorldProfileRecord,
|
||||
): {
|
||||
imageSrc: string | null;
|
||||
renderMode: CustomWorldCoverRenderMode;
|
||||
characterImageSrcs: string[];
|
||||
sourceType: 'default' | 'uploaded' | 'generated';
|
||||
} {
|
||||
const playableRoles = readArray(profile.playableNpcs).filter(isRecord);
|
||||
const cover = isRecord(profile.cover) ? profile.cover : null;
|
||||
const requestedSourceType = readString(cover?.sourceType);
|
||||
const sourceType =
|
||||
requestedSourceType === 'uploaded' ||
|
||||
requestedSourceType === 'generated'
|
||||
? requestedSourceType
|
||||
: 'default';
|
||||
|
||||
if (sourceType !== 'default') {
|
||||
const explicitImageSrc = readImageSrc(cover?.imageSrc);
|
||||
if (explicitImageSrc) {
|
||||
return {
|
||||
imageSrc: explicitImageSrc,
|
||||
renderMode: 'image',
|
||||
characterImageSrcs: [],
|
||||
sourceType,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const openingSceneImageSrc = resolveOpeningSceneImageSrc(profile);
|
||||
const roleById = new Map(
|
||||
playableRoles.map((role) => [readString(role.id), role] as const),
|
||||
);
|
||||
const characterImageSrcs = normalizeCoverCharacterRoleIds(
|
||||
cover?.characterRoleIds,
|
||||
playableRoles,
|
||||
)
|
||||
.map((roleId) => readImageSrc(roleById.get(roleId)?.imageSrc))
|
||||
.filter((imageSrc): imageSrc is string => Boolean(imageSrc));
|
||||
const leadPlayableImageSrc = resolveLeadPlayableImageSrc(playableRoles);
|
||||
|
||||
return {
|
||||
imageSrc: openingSceneImageSrc || leadPlayableImageSrc,
|
||||
renderMode:
|
||||
openingSceneImageSrc && characterImageSrcs.length > 0
|
||||
? 'scene_with_roles'
|
||||
: 'image',
|
||||
characterImageSrcs:
|
||||
openingSceneImageSrc && characterImageSrcs.length > 0
|
||||
? characterImageSrcs
|
||||
: [],
|
||||
sourceType: 'default',
|
||||
};
|
||||
}
|
||||
|
||||
function detectThemeMode(
|
||||
profile: Pick<
|
||||
CustomWorldProfileRecord,
|
||||
@@ -64,28 +164,7 @@ function detectThemeMode(
|
||||
}
|
||||
|
||||
export function buildCustomWorldCoverImageSrc(profile: CustomWorldProfileRecord) {
|
||||
const explicitCampImage = isRecord(profile.camp)
|
||||
? readImageSrc(profile.camp.imageSrc)
|
||||
: null;
|
||||
if (explicitCampImage) {
|
||||
return explicitCampImage;
|
||||
}
|
||||
|
||||
const landmarkImage = readArray(profile.landmarks)
|
||||
.map((landmark) => (isRecord(landmark) ? readImageSrc(landmark.imageSrc) : null))
|
||||
.find(Boolean);
|
||||
if (landmarkImage) {
|
||||
return landmarkImage;
|
||||
}
|
||||
|
||||
const playableImage = readArray(profile.playableNpcs)
|
||||
.map((role) => (isRecord(role) ? readImageSrc(role.imageSrc) : null))
|
||||
.find(Boolean);
|
||||
if (playableImage) {
|
||||
return playableImage;
|
||||
}
|
||||
|
||||
return null;
|
||||
return resolveCustomWorldCoverPresentation(profile).imageSrc;
|
||||
}
|
||||
|
||||
export function extractCustomWorldLibraryMetadata(profile: CustomWorldProfileRecord) {
|
||||
|
||||
Reference in New Issue
Block a user