186 lines
5.0 KiB
Lua
186 lines
5.0 KiB
Lua
--- Utilities for data stage prototype manipulation.
|
|
--- ```lua
|
|
--- local flib_data_util = require("__flib__/data-util")
|
|
--- ```
|
|
--- @class flib_data_util
|
|
local flib_data_util = {}
|
|
|
|
--- Copy a prototype, assigning a new name and minable properties.
|
|
--- @param prototype table
|
|
--- @param new_name string string
|
|
--- @param remove_icon? boolean
|
|
--- @return table
|
|
function flib_data_util.copy_prototype(prototype, new_name, remove_icon)
|
|
if not prototype.type or not prototype.name then
|
|
error("Invalid prototype: prototypes must have name and type properties.")
|
|
return --- @diagnostic disable-line
|
|
end
|
|
local p = table.deepcopy(prototype)
|
|
p.name = new_name
|
|
if p.minable and p.minable.result then
|
|
p.minable.result = new_name
|
|
end
|
|
if p.place_result then
|
|
p.place_result = new_name
|
|
end
|
|
if p.result then
|
|
p.result = new_name
|
|
end
|
|
if p.results then
|
|
for _, result in pairs(p.results) do
|
|
if result.name == prototype.name then
|
|
result.name = new_name
|
|
end
|
|
end
|
|
end
|
|
if remove_icon then
|
|
p.icon = nil
|
|
p.icon_size = nil
|
|
p.icon_mipmaps = nil
|
|
p.icons = nil
|
|
end
|
|
|
|
return p
|
|
end
|
|
|
|
--- Copy prototype.icon/icons to a new fully defined icons array, optionally adding new icon layers.
|
|
---
|
|
--- Returns `nil` if the prototype's icons are incorrectly or incompletely defined.
|
|
--- @param prototype table
|
|
--- @param new_layers? IconSpecification[]
|
|
--- @return IconSpecification[]|nil
|
|
function flib_data_util.create_icons(prototype, new_layers)
|
|
if new_layers then
|
|
for _, new_layer in pairs(new_layers) do
|
|
if not new_layer.icon or not new_layer.icon_size then
|
|
return nil
|
|
end
|
|
end
|
|
end
|
|
|
|
if prototype.icons then
|
|
local icons = {}
|
|
for _, v in pairs(prototype.icons) do
|
|
-- Over define as much as possible to minimize weirdness: https://forums.factorio.com/viewtopic.php?f=25&t=81980
|
|
icons[#icons + 1] = {
|
|
icon = v.icon,
|
|
icon_size = v.icon_size or prototype.icon_size or 32,
|
|
icon_mipmaps = v.icon_mipmaps or prototype.icon_mipmaps or 0,
|
|
tint = v.tint,
|
|
scale = v.scale or 1,
|
|
shift = v.shift,
|
|
}
|
|
end
|
|
if new_layers then
|
|
for _, new_layer in pairs(new_layers) do
|
|
icons[#icons + 1] = new_layer
|
|
end
|
|
end
|
|
return icons
|
|
elseif prototype.icon then
|
|
local icons = {
|
|
{
|
|
icon = prototype.icon,
|
|
icon_size = prototype.icon_size,
|
|
icon_mipmaps = prototype.icon_mipmaps,
|
|
tint = { r = 1, g = 1, b = 1, a = 1 },
|
|
},
|
|
}
|
|
if new_layers then
|
|
for _, new_layer in pairs(new_layers) do
|
|
icons[#icons + 1] = new_layer
|
|
end
|
|
end
|
|
return icons
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
local exponent_multipliers = {
|
|
["y"] = 0.000000000000000000000001,
|
|
["z"] = 0.000000000000000000001,
|
|
["a"] = 0.000000000000000001,
|
|
["f"] = 0.000000000000001,
|
|
["p"] = 0.000000000001,
|
|
["n"] = 0.000000001,
|
|
["u"] = 0.000001, -- μ is invalid
|
|
["m"] = 0.001,
|
|
["c"] = 0.01,
|
|
["d"] = 0.1,
|
|
[""] = 1,
|
|
["da"] = 10,
|
|
["h"] = 100,
|
|
["k"] = 1000,
|
|
["M"] = 1000000,
|
|
["G"] = 1000000000,
|
|
["T"] = 1000000000000,
|
|
["P"] = 1000000000000000,
|
|
["E"] = 1000000000000000000,
|
|
["Z"] = 1000000000000000000000,
|
|
["Y"] = 1000000000000000000000000,
|
|
}
|
|
|
|
--- Convert an energy string to base unit value + suffix.
|
|
---
|
|
--- Returns `nil` if `energy_string` is incorrectly formatted.
|
|
--- @param energy_string string
|
|
--- @return number?
|
|
--- @return string?
|
|
function flib_data_util.get_energy_value(energy_string)
|
|
if type(energy_string) == "string" then
|
|
local v, _, exp, unit = string.match(energy_string, "([%-+]?[0-9]*%.?[0-9]+)((%D*)([WJ]))")
|
|
local value = tonumber(v)
|
|
if value and exp and exponent_multipliers[exp] then
|
|
value = value * exponent_multipliers[exp]
|
|
return value, unit
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
--- Build a sprite from constituent parts.
|
|
--- @param name? string
|
|
--- @param position? MapPosition
|
|
--- @param filename? string
|
|
--- @param size? Vector
|
|
--- @param mipmap_count? number
|
|
--- @param mods? table
|
|
--- @return SpriteSpecification
|
|
function flib_data_util.build_sprite(name, position, filename, size, mipmap_count, mods)
|
|
local def = {
|
|
type = "sprite",
|
|
name = name,
|
|
filename = filename,
|
|
position = position,
|
|
size = size,
|
|
mipmap_count = mipmap_count,
|
|
flags = { "icon" },
|
|
}
|
|
if mods then
|
|
for k, v in pairs(mods) do
|
|
def[k] = v
|
|
end
|
|
end
|
|
return def
|
|
end
|
|
|
|
--- An empty image. This image is 8x8 to facilitate usage with GUI styles.
|
|
flib_data_util.empty_image = "__flib__/graphics/empty.png"
|
|
|
|
--- A black image, for use with tool backgrounds. This image is 1x1.
|
|
flib_data_util.black_image = "__flib__/graphics/black.png"
|
|
|
|
--- A desaturated planner image. Tint this sprite to easily add your own planners.
|
|
flib_data_util.planner_base_image = "__flib__/graphics/planner.png"
|
|
|
|
--- A dark red button tileset. Used for the `flib_tool_button_dark_red` style.
|
|
flib_data_util.dark_red_button_tileset = "__flib__/graphics/dark-red-button.png"
|
|
|
|
return flib_data_util
|
|
|
|
--- @class IconSpecification
|
|
--- @field icon string
|
|
--- @field icon_size int
|
|
--- @class SpriteSpecification
|