This commit is contained in:
phidias authored and GitHub committed 2026-11-10 19:47:48 +09:00
1 parent fc8d5a3064
commit 30f9739844
1 file changed
+80 -73
+80 -73
View File
@@ -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<string, ExpScenario_Vlayer.ItemCountWithQuality> Every stored item, allocated or not
--- @field unallocated table<string, ExpScenario_Vlayer.ItemCountWithQuality> Items waiting for surface area
--- @field items table<string, table<number, number>> Every stored item, allocated or not
--- @field unallocated table<string, table<number, number>> 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<string, ExpScenario_Vlayer.ItemCountWithQuality>
--- @return table<string, table<number, number>>
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<string, ExpScenario_Vlayer.ItemCountWithQuality>
--- @return table<string, table<number, number>>
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<string, ExpScenario_Vlayer.ItemCountWithQuality>
--- @return table<string, table<number, number>>
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