mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 12:10:46 +00:00
Resolve versioned map assets per file
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { assetUrl } from "../core/AssetUrls";
|
||||
import { FetchGameMapLoader } from "../core/game/FetchGameMapLoader";
|
||||
|
||||
export const terrainMapFileLoader = new FetchGameMapLoader(() =>
|
||||
assetUrl("maps"),
|
||||
export const terrainMapFileLoader = new FetchGameMapLoader((path) =>
|
||||
assetUrl(`maps/${path}`),
|
||||
);
|
||||
|
||||
@@ -37,25 +37,25 @@ export class BinaryLoaderGameMapLoader implements GameMapLoader {
|
||||
})
|
||||
.then((buf) => new Uint8Array(buf));
|
||||
|
||||
const mapBasePath = assetUrl(`maps/${fileName}`);
|
||||
const mapAssetUrl = (path: string) => assetUrl(`maps/${fileName}/${path}`);
|
||||
|
||||
const mapData = {
|
||||
mapBin: this.createLazyLoader(() => loadBinary(`${mapBasePath}/map.bin`)),
|
||||
mapBin: this.createLazyLoader(() => loadBinary(mapAssetUrl("map.bin"))),
|
||||
map4xBin: this.createLazyLoader(() =>
|
||||
loadBinary(`${mapBasePath}/map4x.bin`),
|
||||
loadBinary(mapAssetUrl("map4x.bin")),
|
||||
),
|
||||
map16xBin: this.createLazyLoader(() =>
|
||||
loadBinary(`${mapBasePath}/map16x.bin`),
|
||||
loadBinary(mapAssetUrl("map16x.bin")),
|
||||
),
|
||||
manifest: this.createLazyLoader(() =>
|
||||
fetch(`${mapBasePath}/manifest.json`).then((res) => {
|
||||
fetch(mapAssetUrl("manifest.json")).then((res) => {
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to load ${mapBasePath}/manifest.json`);
|
||||
throw new Error(`Failed to load ${mapAssetUrl("manifest.json")}`);
|
||||
}
|
||||
return res.json() as Promise<MapManifest>;
|
||||
}),
|
||||
),
|
||||
webpPath: `${mapBasePath}/thumbnail.webp`,
|
||||
webpPath: mapAssetUrl("thumbnail.webp"),
|
||||
} satisfies MapData;
|
||||
|
||||
this.maps.set(map, mapData);
|
||||
|
||||
@@ -4,7 +4,9 @@ import { GameMapLoader, MapData } from "./GameMapLoader";
|
||||
export class FetchGameMapLoader implements GameMapLoader {
|
||||
private maps: Map<GameMapType, MapData>;
|
||||
|
||||
public constructor(private readonly prefix: string | (() => string)) {
|
||||
public constructor(
|
||||
private readonly pathResolver: string | ((path: string) => string),
|
||||
) {
|
||||
this.maps = new Map<GameMapType, MapData>();
|
||||
}
|
||||
|
||||
@@ -35,12 +37,15 @@ export class FetchGameMapLoader implements GameMapLoader {
|
||||
return mapData;
|
||||
}
|
||||
|
||||
private getPrefix(): string {
|
||||
return typeof this.prefix === "function" ? this.prefix() : this.prefix;
|
||||
private resolveUrl(path: string): string {
|
||||
if (typeof this.pathResolver === "function") {
|
||||
return this.pathResolver(path);
|
||||
}
|
||||
return `${this.pathResolver}/${path}`;
|
||||
}
|
||||
|
||||
private url(map: string, path: string) {
|
||||
return `${this.getPrefix()}/${map}/${path}`;
|
||||
return this.resolveUrl(`${map}/${path}`);
|
||||
}
|
||||
|
||||
private async loadBinaryFromUrl(url: string) {
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
const ctx: Worker = self as any;
|
||||
globalThis.__ASSET_MANIFEST__ = __ASSET_MANIFEST__;
|
||||
let gameRunner: Promise<GameRunner> | null = null;
|
||||
const mapLoader = new FetchGameMapLoader(() => assetUrl("maps"));
|
||||
const mapLoader = new FetchGameMapLoader((path) => assetUrl(`maps/${path}`));
|
||||
// Yield threshold; not a backlog cap. Used to avoid monopolizing the worker task
|
||||
// and flooding the main thread with messages during catch-up.
|
||||
const MAX_TICKS_BEFORE_YIELD = 4;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import { FetchGameMapLoader } from "../../../src/core/game/FetchGameMapLoader";
|
||||
import { GameMapType } from "../../../src/core/game/Game";
|
||||
|
||||
describe("FetchGameMapLoader", () => {
|
||||
test("resolves each map file through the provided path resolver", async () => {
|
||||
const fetchMock = vi.fn(async (url: string) => ({
|
||||
ok: true,
|
||||
arrayBuffer: async () => new ArrayBuffer(0),
|
||||
json: async () => ({ url }),
|
||||
statusText: "OK",
|
||||
}));
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const loader = new FetchGameMapLoader(
|
||||
(path) => `/_assets/maps/${path}.hashed`,
|
||||
);
|
||||
const mapData = loader.getMapData(GameMapType.BritanniaClassic);
|
||||
|
||||
expect(mapData.webpPath).toBe(
|
||||
"/_assets/maps/britanniaclassic/thumbnail.webp.hashed",
|
||||
);
|
||||
|
||||
await mapData.manifest();
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(
|
||||
"/_assets/maps/britanniaclassic/manifest.json.hashed",
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user