| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import fs from "fs";
- import { checkIcons, dataRawPath, getJsonData, scriptOutputPath } from "./helpers/file.helper.ts";
- import type { Beacon, Item, Machine, Module, Quality, RecipeCategory, Signal } from "./process-data.models.ts";
- import { groupPrototypes, type Group } from "./helpers/groups.helper.ts";
- import { parseRecipe, type Recipe } from "./helpers/recipes.helper.ts";
- import type { ProcessedData } from "./process-data.models.ts";
- import { buildIconTextureMap, walkForIcons } from "./helpers/icons.helper.ts";
- import path from "path";
- import { ENTITY_KEYS, ITEM_KEYS, SPACE_LOCATION_KEYS } from "./lua-api/const.ts";
- import type { FactorioRawData } from "./lua-api/models.ts";
- const isNotHidden = (o: unknown) => !(o as { hidden?: boolean }).hidden;
- /**
- * Extract machines.
- */
- function extractMachines(data: FactorioRawData): Machine[] {
- return Object.values(data["assembling-machine"] ?? {})
- .filter(isNotHidden)
- .map((machine) => ({
- name: machine.name,
- icon: `entity/${machine.name}.png`,
- crafting_categories: machine.crafting_categories,
- crafting_speed: machine.crafting_speed,
- allowed_effects: machine.allowed_effects,
- module_slots: machine.module_slots,
- selection_box: machine.selection_box,
- effect_receiver: machine.effect_receiver,
- }));
- }
- /**
- * Extract modules.
- */
- function extractModules(data: FactorioRawData): Module[] {
- return Object.values(data.module ?? {})
- .filter(isNotHidden)
- .map((module) => ({
- name: module.name,
- icon: `item/${module.name}.png`,
- subgroup: module.subgroup,
- category: module.category,
- tier: module.tier,
- order: module.order,
- effect: module.effect,
- }));
- }
- /**
- * Extract beacon.
- */
- function extractBeacon(data: FactorioRawData): Beacon[] {
- return Object.values(data.beacon ?? {})
- .filter(isNotHidden)
- .map((beacon) => ({
- name: beacon.name,
- icon: `item/${beacon.name}.png`,
- subgroup: beacon.subgroup,
- distribution_effectivity: beacon.distribution_effectivity,
- distribution_effectivity_bonus_per_quality_level: beacon.distribution_effectivity_bonus_per_quality_level,
- module_slots: beacon.module_slots,
- allowed_effects: beacon.allowed_effects,
- profile: beacon.profile,
- }));
- }
- /**
- * Extract all items (and item‑like things) from the raw dump.
- */
- function extractItems(dataRaw: FactorioRawData): Record<string, Item> {
- return ITEM_KEYS.reduce((acc: Record<string, Item>, key) => {
- const data = dataRaw[key];
- Object.values(data ?? {}).forEach((item) => {
- const isFluid = item.type === "fluid";
- acc[item.name] = {
- name: item.name,
- hidden: !isNotHidden(item),
- icon: `${isFluid ? "fluid" : "item"}/${item.name}.png`,
- subgroup: item.subgroup ?? (isFluid ? "fluid" : "other"),
- order: item.order,
- };
- });
- return acc;
- }, {});
- }
- export async function processData(outputFolder: string) {
- const data = getJsonData(dataRawPath) as FactorioRawData;
- const items = extractItems(data);
- const machines = extractMachines(data);
- const modules = extractModules(data);
- const recipeCategories: RecipeCategory[] = Object.values(data["recipe-category"] ?? {})
- .filter(isNotHidden)
- .map((c) => ({ name: c.name, subgroup: c.subgroup, order: c.order }));
- const recipes = Object.values(data["recipe"] ?? {})
- .filter(isNotHidden)
- .map((o) => parseRecipe(o, items));
- const qualityLevels: Quality[] = Object.values(data.quality ?? {})
- .filter(isNotHidden)
- .map((o) => ({
- ...o,
- icon: `quality/${o.name}.png`,
- }));
- const signals: Record<string, Signal> = {};
- const EXCLUDED_ENTITY: Array<keyof FactorioRawData> = [
- "corpse",
- "rail-remnants",
- "sticker",
- "elevated-straight-rail",
- "straight-rail",
- ];
- const signalGroups: { signalType: string; entityTypes: Array<keyof FactorioRawData> }[] = [
- { signalType: "virtual-signal", entityTypes: ["virtual-signal"] },
- { signalType: "quality", entityTypes: ["quality"] },
- { signalType: "entity", entityTypes: ENTITY_KEYS },
- { signalType: "space-location", entityTypes: SPACE_LOCATION_KEYS },
- ];
- for (let { signalType, entityTypes } of signalGroups)
- for (let entityTypeName of entityTypes) {
- let entries = data[entityTypeName];
- console.log(entityTypeName);
- if (entries !== undefined)
- for (let entry of Object.values(entries)) {
- if (isNotHidden(entry) && !EXCLUDED_ENTITY.includes(entry.type) && !entry.deconstruction_alternative)
- signals[entry.name] = {
- type: signalType,
- name: entry.name,
- subgroup: entry.subgroup ?? "other",
- icon: `${signalType}/${entry.name}.png`,
- order: entry.order,
- };
- }
- }
- for (let item of Object.values(items)) {
- if (!item.hidden) {
- const signal = {
- name: item.name,
- type: "item",
- subgroup: item.subgroup ?? "",
- icon: item.icon,
- order: item.order,
- };
- let k = item.name;
- if (k in signals) {
- if (signal.subgroup && signals[k].subgroup != "other" && signals[k].subgroup != signal.subgroup) {
- k = "item." + k;
- } else {
- console.log(`Existing entry for ${k} in the same group`);
- }
- }
- signals[k] = signal;
- }
- }
- for (let recipe of recipes) {
- if (!(recipe.name in signals))
- signals[recipe.name] = {
- type: "recipe",
- name: recipe.name,
- subgroup: recipe.subgroup ?? "",
- icon: recipe.icon,
- order: recipe.order,
- };
- }
- const recipeGroup: Array<Group<Recipe>> = groupPrototypes(recipes, data, true);
- const signalGroup: Array<Group<Signal>> = groupPrototypes(Object.values(signals), data, true);
- const beacons = extractBeacon(data);
- const output: ProcessedData = {
- qualityLevels,
- machines,
- beacons,
- modules,
- recipeCategories,
- recipeGroup,
- signalGroup,
- };
- fs.mkdirSync(outputFolder, { recursive: true });
- const icons = new Set<string>();
- walkForIcons(output, icons);
- const iconsList = Array.from(icons).sort();
- checkIcons(iconsList);
- fs.writeFileSync(path.resolve(outputFolder, "data.json"), JSON.stringify(output, null, 2), "utf-8");
- await buildIconTextureMap(iconsList, scriptOutputPath, outputFolder);
- }
|