forked from phenom/healer-man
71 lines
2.3 KiB
TypeScript
71 lines
2.3 KiB
TypeScript
import {
|
|
contentPackIsUsable,
|
|
getContentManagerSnapshot,
|
|
installContentPack,
|
|
removeContentPack,
|
|
resolveContentUrl,
|
|
subscribeContentManager,
|
|
} from "../content/contentManager";
|
|
|
|
export const COMBAT_MEDIA_MANIFEST_URL = "/assets/game/combat-effects/manifest.json";
|
|
export const COMBAT_MEDIA_CONTENT_PACK_ID = "core:combat-media";
|
|
|
|
export interface CombatMediaDownloadProgress {
|
|
readonly completed: number;
|
|
readonly total: number;
|
|
}
|
|
|
|
export interface CombatMediaDownloadResult {
|
|
readonly fileCount: number;
|
|
}
|
|
|
|
type ProgressListener = (progress: CombatMediaDownloadProgress) => void;
|
|
|
|
function isCombatMediaUrl(value: unknown): value is string {
|
|
return typeof value === "string" && value.startsWith("/assets/game/combat-effects/");
|
|
}
|
|
|
|
/** Callers must enforce the player's original-media opt-in before fetching. */
|
|
export async function fetchCombatMediaAsset(url: string): Promise<Response> {
|
|
if (!isCombatMediaUrl(url)) throw new Error(`Unsupported combat media URL: ${url}`);
|
|
return fetchOptionalMediaAsset(url);
|
|
}
|
|
|
|
/** Fetch source media only after its shared optional pack has been enabled. */
|
|
export async function fetchOptionalMediaAsset(url: string): Promise<Response> {
|
|
if (!combatMediaPackReady()) throw new Error("Original spell media is not installed.");
|
|
return fetch(resolveContentUrl(url), { cache: "no-store" });
|
|
}
|
|
|
|
/** Download and verify every file owned by the original combat-media pack. */
|
|
export async function downloadCombatMediaPack(
|
|
onProgress?: ProgressListener,
|
|
): Promise<CombatMediaDownloadResult> {
|
|
const publishProgress = () => {
|
|
const state = getContentManagerSnapshot();
|
|
onProgress?.({
|
|
completed: state.downloadedBytes,
|
|
total: Math.max(1, state.totalBytes),
|
|
});
|
|
};
|
|
const unsubscribe = subscribeContentManager(publishProgress);
|
|
try {
|
|
await installContentPack(COMBAT_MEDIA_CONTENT_PACK_ID);
|
|
publishProgress();
|
|
const pack = getContentManagerSnapshot().manifest?.packs.find((candidate) => (
|
|
candidate.id === COMBAT_MEDIA_CONTENT_PACK_ID
|
|
));
|
|
return { fileCount: pack?.fileCount ?? 0 };
|
|
} finally {
|
|
unsubscribe();
|
|
}
|
|
}
|
|
|
|
export async function removeCombatMediaPack(): Promise<void> {
|
|
await removeContentPack(COMBAT_MEDIA_CONTENT_PACK_ID);
|
|
}
|
|
|
|
export function combatMediaPackReady(): boolean {
|
|
return contentPackIsUsable(COMBAT_MEDIA_CONTENT_PACK_ID);
|
|
}
|