import { assetUrl } from "../AssetUrls"; import { GameMapType } from "./Game"; import { GameMapLoader, MapData } from "./GameMapLoader"; import { MapManifest } from "./TerrainMapLoader"; export class BinaryLoaderGameMapLoader implements GameMapLoader { private maps: Map; constructor() { this.maps = new Map(); } private createLazyLoader(importFn: () => Promise): () => Promise { let cache: Promise | null = null; return () => { cache ??= importFn(); return cache; }; } getMapData(map: GameMapType): MapData { const cachedMap = this.maps.get(map); if (cachedMap) { return cachedMap; } const key = Object.keys(GameMapType).find( (k) => GameMapType[k as keyof typeof GameMapType] === map, ); const fileName = key?.toLowerCase(); const loadBinary = (url: string) => fetch(url) .then((res) => { if (!res.ok) throw new Error(`Failed to load ${url}`); return res.arrayBuffer(); }) .then((buf) => new Uint8Array(buf)); const mapAssetUrl = (path: string) => assetUrl(`maps/${fileName}/${path}`); const mapData = { mapBin: this.createLazyLoader(() => loadBinary(mapAssetUrl("map.bin"))), map4xBin: this.createLazyLoader(() => loadBinary(mapAssetUrl("map4x.bin")), ), map16xBin: this.createLazyLoader(() => loadBinary(mapAssetUrl("map16x.bin")), ), manifest: this.createLazyLoader(() => fetch(mapAssetUrl("manifest.json")).then((res) => { if (!res.ok) { throw new Error(`Failed to load ${mapAssetUrl("manifest.json")}`); } return res.json() as Promise; }), ), webpPath: mapAssetUrl("thumbnail.webp"), } satisfies MapData; this.maps.set(map, mapData); return mapData; } }