265 lines
7.7 KiB
Lua
265 lines
7.7 KiB
Lua
local bounding_box = require("__flib__.bounding-box")
|
|
local dictionary = require("__flib__.dictionary-lite")
|
|
local format = require("__flib__.format")
|
|
local math = require("__flib__.math")
|
|
local table = require("__flib__.table")
|
|
|
|
local constants = require("constants")
|
|
|
|
local core_util = require("__core__.lualib.util")
|
|
|
|
local util = {}
|
|
|
|
--- @return AmountIdent
|
|
function util.build_amount_ident(input)
|
|
--- @class AmountIdent
|
|
return {
|
|
amount = input.amount or false,
|
|
amount_min = input.amount_min or false,
|
|
amount_max = input.amount_max or false,
|
|
catalyst_amount = input.catalyst_amount or false,
|
|
probability = input.probability or false,
|
|
format = input.format or "format_amount",
|
|
}
|
|
end
|
|
|
|
-- HACK: Requiring `formatter` in this file causes a dependency loop
|
|
local function format_number(value)
|
|
return format.number(math.round(value, 0.01))
|
|
end
|
|
|
|
--- @class TemperatureIdent
|
|
--- @field string string
|
|
--- @field short_string string
|
|
--- @field min double
|
|
--- @field max double
|
|
|
|
--- Builds a `TemperatureIdent` based on the fluid input/output parameters.
|
|
function util.build_temperature_ident(fluid)
|
|
local temperature = fluid.temperature
|
|
local temperature_min = fluid.minimum_temperature
|
|
local temperature_max = fluid.maximum_temperature
|
|
local temperature_string
|
|
local short_temperature_string
|
|
local short_top_string
|
|
if temperature then
|
|
temperature_string = format_number(temperature)
|
|
short_temperature_string = core_util.format_number(temperature, true)
|
|
temperature_min = temperature
|
|
temperature_max = temperature
|
|
elseif temperature_min and temperature_max then
|
|
if temperature_min == math.min_double then
|
|
temperature_string = "≤" .. format_number(temperature_max)
|
|
short_temperature_string = "≤" .. core_util.format_number(temperature_max, true)
|
|
elseif temperature_max == math.max_double then
|
|
temperature_string = "≥" .. format_number(temperature_min)
|
|
short_temperature_string = "≥" .. core_util.format_number(temperature_min, true)
|
|
else
|
|
temperature_string = "" .. format_number(temperature_min) .. "-" .. format_number(temperature_max)
|
|
short_temperature_string = core_util.format_number(temperature_min, true)
|
|
short_top_string = core_util.format_number(temperature_max, true)
|
|
end
|
|
end
|
|
|
|
if temperature_string then
|
|
return {
|
|
string = temperature_string,
|
|
short_string = short_temperature_string,
|
|
short_top_string = short_top_string,
|
|
min = temperature_min,
|
|
max = temperature_max,
|
|
}
|
|
end
|
|
end
|
|
|
|
--- Get the "sorting number" of a temperature. Will sort in ascending order, with absolute, then min range, then max range.
|
|
--- @param temperature_ident TemperatureIdent
|
|
function util.get_sorting_number(temperature_ident)
|
|
if temperature_ident.min == math.min_double then
|
|
return temperature_ident.max + 0.001
|
|
elseif temperature_ident.max == math.max_double then
|
|
return temperature_ident.min + 0.003
|
|
elseif temperature_ident.min ~= temperature_ident.max then
|
|
return temperature_ident.min + 0.002
|
|
else
|
|
return temperature_ident.min
|
|
end
|
|
end
|
|
|
|
function util.convert_and_sort(tbl)
|
|
for key in pairs(tbl) do
|
|
tbl[#tbl + 1] = key
|
|
end
|
|
table.sort(tbl)
|
|
return tbl
|
|
end
|
|
|
|
function util.unique_string_array(initial_tbl)
|
|
initial_tbl = initial_tbl or {}
|
|
local hash = {}
|
|
for _, value in pairs(initial_tbl) do
|
|
hash[value] = true
|
|
end
|
|
return setmetatable(initial_tbl, {
|
|
__newindex = function(tbl, key, value)
|
|
if not hash[value] then
|
|
hash[value] = true
|
|
rawset(tbl, key, value)
|
|
end
|
|
end,
|
|
})
|
|
end
|
|
|
|
function util.unique_obj_array(initial_tbl)
|
|
local hash = {}
|
|
return setmetatable(initial_tbl or {}, {
|
|
__newindex = function(tbl, key, value)
|
|
if not hash[value.name] then
|
|
hash[value.name] = true
|
|
rawset(tbl, key, value)
|
|
end
|
|
end,
|
|
})
|
|
end
|
|
|
|
function util.frame_action_button(sprite, tooltip, ref, action)
|
|
return {
|
|
type = "sprite-button",
|
|
style = "frame_action_button",
|
|
sprite = sprite .. "_white",
|
|
hovered_sprite = sprite .. "_black",
|
|
clicked_sprite = sprite .. "_black",
|
|
tooltip = tooltip,
|
|
mouse_button_filter = { "left" },
|
|
ref = ref,
|
|
actions = {
|
|
on_click = action,
|
|
},
|
|
}
|
|
end
|
|
|
|
function util.process_placed_by(prototype)
|
|
local placed_by = prototype.items_to_place_this
|
|
if placed_by then
|
|
return table.map(placed_by, function(item_stack)
|
|
return {
|
|
class = "item",
|
|
name = item_stack.name,
|
|
amount_ident = util.build_amount_ident({ amount = item_stack.count }),
|
|
}
|
|
end)
|
|
end
|
|
end
|
|
|
|
function util.convert_categories(source_tbl, class)
|
|
local categories = {}
|
|
for category in pairs(source_tbl) do
|
|
categories[#categories + 1] = { class = class, name = category }
|
|
end
|
|
return categories
|
|
end
|
|
|
|
function util.convert_to_ident(class, source)
|
|
if source then
|
|
return { class = class, name = source }
|
|
end
|
|
end
|
|
|
|
--- @param prototype LuaEntityPrototype
|
|
--- @return DisplayResolution?
|
|
function util.get_size(prototype)
|
|
if prototype.selection_box then
|
|
local box = prototype.selection_box
|
|
return { height = math.ceil(bounding_box.height(box)), width = math.ceil(bounding_box.width(box)) }
|
|
end
|
|
end
|
|
|
|
--- @param prototype LuaEntityPrototype
|
|
function util.process_energy_source(prototype)
|
|
local burner = prototype.burner_prototype
|
|
local fluid_energy_source = prototype.fluid_energy_source_prototype
|
|
if burner then
|
|
return util.convert_categories(burner.fuel_categories, "fuel_category")
|
|
elseif fluid_energy_source then
|
|
local filter = fluid_energy_source.fluid_box.filter
|
|
if filter then
|
|
return {}, { class = "fluid", name = filter.name }
|
|
end
|
|
return { { class = "fuel_category", name = "burnable-fluid" } }
|
|
end
|
|
return {}
|
|
end
|
|
|
|
--- Safely retrive the given GUI, checking for validity.
|
|
--- @param player_index number
|
|
--- @param gui_name string
|
|
--- @param gui_key number|string?
|
|
function util.get_gui(player_index, gui_name, gui_key)
|
|
local player_table = global.players[player_index]
|
|
if not player_table then
|
|
return
|
|
end
|
|
local tbl = player_table.guis[gui_name]
|
|
if not tbl then
|
|
return
|
|
end
|
|
if gui_key then
|
|
tbl = tbl[gui_key]
|
|
end
|
|
if tbl and tbl.refs.window and tbl.refs.window.valid then
|
|
return tbl
|
|
end
|
|
end
|
|
|
|
--- Dispatch the given action on all GUIs of the given name.
|
|
--- @param player_index number
|
|
--- @param gui_name string
|
|
--- @param msg string|table
|
|
function util.dispatch_all(player_index, gui_name, msg)
|
|
local player_table = global.players[player_index]
|
|
if not player_table then
|
|
return
|
|
end
|
|
local ignored = gui_name == "info" and constants.ignored_info_ids or {}
|
|
for key, Gui in pairs(player_table.guis[gui_name]) do
|
|
if not ignored[key] then
|
|
Gui:dispatch(msg)
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Determine if the given prototype is blueprintable
|
|
--- @param prototype LuaEntityPrototype
|
|
--- @return boolean
|
|
function util.is_blueprintable(prototype)
|
|
return prototype.has_flag("player-creation")
|
|
and not prototype.has_flag("not-selectable-in-game")
|
|
and not prototype.has_flag("not-blueprintable")
|
|
and not prototype.has_flag("hidden")
|
|
end
|
|
|
|
--- Create a new dictionary only if not in on_load.
|
|
--- @param name string
|
|
--- @param initial_contents Dictionary?
|
|
function util.new_dictionary(name, initial_contents)
|
|
if game then
|
|
dictionary.new(name, initial_contents)
|
|
end
|
|
end
|
|
|
|
--- Add to the dictionary only if not in on_load.
|
|
--- @param dict string
|
|
--- @param key string
|
|
--- @param localised LocalisedString
|
|
function util.add_to_dictionary(dict, key, localised)
|
|
if game then
|
|
-- Fall back to internal key in non-description dictionaries
|
|
if not string.find(dict, "description") then
|
|
localised = { "?", localised, key }
|
|
end
|
|
dictionary.add(dict, key, localised)
|
|
end
|
|
end
|
|
|
|
return util
|