| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- import type { FluidProductPrototype, ItemProductPrototype, RecipePrototype } from "../lua-api/models.ts";
- import type { Item } from "../process-data.models.ts";
- export type Ingredient = {
- type: "fluid" | "item";
- name: string;
- amount: number;
- };
- export type Recipe = {
- name: string;
- icon?: string;
- subgroup: string;
- order?: string;
- /** The [categories](prototype:RecipeCategory) of this recipe. Controls which machines can craft this recipe.
- The built-in categories can be found [here](https://wiki.factorio.com/Data.raw#recipe-category). The base `"crafting"` category can not contain recipes with fluid ingredients or products.
- The array must contain at least one category, it cannot be empty. */
- categories?: string[];
- /** The amount of time it takes to make this recipe. Must be `> 0.001`. Equals the number of seconds it takes to craft at crafting speed `1`. */
- energy_required?: number;
- /** Whether the recipe is allowed to have the extra inserter overload bonus applied (4 * stack inserter stack size). */
- allow_inserter_overload?: boolean;
- allow_productivity?: boolean;
- allow_quality?: boolean;
- allow_speed?: boolean;
- /** Used to determine how many extra items are put into an assembling machine before it's considered "full enough". See [insertion limits](https://wiki.factorio.com/Inserters#Insertion_limits).
- If set to `0`, it instead uses the following formula: `1.166 / (energy_required / the assembler's crafting_speed)`, rounded up, and clamped to be between`2` and `100`. The numbers used in this formula can be changed by the [UtilityConstants](prototype:UtilityConstants) properties `dynamic_recipe_overload_factor`, `minimum_recipe_overload_multiplier`, and `maximum_recipe_overload_multiplier`. */
- overload_multiplier?: number;
- ingredients?: Ingredient[];
- results?: Array<ItemProductPrototype | FluidProductPrototype>;
- };
- export function getRecipeIcon(recipe: RecipePrototype, mainProduct: Item | undefined): string {
- if (recipe.icons || recipe.icon) return `recipe/${recipe.name}.png`;
- if (mainProduct && mainProduct.icon) return mainProduct.icon;
- console.warn(`No icon found for :${recipe.name}`);
- return "";
- }
- export function getRecipeSubGroup(recipe: RecipePrototype, mainProduct: Item | undefined): string {
- if (recipe.subgroup) return recipe.subgroup;
- if (mainProduct) return mainProduct.subgroup;
- return "other";
- }
- export function getMainProductName(recipe: RecipePrototype): string {
- if (recipe.results?.length == 1) {
- return recipe.results[0].name;
- } else if (recipe.results && recipe.main_product) {
- const mainProduct = recipe.main_product;
- const result = recipe.results.find((r) => r.name === mainProduct);
- if (result) {
- return result.name;
- }
- throw new Error(`Main product '${mainProduct}' declared by recipe '${recipe.name}' not found in results`);
- }
- return "";
- }
- export function parseRecipe(recipe: RecipePrototype, itemsMap: Record<string, Item>): Recipe {
- const rawIngredient = Array.isArray(recipe.ingredients) ? recipe.ingredients : [];
- const ingredients = rawIngredient.map((i) => ({ name: i.name, amount: i.amount, type: i.type }));
- const mainProduct = itemsMap[getMainProductName(recipe)];
- const r: Recipe = {
- name: recipe.name,
- icon: getRecipeIcon(recipe, mainProduct),
- subgroup: getRecipeSubGroup(recipe, mainProduct),
- energy_required: recipe.energy_required,
- allow_inserter_overload: recipe.allow_inserter_overload,
- overload_multiplier: recipe.overload_multiplier,
- order: recipe.order ?? mainProduct.order,
- categories: recipe.categories ?? ["crafting"],
- ingredients,
- results: recipe.results,
- };
- if (recipe.allow_productivity) r.allow_productivity = true;
- if (recipe.allow_quality) r.allow_quality = true;
- if (recipe.allow_speed) r.allow_speed = true;
- return r;
- }
|