201 lines
5.7 KiB
Lua

local calc_util = require("__RateCalculator__/scripts/calc-util")
local gui = require("__RateCalculator__/scripts/gui")
--- @class Set<T>: { [T]: boolean }
--- @alias CalculationError
--- | "max-crafting-speed"
--- | "incompatible-science-packs"
--- | "no-active-research"
--- | "no-input-fluid"
--- | "no-fuel"
--- | "no-mineable-resources"
--- | "no-power"
--- | "no-recipe"
--- @class CalculationSet
--- @field completed Set<string>
--- @field errors Set<CalculationError>
--- @field player LuaPlayer
--- @field rates table<string, Rates>
--- @field research_data ResearchData?
--- @alias MachineCounts table<string, uint>
--- @class Rate
--- @field machine_counts MachineCounts
--- @field machines integer
--- @field rate double
--- @class Rates
--- @field type string
--- @field name string
--- @field temperature double?
--- @field output Rate
--- @field input Rate
--- @class ResearchData
--- @field ingredients Ingredient[]
--- @field multiplier double
--- @field speed_modifier double
--- @param player LuaPlayer
--- @return CalculationSet
local function new_calculation_set(player)
local force = player.force
local current_research = force.current_research
--- @type ResearchData?
local research_data
if current_research then
research_data = {
ingredients = current_research.research_unit_ingredients,
multiplier = 1 / (current_research.research_unit_energy / 60),
speed_modifier = force.laboratory_speed_modifier,
}
end
return {
completed = {},
errors = {},
player = player,
rates = {},
research_data = research_data,
}
end
--- @param set CalculationSet
--- @param entity LuaEntity
--- @param invert boolean
local function process_entity(set, entity, invert)
local emissions_per_second = entity.prototype.emissions_per_second
local type = entity.type
if type == "burner-generator" or type == "generator" then
calc_util.add_rate(
set,
"output",
"item",
"rcalc-power-dummy",
entity.prototype.max_power_output * 60,
invert,
entity.name
)
elseif type ~= "burner-generator" and entity.prototype.electric_energy_source_prototype then
emissions_per_second = calc_util.process_electric_energy_source(set, entity, invert, emissions_per_second)
elseif entity.prototype.fluid_energy_source_prototype then
emissions_per_second = calc_util.process_fluid_energy_source(set, entity, invert, emissions_per_second)
elseif entity.prototype.heat_energy_source_prototype then
calc_util.process_heat_energy_source(set, entity, invert)
end
if entity.burner then
emissions_per_second = calc_util.process_burner(set, entity, invert, emissions_per_second)
end
if type == "assembling-machine" or type == "furnace" or type == "rocket-silo" then
emissions_per_second = calc_util.process_crafter(set, entity, invert, emissions_per_second)
elseif type == "beacon" then
calc_util.process_beacon(set, entity)
elseif type == "boiler" then
calc_util.process_boiler(set, entity, invert)
elseif type == "lab" then
calc_util.process_lab(set, entity, invert)
elseif type == "generator" then
calc_util.process_generator(set, entity, invert)
elseif type == "mining-drill" then
calc_util.process_mining_drill(set, entity, invert)
elseif type == "offshore-pump" then
calc_util.process_offshore_pump(set, entity, invert)
elseif type == "reactor" then
calc_util.process_reactor(set, entity, invert)
end
if emissions_per_second > 0 then
calc_util.add_rate(set, "output", "item", "rcalc-pollution-dummy", emissions_per_second, invert, entity.name)
elseif emissions_per_second < 0 then
calc_util.add_rate(set, "input", "item", "rcalc-pollution-dummy", -emissions_per_second, invert, entity.name)
end
end
--- @param set CalculationSet
--- @param entities LuaEntity[]
--- @param invert boolean
local function process_entities(set, entities, invert)
for _, entity in pairs(entities) do
process_entity(set, entity, invert)
end
end
--- @param e EventData.on_player_selected_area
local function on_player_selected_area(e)
if e.item ~= "rcalc-selection-tool" then
return
end
if not next(e.entities) then
return
end
local player = game.get_player(e.player_index)
if not player then
return
end
local set = new_calculation_set(player)
process_entities(set, e.entities, false)
gui.build_and_show(player, set, true)
if player.mod_settings["rcalc-dismiss-tool-on-selection"].value then
player.clear_cursor()
end
end
--- @param e EventData.on_player_alt_selected_area
local function on_player_alt_selected_area(e)
if e.item ~= "rcalc-selection-tool" then
return
end
if not next(e.entities) then
return
end
local player = game.get_player(e.player_index)
if not player then
return
end
local set = gui.get_current_set(player)
if not set then
set = new_calculation_set(player)
end
set.errors = {}
process_entities(set, e.entities, false)
gui.build_and_show(player, set)
end
--- @param e EventData.on_player_reverse_selected_area
local function on_player_alt_reverse_selected_area(e)
if e.item ~= "rcalc-selection-tool" then
return
end
if not next(e.entities) then
return
end
local player = game.get_player(e.player_index)
if not player then
return
end
local set = gui.get_current_set(player)
if not set then
set = new_calculation_set(player)
end
set.errors = {}
process_entities(set, e.entities, true)
gui.build_and_show(player, set)
end
--- @class Calc
local calc = {}
calc.events = {
[defines.events.on_player_alt_reverse_selected_area] = on_player_alt_reverse_selected_area,
[defines.events.on_player_alt_selected_area] = on_player_alt_selected_area,
[defines.events.on_player_selected_area] = on_player_selected_area,
}
return calc