command.helper.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import { exec, spawn } from "child_process";
  2. import fs from "fs";
  3. const logsPath = `./scripts/logs`;
  4. const logPath = `${logsPath}/factorio-update.log`;
  5. if (!fs.existsSync(logsPath)) fs.mkdirSync(logsPath);
  6. if (fs.existsSync(logPath)) fs.rmSync(logPath);
  7. /** Log command output to separate log file to minimize console output */
  8. function logDebug(msg: string): void {
  9. fs.appendFileSync(logPath, msg);
  10. }
  11. async function runCommand(command: string, args?: string[]): Promise<number | null> {
  12. return new Promise((resolve, reject) => {
  13. const proc = spawn(command, args);
  14. proc.stdout.on("data", (data: string) => {
  15. logDebug(data);
  16. });
  17. proc.stderr.on("data", (data: string) => {
  18. logDebug(data);
  19. });
  20. proc.on("error", (code) => {
  21. reject(code);
  22. });
  23. proc.on("exit", (code) => {
  24. resolve(code);
  25. });
  26. });
  27. }
  28. const FACTORIO_BIN_PATH = `C:\\Program Files\\Factorio\\bin\\x64\\factorio.exe`;
  29. /**
  30. * Dumps data.raw as JSON to the script output folder and exits.
  31. * the output are genereate in Factorio data folder under script-output/.
  32. * more at https://wiki.factorio.com/Command_line_parameters
  33. * @returns
  34. */
  35. export const dumpFactorioData = async () => {
  36. await runCommand(FACTORIO_BIN_PATH, ["--dump-data"]);
  37. await waitForFactorio(true, 10000);
  38. await waitForFactorio(false, 30000);
  39. };
  40. /**
  41. * Dumps all prototypes name and description (if they have a valid value) to the script output folder and exits.
  42. * the output are genereate in Factorio data folder under script-output.
  43. * more at https://wiki.factorio.com/Command_line_parameters
  44. * @returns
  45. */
  46. export const dumpFactorioLocale = async () => {
  47. await runCommand(FACTORIO_BIN_PATH, ["--dump-prototype-locale"]);
  48. await waitForFactorio(true, 10000);
  49. await waitForFactorio(false, 30000);
  50. };
  51. export const dumpFactorioIcon = async () => {
  52. await runCommand(FACTORIO_BIN_PATH, ["--dump-icon-sprites"]);
  53. await waitForFactorio(true, 10000);
  54. await waitForFactorio(false, 60000);
  55. };
  56. /** Check whether Factorio is running after a delay */
  57. export async function checkIfFactorioIsRunning(delayMs = 1000): Promise<boolean> {
  58. return new Promise((resolve, reject) => {
  59. setTimeout(() => {
  60. exec("tasklist", (err, stdout, _) => {
  61. if (err != null) reject(err);
  62. resolve(stdout.toLowerCase().includes("factorio.exe"));
  63. });
  64. }, delayMs);
  65. });
  66. }
  67. /**
  68. * Wait for factorio.exe to exit, since the image dump continues to run after
  69. * the batch script exits.
  70. */
  71. async function waitForFactorio(running: boolean, waitMs: number): Promise<void> {
  72. const start = Date.now();
  73. let result = false;
  74. let runtime = 0;
  75. do {
  76. result = await checkIfFactorioIsRunning();
  77. runtime = Date.now() - start;
  78. } while (result !== running && runtime < waitMs);
  79. logDebug(`Waited ${runtime.toString()} for Factorio to ${running ? "start" : "exit"}\n`);
  80. }