diff --git a/exp_scenario/module/control/vlayer.lua b/exp_scenario/module/control/vlayer.lua index a43c2350..d6a33c40 100644 --- a/exp_scenario/module/control/vlayer.lua +++ b/exp_scenario/module/control/vlayer.lua @@ -53,13 +53,9 @@ local mega = 1000000 --- @field output_limit number Power output limit --- @field capacity number MJ the allocated accumulators can hold ---- @class ExpScenario_Vlayer.ItemCountWithQuality ---- @field quality number ---- @field count number - --- @class ExpScenario_Vlayer.Storage ---- @field items table Every stored item, allocated or not ---- @field unallocated table Items waiting for surface area +--- @field items table> Every stored item, allocated or not +--- @field unallocated table> Items waiting for surface area --- @field energy number J --- @class ExpScenario_Vlayer.Statistics @@ -156,8 +152,44 @@ allowed_items["landfill"] = { } --- @type ExpScenario_Vlayer.Data -local vlayer_data = { -} +local vlayer_data = {} + +--- @param surface_index number? +local function update_surface(surface_index) + if vlayer_data[surface_index] then + return + end + + -- global surface will have its data point to the main surface + if config.global_surface then + return + end + + vlayer_data[surface_index] = { + interfaces = { + energy = {}, + circuit = {}, + storage_input = {}, + storage_output = {}, + }, + properties = { + total_surface_area = 0, + used_surface_area = 0, + total_production = 0, + production = 0, + input_limit = 0, + output_limit = 0, + capacity = 0, + }, + storage = { + items = {}, + unallocated = {}, + energy = 0, + } + } +end + +update_surface(1) Storage.register(vlayer_data, function(tbl) vlayer_data = tbl @@ -196,24 +228,27 @@ circuit_description = table.concat(circuit_description, "\n") --- Get every stored item keyed by name, allocated or not --- @param s_index number surface index ---- @return table +--- @return table> function Vlayer.get_items(s_index) - return config.global_surface and vlayer_data[1].storage.items or vlayer_data[s_index].storage.items + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + return vd.storage.items end --- Get the items waiting for surface area keyed by name --- @param s_index number surface index ---- @return table +--- @return table> function Vlayer.get_unallocated_items(s_index) - return config.global_surface and vlayer_data[1].storage.unallocated or vlayer_data[s_index].storage.unallocated + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + return vd.storage.unallocated end --- Get the items which contribute to the properties keyed by name --- @param s_index number surface index ---- @return table +--- @return table> function Vlayer.get_allocated_items(s_index) local allocated = {} - local storage = config.global_surface and vlayer_data[1].storage or vlayer_data[s_index].storage + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + local storage = vd.storage local unallocated = storage.unallocated for name, qnc in pairs(storage.items) do for quality, count in pairs(qnc) do @@ -227,7 +262,8 @@ end --- @param s_index number surface index --- @return ExpScenario_Vlayer.Interfaces function Vlayer.get_interfaces(s_index) - return config.global_surface and vlayer_data[1].interfaces or vlayer_data[s_index].interfaces + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + return vd.interfaces end --- Get the signal each statistic is sent as on circuit interfaces @@ -240,8 +276,9 @@ end --- @param s_index number surface index --- @return number local function get_remaining_surface_area(s_index) - local properties = config.global_surface and vlayer_data[1].properties or vlayer_data[s_index].properties - local unallocated = config.global_surface and vlayer_data[1].storage.unallocated or vlayer_data[s_index].storage.unallocated + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + local properties = vd.properties + local unallocated = vd.storage.unallocated local remaining = properties.total_surface_area - properties.used_surface_area for name, qnc in pairs(unallocated) do for _, count in pairs(qnc) do @@ -255,8 +292,7 @@ end --- @param s_index number surface index --- @return number local function get_production_multiplier(s_index) - local surface = game.surfaces[s_index] - if not surface then return 0 end + local surface = assert(config.global_surface and game.surface[1] or game.surfaces[s_index]) local multiplier = surface.solar_power_multiplier if surface.always_day then return multiplier @@ -288,8 +324,7 @@ end --- @param s_index number surface index --- @return number local function get_sustained_multiplier(s_index) - local surface = game.surfaces[s_index] - if not surface then return 0 end + local surface = assert(config.global_surface and game.surface[1] or game.surfaces[s_index]) local multiplier = surface.solar_power_multiplier if surface.always_day then return multiplier @@ -308,7 +343,8 @@ end --- @param quality_level number local function allocate_item(s_index, name, count, quality_level) local item = allowed_items[name] - local properties = config.global_surface and vlayer_data[1].properties or vlayer_data[s_index].properties + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + local properties = vd.properties if item.production then local prod = item.production[quality_level] * count properties.production = properties.production + prod @@ -334,7 +370,8 @@ end --- @param quality_level number local function count_unallocated_production(s_index, name, count, quality_level) local item = allowed_items[name] - local properties = config.global_surface and vlayer_data[1].properties or vlayer_data[s_index].properties + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + local properties = vd.properties if item.production then properties.total_production = properties.total_production + item.production[quality_level] * count end @@ -347,7 +384,8 @@ end --- @param quality_level number function Vlayer.insert_item(s_index, name, count, quality_level) local item = assert(allowed_items[name], "Item not allowed in the vlayer: " .. name) - local storage = config.global_surface and vlayer_data[1].storage or vlayer_data[s_index].storage + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + local storage = vd.storage if not storage.items[name] then storage.items[name] = {} end storage.items[name][quality_level] = storage.items[name][quality_level] + count @@ -356,7 +394,7 @@ function Vlayer.insert_item(s_index, name, count, quality_level) return end - local properties = config.global_surface and vlayer_data[1].properties or vlayer_data[s_index].properties + local properties = vd.properties local surplus_area = properties.total_surface_area - properties.used_surface_area local allocated = min(count, floor(surplus_area / item.required_area)) if allocated > 0 then @@ -377,7 +415,8 @@ end --- @return number # The count actually removed function Vlayer.remove_item(s_index, name, count, quality_level) local item = assert(allowed_items[name], "Item not allowed in the vlayer: " .. name) - local storage = config.global_surface and vlayer_data[1].storage or vlayer_data[s_index].storage + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + local storage = vd.storage local removed = 0 if not config.unlimited_surface_area and item.required_area > 0 then @@ -391,7 +430,7 @@ function Vlayer.remove_item(s_index, name, count, quality_level) end end - local properties = config.global_surface and vlayer_data[1].properties or vlayer_data[s_index].properties + local properties = vd.properties local deallocate = min(count, storage.items[name][quality_level]) if item.surface_area and item.surface_area > 0 then local surplus_area = properties.total_surface_area - properties.used_surface_area @@ -411,7 +450,8 @@ end --- @param energy number J, negative to take --- @return number # J stored afterwards function Vlayer.energy_changed(s_index, energy) - local storage = config.global_surface and vlayer_data[1].storage or vlayer_data[s_index].storage + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + local storage = vd.storage storage.energy = storage.energy + energy return storage.energy end @@ -420,7 +460,8 @@ end --- @param s_index number surface index --- @return ExpScenario_Vlayer.Statistics function Vlayer.get_statistics(s_index) - local properties = config.global_surface and vlayer_data[1].properties or vlayer_data[s_index].properties + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + local properties = vd.properties local production = properties.production * mega local production_multiplier = get_production_multiplier(s_index) local sustained_multiplier = get_sustained_multiplier(s_index) @@ -437,7 +478,7 @@ function Vlayer.get_statistics(s_index) energy_total_production = properties.total_production * sustained_multiplier * mega, energy_sustained = production * sustained_multiplier, energy_capacity = properties.capacity * mega, - energy_storage = config.global_surface and vlayer_data[1].storage.energy or vlayer_data[s_index].storage.energy, + energy_storage = vd.storage.energy, } end @@ -447,7 +488,8 @@ end --- @param interface_type ExpScenario_Vlayer.InterfaceType --- @param player LuaPlayer? local function register_interface(s_index, interface, interface_type, player) - local interfaces = config.global_surface and vlayer_data[1].interfaces[interface_type] or vlayer_data[s_index].interfaces[interface_type] + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + local interfaces = vd.interfaces[interface_type] interfaces[#interfaces + 1] = interface interface.last_user = player interface.destructible = false @@ -515,8 +557,9 @@ end --- @return ExpScenario_Vlayer.InterfaceType function Vlayer.remove_interface(interface) local s_index = interface.surface.index - local storage = config.global_surface and vlayer_data[1].storage or vlayer_data[s_index].storage - local interfaces = config.global_surface and vlayer_data[1].interfaces or vlayer_data[s_index].interfaces + local vd = assert(config.global_surface and vlayer_data[1] or vlayer_data[s_index]) + local storage = vd.storage + local interfaces = vd.interfaces local interface_type = assert(interface_types[interface.name], "Entity is not a vlayer interface: " .. interface.name) if interface_type == "storage_input" or interface_type == "storage_output" then ExpUtil.transfer_inventory_to_surface{ @@ -696,40 +739,6 @@ local function handle_energy_interfaces() end end -local function update_surface(event) - if vlayer_data[event.surface_index] then - return - end - - -- global surface will have its data point to the main surface - if config.global_surface then - return - end - - vlayer_data[event.surface_index] = { - interfaces = { - energy = {}, - circuit = {}, - storage_input = {}, - storage_output = {}, - }, - properties = { - total_surface_area = 0, - used_surface_area = 0, - total_production = 0, - production = 0, - input_limit = 0, - output_limit = 0, - capacity = 0, - }, - storage = { - items = {}, - unallocated = {}, - energy = 0, - } - } -end - --- Move items between the interfaces and storage local function update_storage() handle_input_interfaces() @@ -745,12 +754,10 @@ end local e = defines.events -Vlayer.on_init = function() - update_surface({surface_index=game.surfaces["nauvis"].index}) -end -- The default surface exists before on_surface_created can fire -Vlayer.events[e.on_surface_created] = update_surface -Vlayer.events[e.on_surface_renamed] = update_surface -Vlayer.events[e.on_surface_imported] = update_surface +Vlayer.on_init = update_surface -- The default surface exists before on_surface_created can fire +Vlayer.events[e.on_surface_created] = function update_surface(event.surface_index) end +Vlayer.events[e.on_surface_renamed] = function update_surface(event.surface_index) end +Vlayer.events[e.on_surface_imported] = function update_surface(event.surface_index) end Vlayer.on_nth_tick[update_tick_storage] = update_storage Vlayer.on_nth_tick[update_tick_energy] = update_energy