import { exec, spawn } from "child_process"; import fs from "fs"; const logsPath = `./scripts/logs`; const logPath = `${logsPath}/factorio-update.log`; if (!fs.existsSync(logsPath)) fs.mkdirSync(logsPath); if (fs.existsSync(logPath)) fs.rmSync(logPath); /** Log command output to separate log file to minimize console output */ function logDebug(msg: string): void { fs.appendFileSync(logPath, msg); } async function runCommand(command: string, args?: string[]): Promise { return new Promise((resolve, reject) => { const proc = spawn(command, args); proc.stdout.on("data", (data: string) => { logDebug(data); }); proc.stderr.on("data", (data: string) => { logDebug(data); }); proc.on("error", (code) => { reject(code); }); proc.on("exit", (code) => { resolve(code); }); }); } const FACTORIO_BIN_PATH = `C:\\Program Files\\Factorio\\bin\\x64\\factorio.exe`; /** * Dumps data.raw as JSON to the script output folder and exits. * the output are genereate in Factorio data folder under script-output/. * more at https://wiki.factorio.com/Command_line_parameters * @returns */ export const dumpFactorioData = async () => { await runCommand(FACTORIO_BIN_PATH, ["--dump-data"]); await waitForFactorio(true, 10000); await waitForFactorio(false, 30000); }; /** * Dumps all prototypes name and description (if they have a valid value) to the script output folder and exits. * the output are genereate in Factorio data folder under script-output. * more at https://wiki.factorio.com/Command_line_parameters * @returns */ export const dumpFactorioLocale = async () => { await runCommand(FACTORIO_BIN_PATH, ["--dump-prototype-locale"]); await waitForFactorio(true, 10000); await waitForFactorio(false, 30000); }; export const dumpFactorioIcon = async () => { await runCommand(FACTORIO_BIN_PATH, ["--dump-icon-sprites"]); await waitForFactorio(true, 10000); await waitForFactorio(false, 60000); }; /** Check whether Factorio is running after a delay */ export async function checkIfFactorioIsRunning(delayMs = 1000): Promise { return new Promise((resolve, reject) => { setTimeout(() => { exec("tasklist", (err, stdout, _) => { if (err != null) reject(err); resolve(stdout.toLowerCase().includes("factorio.exe")); }); }, delayMs); }); } /** * Wait for factorio.exe to exit, since the image dump continues to run after * the batch script exits. */ async function waitForFactorio(running: boolean, waitMs: number): Promise { const start = Date.now(); let result = false; let runtime = 0; do { result = await checkIfFactorioIsRunning(); runtime = Date.now() - start; } while (result !== running && runtime < waitMs); logDebug(`Waited ${runtime.toString()} for Factorio to ${running ? "start" : "exit"}\n`); }