z_mirror/RateCalculator
git clone https://git.raiguard.me/z_mirror/RateCalculator
8cbeb98
trunk
1local calc_util =require ( "scripts.calc-util" ) 2 3local gui =require ( "scripts.gui" ) 4 5--- @class Set<T>: { [T]: boolean } 6 7--- @alias CalculationError 8--- | "max-crafting-speed" 9--- | "incompatible-science-packs" 10--- | "no-active-research" 11--- | "no-input-fluid" 12--- | "no-fuel" 13--- | "no-mineable-resources" 14--- | "no-power" 15--- | "no-recipe" 16 17--- @class CalculationSet 18--- @field completed Set<string> 19--- @field errors Set<CalculationError> 20--- @field player LuaPlayer 21--- @field rates table<string, Rates> 22--- @field research_data ResearchData? 23--- @field pollutant string 24 25--- @alias MachineCounts table<string, uint> 26 27--- @class Rate 28--- @field machine_counts MachineCounts 29--- @field machines integer 30--- @field rate double 31 32--- @class Rates 33--- @field type string 34--- @field name string 35--- @field quality string? 36--- @field temperature double? 37--- @field output Rate 38--- @field input Rate 39 40--- @class ResearchData 41--- @field ingredients Ingredient[] 42--- @field multiplier double 43--- @field speed_modifier double 44 45--- @param player LuaPlayer 46--- @return CalculationSet 47local function new_calculation_set ( player ) 48local force =player . force 49local current_research =force . current_research 50--- @type ResearchData? 51local research_data 52if current_research then 53research_data ={ 54ingredients =current_research . research_unit_ingredients , 55multiplier =1 / ( current_research . research_unit_energy / 60 ), 56speed_modifier =force . laboratory_speed_modifier , 57} 58end 59local pollutant ="" 60local pollutant_prototype =player . surface . pollutant_type 61if pollutant_prototype then 62pollutant =pollutant_prototype . name 63end 64return { 65completed ={} , 66errors ={} , 67player =player , 68rates ={} , 69research_data =research_data , 70pollutant =pollutant , 71} 72end 73 74local entity_blacklist ={ 75-- Transport Drones 76[ "buffer-depot" ] =true , 77[ "fluid-depot" ] =true , 78[ "fuel-depot" ] =true , 79[ "request-depot" ] =true , 80} 81 82--- @param set CalculationSet 83--- @param entity LuaEntity 84--- @param invert boolean 85local function process_entity ( set , entity , invert ) 86if entity_blacklist [ entity . name ] then 87return 88end 89 90local emissions_per_second =entity . prototype . emissions_per_second [ set . pollutant ] or 0 91local type =entity . type 92 93if type == "burner-generator" or type == "generator" then 94calc_util . add_rate ( 95set , 96"output" , 97"item" , 98"rcalc-power-dummy" , 99"normal" , 100entity . prototype . get_max_power_output ( entity . quality ) * 60 , 101invert , 102entity . name 103) 104elseif type ~= "burner-generator" and entity . prototype . electric_energy_source_prototype then 105emissions_per_second =calc_util . process_electric_energy_source ( set , entity , invert , emissions_per_second ) 106elseif entity . prototype . fluid_energy_source_prototype then 107emissions_per_second =calc_util . process_fluid_energy_source ( set , entity , invert , emissions_per_second ) 108elseif entity . prototype . heat_energy_source_prototype then 109calc_util . process_heat_energy_source ( set , entity , invert ) 110end 111 112if entity . burner then 113emissions_per_second =calc_util . process_burner ( set , entity , invert , emissions_per_second ) 114end 115 116if type == "assembling-machine" or type == "furnace" or type == "rocket-silo" then 117emissions_per_second =calc_util . process_crafter ( set , entity , invert , emissions_per_second ) 118elseif type == "beacon" then 119calc_util . process_beacon ( set , entity ) 120elseif type == "boiler" then 121calc_util . process_boiler ( set , entity , invert ) 122elseif type == "lab" then 123calc_util . process_lab ( set , entity , invert ) 124elseif type == "generator" then 125calc_util . process_generator ( set , entity , invert ) 126elseif type == "mining-drill" then 127calc_util . process_mining_drill ( set , entity , invert ) 128elseif type == "offshore-pump" then 129calc_util . process_offshore_pump ( set , entity , invert ) 130elseif type == "reactor" then 131calc_util . process_reactor ( set , entity , invert ) 132end 133 134if emissions_per_second > 0 then 135calc_util . add_rate ( 136set , 137"output" , 138"item" , 139"rcalc-pollution-dummy" , 140"normal" , 141emissions_per_second , 142invert , 143entity . name 144) 145elseif emissions_per_second < 0 then 146calc_util . add_rate ( 147set , 148"input" , 149"item" , 150"rcalc-pollution-dummy" , 151"normal" , 152- emissions_per_second , 153invert , 154entity . name 155) 156end 157end 158 159--- @param set CalculationSet 160--- @param entities LuaEntity[] 161--- @param invert boolean 162local function process_entities ( set , entities , invert ) 163for _ , entity in pairs ( entities ) do 164process_entity ( set , entity , invert ) 165end 166end 167 168--- @param e EventData.on_player_selected_area 169local function on_player_selected_area ( e ) 170if e . item ~= "rcalc-selection-tool" then 171return 172end 173if not next ( e . entities ) then 174return 175end 176local player =game . get_player ( e . player_index ) 177if not player then 178return 179end 180local set =new_calculation_set ( player ) 181process_entities ( set , e . entities , false ) 182gui . build_and_show ( player , set , true ) 183if player . mod_settings [ "rcalc-dismiss-tool-on-selection" ]. value then 184player . clear_cursor () 185end 186end 187 188--- @param e EventData.on_player_alt_selected_area 189local function on_player_alt_selected_area ( e ) 190if e . item ~= "rcalc-selection-tool" then 191return 192end 193if not next ( e . entities ) then 194return 195end 196local player =game . get_player ( e . player_index ) 197if not player then 198return 199end 200local set =gui . get_current_set ( player ) 201if not set then 202set =new_calculation_set ( player ) 203end 204set . errors ={} 205process_entities ( set , e . entities , false ) 206gui . build_and_show ( player , set ) 207end 208 209--- @param e EventData.on_player_reverse_selected_area 210local function on_player_alt_reverse_selected_area ( e ) 211if e . item ~= "rcalc-selection-tool" then 212return 213end 214if not next ( e . entities ) then 215return 216end 217local player =game . get_player ( e . player_index ) 218if not player then 219return 220end 221local set =gui . get_current_set ( player ) 222if not set then 223set =new_calculation_set ( player ) 224end 225set . errors ={} 226process_entities ( set , e . entities , true ) 227gui . build_and_show ( player , set ) 228end 229 230--- @class Calc: event_handler 231local calc ={} 232 233calc . events ={ 234[ defines . events . on_player_alt_reverse_selected_area ] =on_player_alt_reverse_selected_area , 235[ defines . events . on_player_alt_selected_area ] =on_player_alt_selected_area , 236[ defines . events . on_player_selected_area ] =on_player_selected_area , 237} 238 239return calc