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 mapBasePath = `/maps/${fileName}`; const mapData = { mapBin: this.createLazyLoader(() => loadBinary(`${mapBasePath}/map.bin`)), map4xBin: this.createLazyLoader(() => loadBinary(`${mapBasePath}/map4x.bin`), ), map16xBin: this.createLazyLoader(() => loadBinary(`${mapBasePath}/map16x.bin`), ), manifest: this.createLazyLoader(() => fetch(`${mapBasePath}/manifest.json`).then((res) => { if (!res.ok) { throw new Error(`Failed to load ${mapBasePath}/manifest.json`); } return res.json() as Promise; }), ), webpPath: `${mapBasePath}/thumbnail.webp`, } satisfies MapData; this.maps.set(map, mapData); return mapData; } }