62 lines
2.1 KiB
TypeScript
62 lines
2.1 KiB
TypeScript
import { artManifest } from "./manifest";
|
|
|
|
/** Where `scripts/map-art.mjs` output is served from (`public/assets/map-gen`). */
|
|
export const ART_BASE_URL = "/assets/map-gen";
|
|
export const ART_BUNDLE = "map-art";
|
|
|
|
/** The generated files to load: 2x sprites on high-density screens (Step 10C.4). */
|
|
export function artBundle(devicePixelRatio: number): Record<string, string> {
|
|
const density = devicePixelRatio >= 2 ? "2x" : "1x";
|
|
const bundle: Record<string, string> = {};
|
|
for (const [id, asset] of Object.entries(artManifest.assets)) {
|
|
if (asset.file === null) continue;
|
|
bundle[id] =
|
|
asset.kind === "background"
|
|
? `${ART_BASE_URL}/${id}.webp`
|
|
: `${ART_BASE_URL}/${id}@${density}.png`;
|
|
}
|
|
return bundle;
|
|
}
|
|
|
|
/** The part of PixiJS's `Assets` the loader uses (a fake in tests). */
|
|
export interface AssetLoader<T> {
|
|
addBundle(name: string, assets: Record<string, string>): void;
|
|
load(alias: string): Promise<T>;
|
|
}
|
|
|
|
/** Loaded textures by asset id. An id that is absent draws its placeholder (0.5.41). */
|
|
export type ArtTextures<T> = ReadonlyMap<string, T>;
|
|
|
|
let registered = false;
|
|
|
|
/**
|
|
* Registers the map art as one bundle and loads each asset on its own, so one
|
|
* failure only costs that asset: it is left out (placeholder) and one warning
|
|
* names it. Never rejects.
|
|
*/
|
|
export async function loadArt<T>(
|
|
loader: AssetLoader<T>,
|
|
devicePixelRatio: number,
|
|
warn: (message: string) => void = console.warn,
|
|
): Promise<ArtTextures<T>> {
|
|
const bundle = artBundle(devicePixelRatio);
|
|
if (!registered) {
|
|
loader.addBundle(ART_BUNDLE, bundle);
|
|
registered = true;
|
|
}
|
|
const ids = Object.keys(bundle);
|
|
const results = await Promise.allSettled(ids.map((id) => loader.load(id)));
|
|
const textures = new Map<string, T>();
|
|
results.forEach((result, i) => {
|
|
const id = ids[i]!;
|
|
if (result.status === "fulfilled" && result.value) textures.set(id, result.value);
|
|
else warn(`Map art "${id}" failed to load; drawing its placeholder.`);
|
|
});
|
|
return textures;
|
|
}
|
|
|
|
/** Test hook: forget that the bundle was registered. */
|
|
export function resetArtRegistration(): void {
|
|
registered = false;
|
|
}
|