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 { 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 { 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: [], }; }