65 lines
1.9 KiB
TypeScript

import type { CampaignInventory } from "./campaign-types.ts";
import { dirname, resolve } from "@std/path";
function isCampaignInventory(raw: unknown): raw is CampaignInventory {
const r = raw as CampaignInventory | null;
if (!r || r.version !== 1) return false;
if (typeof r.outputFolderName !== "string" || !r.outputFolderName.trim()) {
return false;
}
if (!r.info || typeof r.info !== "object") return false;
if (typeof r.info.name !== "string") return false;
if (!Array.isArray(r.mapPositions) || !Array.isArray(r.missions)) {
return false;
}
return true;
}
export function parseCampaignInventory(json: unknown): CampaignInventory {
if (!isCampaignInventory(json)) {
throw new Error(
"Invalid campaign.inventory.json: expected version 1 with info, mapPositions, missions",
);
}
return json;
}
export async function readCampaignInventory(
path: string,
): Promise<CampaignInventory> {
const text = await Deno.readTextFile(path);
const data = JSON.parse(text) as unknown;
return parseCampaignInventory(data);
}
export async function writeCampaignInventory(
path: string,
inv: CampaignInventory,
): Promise<void> {
const dir = dirname(resolve(path));
await Deno.mkdir(dir, { recursive: true });
await Deno.writeTextFile(path, JSON.stringify(inv, null, 2) + "\n");
}
export function nextMissionIndex(inv: CampaignInventory): number {
if (inv.missions.length === 0) return 0;
return Math.max(...inv.missions.map((m) => m.index)) + 1;
}
export function defaultInventoryTemplate(): CampaignInventory {
return {
version: 1,
outputFolderName: "OurCampaign",
info: {
name: "New Campaign",
desc: "Subtitle",
bigDesc: "Long description for the campaign detail panel.",
allUnlocked: false,
mapHeight: 500,
backgroundAlpha: 1,
},
mapPositions: [],
missions: [],
};
}