Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Factorio script for finding recipe locale in data stage
--[[
The following code is released under the MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]
local non_entity_types = {
achievement = true,
["active-defense-equipment"] = true,
["ambient-sound"] = true,
ammo = true,
["ammo-category"] = true,
armor = true,
["autoplace-control"] = true,
["battery-equipment"] = true,
["belt-immunity-equipment"] = true,
blueprint = true,
["blueprint-book"] = true,
["build-entity-achievement"] = true,
capsule = true,
["combat-robot-count"] = true,
["construct-with-robots-achievement"] = true,
["copy-paste-tool"] = true,
["custom-input"] = true,
["damage-type"] = true,
["deconstruct-with-robots-achievement"] = true,
["deconstruction-item"] = true,
decorative = true,
["deliver-by-robots-achievement"] = true,
["dont-build-entity-achievement"] = true,
["dont-craft-manually-achievement"] = true,
["dont-use-entity-in-energy-production-achievement"] = true,
["editor-controller"] = true,
["energy-shield-equipment"] = true,
["equipment-category"] = true,
["equipment-grid"] = true,
["finish-the-game-achievement"] = true,
fluid = true,
font = true,
["fuel-category"] = true,
["generator-equipment"] = true,
["god-controller"] = true,
["group-attack-achievement"] = true,
["gui-style"] = true,
gun = true,
item = true,
["item-group"] = true,
["item-subgroup"] = true,
["item-with-entity-data"] = true,
["item-with-inventory"] = true,
["item-with-label"] = true,
["item-with-tags"] = true,
["kill-achievement"] = true,
["map-gen-presets"] = true,
["map-settings"] = true,
["mining-tool"] = true,
module = true,
["module-category"] = true,
["mouse-cursor"] = true,
["movement-bonus-equipment"] = true,
["night-vision-equipment"] = true,
["noise-expression"] = true,
["noise-layer"] = true,
["optimized-decorative"] = true,
["player-damaged-achievement"] = true,
["produce-achievement"] = true,
["produce-per-hour-achievement"] = true,
recipe = true,
["recipe-category"] = true,
["repair-tool"] = true,
["research-achievement"] = true,
["resource-category"] = true,
["roboport-equipment"] = true,
["selection-tool"] = true,
shortcut = true,
["solar-panel-equipment"] = true,
sound = true,
["spectator-controller"] = true,
sprite = true,
technology = true,
tile = true,
tool = true,
["train-path-achievement"] = true,
["trigger-target-type"] = true,
["trivial-smoke"] = true,
tutorial = true,
["upgrade-item"] = true,
["utility-constants"] = true,
["utility-sounds"] = true,
["utility-sprites"] = true,
["virtual-signal"] = true,
["wind-sound"] = true
}
local function find_item_prototype(name)
--- Find the prototype for an item with the given name.
--- This assumes that items and only items have `stack_size` defined.
for type, prototypes in pairs(data.raw) do
local prototype = prototypes[name]
if prototype ~= nil and prototype.stack_size ~= nil then return prototype; end
end
return nil
end
local function find_entity_prototype(name)
--- Find the prototype for an entity with the given name.
for type, prototypes in pairs(data.raw) do
if not non_entity_types[type] and prototypes[name] then return prototypes[name]; end
end
return nil
end
local function find_equipment_prototype(name)
--- Find the prototype for an equipment with the given name.
for type, prototypes in pairs(data.raw) do
if type:match('-equipment') and prototypes[name] then return prototypes[name]; end
end
return nil
end
local function get_equipment_locale(name)
--- Get the localised name of the equipment with the given name.
local equipment = find_equipment_prototype(name)
if equipment.localised_name then return equipment.localised_name
else return {'equipment-name.'..name}; end
end
local function get_entity_locale(name)
--- Get the localised name of the entity with the given name.
local entity = find_entity_prototype(name)
if entity.localised_name then return entity.localised_name
else return {'entity-name.'..name}; end
end
local function get_item_locale(name)
--- Get the localised name of the item with the given name.
local item = find_item_prototype(name)
if item.localised_name then return item.localised_name
elseif item.place_result then return get_entity_locale(item.place_result)
elseif item.placed_as_equipment_result then return get_equipment_locale(item.placed_as_equipment_result)
else return {'item-name.'..name}; end
end
local function get_fluid_locale(name)
--- Get the localised name of the fluid with the given name.
local fluid = data.raw['fluid'][name]
if fluid.localised_name then return fluid.localised_name
else return {'fluid-name.'..name}; end
end
local function parse_product(product)
--- Get a pair of `name, type` from the given product.
if type(product) == 'string' then return product, 'item'
elseif product.name then return product.name, product.type
else return product[1], 'item'; end
end
local function find_product(recipe, product_name)
--- Get a pair of `name, type` for the given product name in the given recipe.
if recipe.results then
for _, product in pairs(recipe.results) do
local name, type = parse_product(product)
if name == product_name then return name, type; end
end
elseif recipe.result == product_name then return product_name, 'item'
else return nil, nil; end
end
local function get_main_product(recipe)
--- Get a pair of `name, type` for the main product of the recipe.
if recipe.main_product == '' then return nil, nil
elseif recipe.main_product ~= nil then return find_product(recipe, recipe.main_product)
elseif recipe.results then
if table_size(recipe.results) == 1 then return parse_product(recipe.results[1])
else return nil, nil; end
else return parse_product(recipe.result); end
end
local function get_recipe_locale(recipe)
--- Get the localised name for the given recipe.
if recipe.localised_name then return recipe.localised_name; end
if recipe.normal ~= nil and recipe.expensive ~= nil then
local normal_product, normal_type = get_main_product(recipe.normal)
local expensive_product, expensive_type = get_main_product(recipe.expensive)
if normal_product ~= nil and normal_product == expensive_product and normal_type == expensive_type then
if normal_type == 'item' then return get_item_locale(normal_product)
else return get_fluid_locale(normal_product); end
else return {'recipe-name.'..recipe.name}; end
end
local main_product, main_type = get_main_product(recipe.normal or recipe.expensive or recipe)
if main_product ~= nil then
if main_type == 'item' then return get_item_locale(main_product)
else return get_fluid_locale(main_product); end
else return {'recipe-name.'..recipe.name}; end
end
return get_recipe_locale
@ST-DDT
Copy link

ST-DDT commented Nov 27, 2019

https://gist.github.com/theRustyKnife/4703994a3811a8041f43dde61affe5ab#file-recipe_locale-lua-L143

I used the following there for now:

	if fluid.localised_name then return fluid.localised_name
	else return {'fluid-name.'..name}; end

But this code works very well, tested with all bobs + GDIW.
Now this only needs a similar set of methods for the description

Loading

@ST-DDT
Copy link

ST-DDT commented Nov 27, 2019

Maybe add a return get_recipe_locale (or something similar) to the EOF. That way you could import it easily like this:

local get_recipe_locale = require "recipe_locale"

Loading

@ST-DDT
Copy link

ST-DDT commented Nov 27, 2019

Under which license do you publish this code?

Loading

@theRustyKnife
Copy link
Author

theRustyKnife commented Nov 27, 2019

What you did in the get_fluid_locale function is exactly what was supposed to be there, I just forgot to put it back while refactoring :| I also added the return as suggested, tho I might make this into a proper module, since some of the other functions could be useful as well and I want to add the description version.

As for the license, I used MIT.

Note that I only made the changes in the github editor, so there's a very real chance there's a typo or something in there...

Loading

@theRustyKnife
Copy link
Author

theRustyKnife commented Jan 21, 2020

I made this into an actual library: https://mods.factorio.com/mod/rusty-locale
It supports both name and description, with a bunch of other stuff that I thought might be useful.

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment