#!/usr/bin/env node import { spawn } from "node:child_process"; import path from "node:path"; import { fileURLToPath } from "node:url"; const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const scripts = path.join(projectRoot, "scripts", "asset-pipeline"); const forwarded = process.argv.slice(2); function hasOption(name) { return forwarded.includes(name); } function run(script, args) { return new Promise((resolve) => { const child = spawn(process.execPath, [path.join(scripts, script), ...args], { cwd: projectRoot, windowsHide: true, stdio: "inherit", }); child.once("error", () => resolve(1)); child.once("exit", (code) => resolve(code ?? 1)); }); } const compressionArgs = [ "public/assets/game/dungeons", "public/assets/game/creatures/shared", "--creatures-only", ...(!hasOption("--concurrency") ? ["--concurrency", "4"] : []), ...(!hasOption("--jobs") ? ["--jobs", "2"] : []), ...(!hasOption("--quality") ? ["--quality", "180"] : []), ...(!hasOption("--report") ? ["--report", "playtest-artifacts/performance/ktx2-creatures-compression.json"] : []), ...forwarded, ]; const compressionCode = await run("compress-ktx2.mjs", compressionArgs); // Always refresh after a partial pass. Successful outputs have new bytes even // if another file failed, and shared GLBs must never remain under stale hashes. const refreshCode = await run("refresh-creature-shipping-metadata.mjs", []); const auditCode = await run("audit-ktx2.mjs", [ "public/assets/game/dungeons", "public/assets/game/creatures/shared", "--creatures-only", "--require-all", "--report", "playtest-artifacts/performance/ktx2-creatures-after.json", ]); if (compressionCode || refreshCode || auditCode) process.exitCode = 1;