mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-11-14 00:14:52 +09:00
vlayer surface and quality draft
This commit is contained in:
1 parent
ce29218f14
commit
66722c8291
5 files changed
+342
-489
No files matched your search
@@ -399,15 +399,12 @@ export const features: Feature[] = [
|
||||
fields: [
|
||||
bool("unlimited_capacity", "Unlimited capacity", "Energy storage without accumulators", false),
|
||||
bool("unlimited_surface_area", "Unlimited area", "Place items without landfill", false),
|
||||
bool("modded_auto_downgrade", "Downgrade modded items", "Convert modded items to their base game equivalent, the originals can not be recovered", false),
|
||||
bool("power_on_space", "Power on platforms", "Energy interfaces can be built on space platforms", false),
|
||||
str("power_on_space_research.name", "Platform research", "The research needed to build energy interfaces on platforms", "research-productivity"),
|
||||
num("power_on_space_research.level", "Platform research level", "The level of that research", 10, 0),
|
||||
str("mimic_surface", "Mimic surface", "The surface the day cycle is copied from, empty for a fixed cycle", "nauvis"),
|
||||
num("interface_limit.energy", "Energy interfaces", "More than one lets disconnected power networks receive power", 1, 0),
|
||||
num("interface_limit.circuit", "Circuit interfaces", "How many circuit interfaces can exist", 20, 0),
|
||||
num("interface_limit.storage_input", "Input interfaces", "How many storage input interfaces can exist", 20, 0),
|
||||
num("interface_limit.storage_output", "Output interfaces", "More than zero allows item teleportation of the allowed items", 1, 0),
|
||||
bool("global_surface", "Power and item sharing", "Every surface point to the main surface, allowing sharing of power and item", false),
|
||||
num("landfill_area", "Landfill area", "How much area a landfill provide", 20, 1),
|
||||
num("interface_limit.energy", "Energy interfaces", "Per surface setting. More than one lets disconnected power networks receive power. 0 means disabled, -1 means unlimited.", 1, -1),
|
||||
num("interface_limit.circuit", "Circuit interfaces", "Per surface setting. How many circuit interfaces can exist. 0 means disabled, -1 means unlimited.", -1, -1),
|
||||
num("interface_limit.storage_input", "Input interfaces", "Per surface setting. How many storage input interfaces can exist. 0 means disabled, -1 means unlimited.", -1, -1),
|
||||
num("interface_limit.storage_output", "Output interfaces", "Per surface setting. More than zero allows item teleportation of the allowed items. 0 means disabled, -1 means unlimited.", 1, -1),
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -2,146 +2,13 @@
|
||||
-- @config Vlayer-Items
|
||||
|
||||
return {
|
||||
--- @class Vlayer.ItemProperties
|
||||
--- @field starting_value number
|
||||
--- @field required_area number
|
||||
--- @field production number?
|
||||
--- @field discharge number?
|
||||
--- @field capacity number?
|
||||
--- @field surface_area number?
|
||||
--- @field fuel_value number?
|
||||
--- @field power boolean?
|
||||
--- @field modded boolean? Set when the item is registered from a modded equivalent
|
||||
--- @field base_game_equivalent string?
|
||||
--- @field multiplier number?
|
||||
|
||||
--- @type table<string, Vlayer.ItemProperties>
|
||||
allowed_items = { -- List of all items allowed in vlayer storage and their properties
|
||||
--[[
|
||||
Allowed properties:
|
||||
starting_value : The amount of the item placed into the vlayer on game start, ignores area requirements
|
||||
required_area : When greater than 0 the items properties are not applied unless their is sufficient surplus surface area
|
||||
production : The energy production of the item in MW, used for solar panels
|
||||
discharge : The energy discharge of the item in MW, used for accumulators
|
||||
capacity : The energy capacity of the item in MJ, used for accumulators
|
||||
surface_area : The surface area provided by the item, used for landfill
|
||||
]]
|
||||
["solar-panel"] = {
|
||||
starting_value = 0,
|
||||
required_area = 9,
|
||||
production = 0.06, -- MW
|
||||
},
|
||||
["accumulator"] = {
|
||||
starting_value = 0,
|
||||
required_area = 4,
|
||||
discharge = 0.3, -- MW
|
||||
capacity = 5, -- MJ
|
||||
},
|
||||
["landfill"] = {
|
||||
starting_value = 0,
|
||||
required_area = 0,
|
||||
surface_area = 20, -- Tiles
|
||||
},
|
||||
["wood"] = {
|
||||
starting_value = 0,
|
||||
required_area = 0,
|
||||
surface_area = 0,
|
||||
fuel_value = 2, -- MJ
|
||||
power = true, -- turn all wood to power to reduce trash
|
||||
},
|
||||
["coal"] = {
|
||||
starting_value = 0,
|
||||
required_area = 0,
|
||||
surface_area = 0,
|
||||
fuel_value = 4, -- MJ
|
||||
power = false, -- turn all coal to power to reduce trash
|
||||
},
|
||||
["solid-fuel"] = {
|
||||
starting_value = 0,
|
||||
required_area = 0,
|
||||
surface_area = 0,
|
||||
fuel_value = 12, -- MJ
|
||||
power = false, -- turn all solid fuel to power to reduce trash
|
||||
},
|
||||
["rocket-fuel"] = {
|
||||
starting_value = 0,
|
||||
required_area = 0,
|
||||
surface_area = 0,
|
||||
fuel_value = 100, -- MJ
|
||||
power = false, -- turn all rocket fuel to power to reduce trash
|
||||
--- @type table<string, string>
|
||||
allowed_categories = { -- List of categories allowed in vlayer storage
|
||||
["production"] = {
|
||||
"solar-panel"
|
||||
},
|
||||
["storage"] = {
|
||||
"accumulator"
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
modded_items = { -- List of all modded items allowed in vlayer storage and their base game equivalent
|
||||
["solar-panel-2"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "solar-panel",
|
||||
multiplier = 4,
|
||||
},
|
||||
["solar-panel-3"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "solar-panel",
|
||||
multiplier = 16,
|
||||
},
|
||||
["solar-panel-4"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "solar-panel",
|
||||
multiplier = 64,
|
||||
},
|
||||
["solar-panel-5"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "solar-panel",
|
||||
multiplier = 256,
|
||||
},
|
||||
["solar-panel-6"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "solar-panel",
|
||||
multiplier = 1024,
|
||||
},
|
||||
["solar-panel-7"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "solar-panel",
|
||||
multiplier = 4096,
|
||||
},
|
||||
["solar-panel-8"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "solar-panel",
|
||||
multiplier = 16384,
|
||||
},
|
||||
["accumulator-2"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "accumulator",
|
||||
multiplier = 4,
|
||||
},
|
||||
["accumulator-3"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "accumulator",
|
||||
multiplier = 16,
|
||||
},
|
||||
["accumulator-4"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "accumulator",
|
||||
multiplier = 64,
|
||||
},
|
||||
["accumulator-5"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "accumulator",
|
||||
multiplier = 256,
|
||||
},
|
||||
["accumulator-6"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "accumulator",
|
||||
multiplier = 1024,
|
||||
},
|
||||
["accumulator-7"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "accumulator",
|
||||
multiplier = 4096,
|
||||
},
|
||||
["accumulator-8"] = {
|
||||
starting_value = 0,
|
||||
base_game_equivalent = "accumulator",
|
||||
multiplier = 16384,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -10,37 +10,18 @@ local items = require("modules/exp_scenario/config/vlayer_items")
|
||||
local feature, config = Feature.register("vlayer", {
|
||||
unlimited_capacity = false, -- an unlimited energy capacity, accumulators are not required
|
||||
unlimited_surface_area = false, -- an unlimited surface area, landfill is not required
|
||||
modded_auto_downgrade = false, -- modded items are converted into their base game equivalent, the originals can not be recovered
|
||||
power_on_space = false, -- energy interfaces can be built on platforms
|
||||
power_on_space_research = { -- the research level needed to build them there
|
||||
name = "research-productivity",
|
||||
level = 10,
|
||||
},
|
||||
mimic_surface = "nauvis", -- the surface the day cycle is copied from, empty to use the fixed cycle below
|
||||
interface_limit = { -- how many of each interface can exist
|
||||
global_surface = false, -- every surface point to the main surface, allowing sharing of power and item
|
||||
landfill_area = 20, -- How much area a landfill provide
|
||||
interface_limit = { -- how many of each interface per surface can exist
|
||||
energy = 1, -- >1 allows for disconnected power networks to receive power
|
||||
circuit = 20,
|
||||
storage_input = 20,
|
||||
circuit = -1,
|
||||
storage_input = -1,
|
||||
storage_output = 1, -- >0 allows for item teleportation of the allowed items
|
||||
},
|
||||
})
|
||||
|
||||
local update_tick_storage = 60
|
||||
local update_tick_energy = 10
|
||||
|
||||
--- The day cycle used when there is no mimic surface, see LuaSurface for details
|
||||
local surface_settings = {
|
||||
always_day = false,
|
||||
solar_power_multiplier = 1,
|
||||
min_brightness = 0.15,
|
||||
ticks_per_day = 25200,
|
||||
daytime = 0,
|
||||
dusk = 0.25,
|
||||
evening = 0.45,
|
||||
morning = 0.55,
|
||||
dawn = 0.75,
|
||||
|
||||
}
|
||||
local update_tick_storage = 60, -- How frequent the storage updates, in tick
|
||||
local update_tick_energy = 10, -- How frequent the energy updates, in tick
|
||||
|
||||
local floor = math.floor
|
||||
local min = math.min
|
||||
@@ -49,6 +30,14 @@ local mega = 1000000
|
||||
|
||||
--- @alias ExpScenario_Vlayer.InterfaceType "energy" | "circuit" | "storage_input" | "storage_output"
|
||||
|
||||
--- @class Vlayer.ItemProperties
|
||||
--- @field required_area number
|
||||
--- @field production table<number, number>? Power output in MW with a quality level key
|
||||
--- @field input_limit table<number, number>? Power input limit in MW with a quality level key
|
||||
--- @field output_limit table<number, number>? Power output limit in MW with a quality level key
|
||||
--- @field capacity table<number, number>? Power capacity in MJ with a quality level key
|
||||
--- @field surface_area number?
|
||||
|
||||
--- @class ExpScenario_Vlayer.Interfaces
|
||||
--- @field energy LuaEntity[]
|
||||
--- @field circuit LuaEntity[]
|
||||
@@ -63,14 +52,13 @@ local mega = 1000000
|
||||
--- @field discharge number MW the allocated accumulators can discharge
|
||||
--- @field capacity number MJ the allocated accumulators can hold
|
||||
|
||||
--- @class ExpScenario_Vlayer.PowerItem
|
||||
--- @field value number J released by burning one
|
||||
--- @class ExpScenario_Vlayer.ItemCountWithQuality
|
||||
--- @field quality string
|
||||
--- @field count number
|
||||
|
||||
--- @class ExpScenario_Vlayer.Storage
|
||||
--- @field items table<string, number> Every stored item, allocated or not
|
||||
--- @field unallocated table<string, number> Items waiting for surface area
|
||||
--- @field power_items table<string, ExpScenario_Vlayer.PowerItem> Fuel burned when the stored energy is low
|
||||
--- @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 energy number J
|
||||
|
||||
--- @class ExpScenario_Vlayer.Statistics
|
||||
@@ -86,11 +74,13 @@ local mega = 1000000
|
||||
--- @field energy_capacity number J
|
||||
--- @field energy_storage number J
|
||||
|
||||
--- @class ExpScenario_Vlayer.Data
|
||||
--- @class ExpScenario_Vlayer.SurfaceData
|
||||
--- @field interfaces ExpScenario_Vlayer.Interfaces
|
||||
--- @field properties ExpScenario_Vlayer.Properties
|
||||
--- @field storage ExpScenario_Vlayer.Storage
|
||||
--- @field surface LuaSurface | table The surface the day cycle is taken from, or a copy of the config settings
|
||||
|
||||
--- @class ExpScenario_Vlayer.Data
|
||||
--- @field surfaces table<number, ExpScenario_Vlayer.SurfaceData> Surface ID key
|
||||
|
||||
--- @class ExpScenario_Vlayer
|
||||
local Vlayer = {
|
||||
@@ -103,46 +93,66 @@ local Vlayer = {
|
||||
on_nth_tick = {},
|
||||
}
|
||||
|
||||
--- The properties of every allowed item, modded items are derived from their base game equivalent
|
||||
local quality_level_to_name = {}
|
||||
|
||||
for _, q in pairs(prototypes.quality) do
|
||||
quality_level_to_name[q.level] = q.name
|
||||
end
|
||||
|
||||
--- The properties of every allowed item
|
||||
local allowed_items = {} --- @type table<string, Vlayer.ItemProperties>
|
||||
for name, properties in pairs(items.allowed_items) do
|
||||
allowed_items[name] = properties
|
||||
|
||||
for _, name in pairs(items.allowed_categories["production"]) do
|
||||
local item_in_category = prototypes.get_entity_filtered{filter = "type", type = name}
|
||||
|
||||
for _, item in pairs(item_in_category) do
|
||||
local item_name = item.name
|
||||
|
||||
allowed_items[item_name] = {
|
||||
required_area = item.tile_width * item.tile_height,
|
||||
-- production_day = item.solar_panel_performance_at_day or 1,
|
||||
-- production_night = item.solar_panel_performance_at_night or 1,
|
||||
-- Quality affected items
|
||||
production = {},
|
||||
}
|
||||
|
||||
for l, n in pairs(quality_level_to_name) do
|
||||
allowed_items[item_name]["production"][l] = item.get_max_energy_production(n) / mega -- W -> MW
|
||||
end
|
||||
end
|
||||
end
|
||||
for name, properties in pairs(items.modded_items) do
|
||||
local base = items.allowed_items[properties.base_game_equivalent]
|
||||
local multiplier = properties.multiplier
|
||||
allowed_items[name] = {
|
||||
starting_value = properties.starting_value or 0,
|
||||
required_area = base.required_area or 0,
|
||||
surface_area = (base.surface_area or 0) * multiplier,
|
||||
production = (base.production or 0) * multiplier,
|
||||
capacity = (base.capacity or 0) * multiplier,
|
||||
}
|
||||
|
||||
for _, name in pairs(items.allowed_categories["storage"]) do
|
||||
local item_in_category = prototypes.get_entity_filtered{filter = "type", type = name}
|
||||
|
||||
for _, item in pairs(item_in_category) do
|
||||
local item_name = item.name
|
||||
|
||||
allowed_items[item_name] = {
|
||||
required_area = item.tile_width * item.tile_height,
|
||||
-- Quality affected items
|
||||
input_limit = {},
|
||||
output_limit = {},
|
||||
capacity = {},
|
||||
}
|
||||
|
||||
if item.electric_energy_source_prototype then
|
||||
for l, n in pairs(quality_level_to_name) do
|
||||
allowed_items[item_name]["input_limit"][l] = item.electric_energy_source_prototype.get_input_flow_limit(n) / mega -- W -> MW
|
||||
allowed_items[item_name]["output_limit"][l] = item.electric_energy_source_prototype.get_output_flow_limit(n) / mega -- W -> MW
|
||||
allowed_items[item_name]["capacity"][l] = item.electric_energy_source_prototype.buffer_capacity * prototypes.quality[n].accumulator_capacity_multiplier / mega -- J -> MJ
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
allowed_items["landfill"] = {
|
||||
surface_area = config.landfill_area
|
||||
}
|
||||
|
||||
--- @type ExpScenario_Vlayer.Data
|
||||
local vlayer_data = {
|
||||
interfaces = {
|
||||
energy = {},
|
||||
circuit = {},
|
||||
storage_input = {},
|
||||
storage_output = {},
|
||||
},
|
||||
properties = {
|
||||
total_surface_area = 0,
|
||||
used_surface_area = 0,
|
||||
total_production = 0,
|
||||
production = 0,
|
||||
discharge = 0,
|
||||
capacity = 0,
|
||||
},
|
||||
storage = {
|
||||
items = {},
|
||||
unallocated = {},
|
||||
power_items = {},
|
||||
energy = 0,
|
||||
},
|
||||
surface = table.deep_copy(surface_settings),
|
||||
surfaces = {}
|
||||
}
|
||||
|
||||
Storage.register(vlayer_data, function(tbl)
|
||||
@@ -181,32 +191,39 @@ end
|
||||
circuit_description = table.concat(circuit_description, "\n")
|
||||
|
||||
--- Get every stored item keyed by name, allocated or not
|
||||
--- @param s_index number
|
||||
--- @return table<string, number>
|
||||
function Vlayer.get_items()
|
||||
return vlayer_data.storage.items
|
||||
function Vlayer.get_items(s_index)
|
||||
return vlayer_data[s_index].storage.items
|
||||
end
|
||||
|
||||
--- Get the items waiting for surface area keyed by name
|
||||
--- @param s_index number
|
||||
--- @return table<string, number>
|
||||
function Vlayer.get_unallocated_items()
|
||||
return vlayer_data.storage.unallocated
|
||||
function Vlayer.get_unallocated_items(s_index)
|
||||
return vlayer_data[s_index].storage.unallocated
|
||||
end
|
||||
|
||||
--- Get the items which contribute to the properties keyed by name
|
||||
--- @param s_index number
|
||||
--- @return table<string, number>
|
||||
function Vlayer.get_allocated_items()
|
||||
function Vlayer.get_allocated_items(s_index)
|
||||
local allocated = {}
|
||||
local unallocated = vlayer_data.storage.unallocated
|
||||
for name, count in pairs(vlayer_data.storage.items) do
|
||||
allocated[name] = count - (unallocated[name] or 0)
|
||||
local storage = vlayer_data[s_index].storage
|
||||
local unallocated = storage.unallocated
|
||||
for name, qnc in pairs(storage.items) do
|
||||
for quality, count in pairs(qnc) do
|
||||
allocated[name][quality] = count - (unallocated[name][quality] or 0)
|
||||
end
|
||||
end
|
||||
return allocated
|
||||
end
|
||||
|
||||
--- Get the interface entities of each type, do not modify
|
||||
--- @param s_index number
|
||||
--- @return ExpScenario_Vlayer.Interfaces
|
||||
function Vlayer.get_interfaces()
|
||||
return vlayer_data.interfaces
|
||||
function Vlayer.get_interfaces(s_index)
|
||||
return vlayer_data[s_index].interfaces
|
||||
end
|
||||
|
||||
--- Get the signal each statistic is sent as on circuit interfaces
|
||||
@@ -216,20 +233,24 @@ function Vlayer.get_circuits()
|
||||
end
|
||||
|
||||
--- Surface area left once the unallocated items have taken what they need
|
||||
--- @param s_index number
|
||||
--- @return number
|
||||
local function get_remaining_surface_area()
|
||||
local properties = vlayer_data.properties
|
||||
local function get_remaining_surface_area(s_index)
|
||||
local properties = vlayer_data[s_index].properties
|
||||
local remaining = properties.total_surface_area - properties.used_surface_area
|
||||
for name, count in pairs(vlayer_data.storage.unallocated) do
|
||||
remaining = remaining - allowed_items[name].required_area * count
|
||||
for name, qnc in pairs(vlayer_data[s_index].storage.unallocated) do
|
||||
for _, count in pairs(qnc) do
|
||||
remaining = remaining - allowed_items[name].required_area * count
|
||||
end
|
||||
end
|
||||
return remaining
|
||||
end
|
||||
|
||||
--- Fraction of solar production available right now, from the darkness of a real surface or the config day cycle
|
||||
--- @param s_index number
|
||||
--- @return number
|
||||
local function get_production_multiplier()
|
||||
local surface = vlayer_data.surface
|
||||
local function get_production_multiplier(s_index)
|
||||
local surface = game.surfaces[s_index]
|
||||
local multiplier = surface.solar_power_multiplier
|
||||
if surface.always_day then
|
||||
return multiplier
|
||||
@@ -245,48 +266,55 @@ local function get_production_multiplier()
|
||||
|
||||
local daytime = (game.tick % surface.ticks_per_day) / surface.ticks_per_day
|
||||
surface.daytime = daytime
|
||||
if daytime <= surface.dusk then
|
||||
if daytime <= surface.daytime_parameters.dusk then
|
||||
return multiplier
|
||||
elseif daytime <= surface.evening then
|
||||
return multiplier * (1 - (daytime - surface.dusk) / (surface.evening - surface.dusk))
|
||||
elseif daytime <= surface.morning then
|
||||
elseif daytime <= surface.daytime_parameters.evening then
|
||||
return multiplier * (1 - (daytime - surface.daytime_parameters.dusk) / (surface.daytime_parameters.evening - surface.daytime_parameters.dusk))
|
||||
elseif daytime <= surface.daytime_parameters.morning then
|
||||
return 0
|
||||
elseif daytime <= surface.dawn then
|
||||
return multiplier * (daytime - surface.morning) / (surface.dawn - surface.morning)
|
||||
elseif daytime <= surface.daytime_parameters.dawn then
|
||||
return multiplier * (daytime - surface.daytime_parameters.morning) / (surface.daytime_parameters.dawn - surface.daytime_parameters.morning)
|
||||
end
|
||||
return multiplier
|
||||
end
|
||||
|
||||
--- Fraction of solar production averaged over a whole day, sunrise and sunset count for half
|
||||
--- @param s_index number
|
||||
--- @return number
|
||||
local function get_sustained_multiplier()
|
||||
local surface = vlayer_data.surface
|
||||
local function get_sustained_multiplier(s_index)
|
||||
local surface = game.surfaces[s_index]
|
||||
local multiplier = surface.solar_power_multiplier
|
||||
if surface.always_day then
|
||||
return multiplier
|
||||
end
|
||||
|
||||
local day_duration = 1 - surface.dawn + surface.dusk
|
||||
local sunset_duration = surface.evening - surface.dusk
|
||||
local sunrise_duration = surface.dawn - surface.morning
|
||||
local day_duration = 1 - surface.daytime_parameters.dawn + surface.daytime_parameters.dusk
|
||||
local sunset_duration = surface.daytime_parameters.evening - surface.daytime_parameters.dusk
|
||||
local sunrise_duration = surface.daytime_parameters.dawn - surface.daytime_parameters.morning
|
||||
return multiplier * (day_duration + 0.5 * (sunset_duration + sunrise_duration))
|
||||
end
|
||||
|
||||
--- Apply the properties of an item to the layer, a negative count deallocates
|
||||
--- @param s_index number
|
||||
--- @param name string
|
||||
--- @param count number
|
||||
local function allocate_item(name, count)
|
||||
--- @param quality_level number
|
||||
local function allocate_item(s_index, name, count, quality_level)
|
||||
local item = allowed_items[name]
|
||||
local properties = vlayer_data.properties
|
||||
local properties = vlayer_data[s_index].properties
|
||||
if item.production then
|
||||
properties.production = properties.production + item.production * count
|
||||
properties.total_production = properties.total_production + item.production * count
|
||||
local prod = item.production[quality_level] * count
|
||||
properties.production = properties.production + prod
|
||||
properties.total_production = properties.total_production + prod
|
||||
end
|
||||
if item.input_limit then
|
||||
properties.input_limit = properties.input_limit + item.input_limit[quality_level] * count
|
||||
end
|
||||
if item.output_limit then
|
||||
properties.output_limit = properties.output_limit + item.output_limit[quality_level] * count
|
||||
end
|
||||
if item.capacity then
|
||||
properties.capacity = properties.capacity + item.capacity * count
|
||||
end
|
||||
if item.discharge then
|
||||
properties.discharge = properties.discharge + item.discharge * count
|
||||
properties.capacity = properties.capacity + item.capacity[quality_level] * count
|
||||
end
|
||||
if item.surface_area then
|
||||
properties.total_surface_area = properties.total_surface_area + item.surface_area * count
|
||||
@@ -297,73 +325,69 @@ local function allocate_item(name, count)
|
||||
end
|
||||
|
||||
--- Count the production of items which are stored but not allocated, so the total shows what more surface area would give
|
||||
--- @param s_index number
|
||||
--- @param name string
|
||||
--- @param count number
|
||||
local function count_unallocated_production(name, count)
|
||||
--- @param quality_level number
|
||||
local function count_unallocated_production(s_index, name, count, quality_level)
|
||||
local item = allowed_items[name]
|
||||
local properties = vlayer_data[s_index].properties
|
||||
if item.production then
|
||||
vlayer_data.properties.total_production = vlayer_data.properties.total_production + item.production * count
|
||||
properties.total_production = properties.total_production + item.production[quality_level] * count
|
||||
end
|
||||
end
|
||||
|
||||
for name, item in pairs(allowed_items) do
|
||||
vlayer_data.storage.items[name] = item.starting_value
|
||||
if item.required_area > 0 then
|
||||
vlayer_data.storage.unallocated[name] = 0
|
||||
end
|
||||
if item.power then
|
||||
vlayer_data.storage.power_items[name] = { value = assert(item.fuel_value) * mega, count = 0 }
|
||||
end
|
||||
allocate_item(name, item.starting_value)
|
||||
end
|
||||
|
||||
--- Store an item, it is allocated straight away when there is surface area for it
|
||||
--- @param s_index number
|
||||
--- @param name string
|
||||
--- @param count number
|
||||
function Vlayer.insert_item(name, count)
|
||||
--- @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 = vlayer_data.storage
|
||||
storage.items[name] = storage.items[name] + count
|
||||
local storage = vlayer_data[s_index].storage
|
||||
storage.items[name][quality_level] = storage.items[name][quality_level] + count
|
||||
|
||||
if config.unlimited_surface_area or item.required_area == 0 then
|
||||
allocate_item(name, count)
|
||||
allocate_item(s_index, name, count, quality_level)
|
||||
return
|
||||
end
|
||||
|
||||
local properties = vlayer_data.properties
|
||||
local properties = vlayer_data[s_index].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
|
||||
allocate_item(name, allocated)
|
||||
allocate_item(s_index, name, allocated, quality_level)
|
||||
end
|
||||
|
||||
local unallocated = count - allocated
|
||||
storage.unallocated[name] = storage.unallocated[name] + unallocated
|
||||
count_unallocated_production(name, unallocated)
|
||||
storage.unallocated[name][quality_level] = storage.unallocated[name][quality_level] + unallocated
|
||||
count_unallocated_production(s_index, name, unallocated, quality_level)
|
||||
end
|
||||
|
||||
--- Take an item out, unallocated items go first and landfill can only go while nothing is using its area
|
||||
--- @param s_index number
|
||||
--- @param name string
|
||||
--- @param count number
|
||||
--- @param quality_level number
|
||||
--- @return number # The count actually removed
|
||||
function Vlayer.remove_item(name, count)
|
||||
function Vlayer.remove_item(s_index, name, wanted, quality_level)
|
||||
local item = assert(allowed_items[name], "Item not allowed in the vlayer: " .. name)
|
||||
local storage = vlayer_data.storage
|
||||
local properties = vlayer_data.properties
|
||||
local storage = vlayer_data[s_index].storage
|
||||
local properties = vlayer_data[s_index].properties
|
||||
local removed = 0
|
||||
|
||||
if not config.unlimited_surface_area and item.required_area > 0 then
|
||||
removed = min(count, storage.unallocated[name])
|
||||
storage.items[name] = storage.items[name] - removed
|
||||
storage.unallocated[name] = storage.unallocated[name] - removed
|
||||
count_unallocated_production(name, -removed)
|
||||
removed = min(count, storage.unallocated[name][quality_level])
|
||||
storage.items[name][quality_level] = storage.items[name][quality_level] - removed
|
||||
storage.unallocated[name][quality_level] = storage.unallocated[name][quality_level] - removed
|
||||
count_unallocated_production(s_index, name, -removed, quality_level)
|
||||
count = count - removed
|
||||
if count == 0 then
|
||||
return removed
|
||||
end
|
||||
end
|
||||
|
||||
local deallocate = min(count, storage.items[name])
|
||||
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
|
||||
deallocate = min(deallocate, floor(surplus_area / item.surface_area))
|
||||
@@ -372,28 +396,30 @@ function Vlayer.remove_item(name, count)
|
||||
end
|
||||
end
|
||||
|
||||
storage.items[name] = storage.items[name] - deallocate
|
||||
allocate_item(name, -deallocate)
|
||||
storage.items[name][quality_level] = storage.items[name][quality_level] - deallocate
|
||||
allocate_item(s_index, name, -deallocate, quality_level)
|
||||
return removed + deallocate
|
||||
end
|
||||
|
||||
--- Add or take energy, used by other modules which spend the stored energy
|
||||
--- @param s_index number
|
||||
--- @param energy number J, negative to take
|
||||
--- @return number # J stored afterwards
|
||||
function Vlayer.energy_changed(energy)
|
||||
local storage = vlayer_data.storage
|
||||
function Vlayer.energy_changed(s_index, energy)
|
||||
local storage = vlayer_data[s_index].storage
|
||||
storage.energy = storage.energy + energy
|
||||
return storage.energy
|
||||
end
|
||||
|
||||
--- Get the statistics of the layer
|
||||
--- @param s_index number
|
||||
--- @return ExpScenario_Vlayer.Statistics
|
||||
function Vlayer.get_statistics()
|
||||
local properties = vlayer_data.properties
|
||||
function Vlayer.get_statistics(s_index)
|
||||
local properties = vlayer_data[s_index].properties
|
||||
local production = properties.production * mega
|
||||
local production_multiplier = get_production_multiplier()
|
||||
local sustained_multiplier = get_sustained_multiplier()
|
||||
local remaining_surface_area = get_remaining_surface_area()
|
||||
local production_multiplier = get_production_multiplier(s_index)
|
||||
local sustained_multiplier = get_sustained_multiplier(s_index)
|
||||
local remaining_surface_area = get_remaining_surface_area(s_index)
|
||||
|
||||
return {
|
||||
total_surface_area = properties.total_surface_area,
|
||||
@@ -406,16 +432,17 @@ function Vlayer.get_statistics()
|
||||
energy_total_production = properties.total_production * sustained_multiplier * mega,
|
||||
energy_sustained = production * sustained_multiplier,
|
||||
energy_capacity = properties.capacity * mega,
|
||||
energy_storage = vlayer_data.storage.energy,
|
||||
energy_storage = vlayer_data[s_index].storage.energy,
|
||||
}
|
||||
end
|
||||
|
||||
--- Make an entity into an interface which players can not mine or damage
|
||||
--- @param s_index number
|
||||
--- @param interface LuaEntity
|
||||
--- @param interface_type ExpScenario_Vlayer.InterfaceType
|
||||
--- @param player LuaPlayer?
|
||||
local function register_interface(interface, interface_type, player)
|
||||
local interfaces = vlayer_data.interfaces[interface_type]
|
||||
local function register_interface(s_index, interface, interface_type, player)
|
||||
local interfaces = vlayer_data[s_index].interfaces[interface_type]
|
||||
interfaces[#interfaces + 1] = interface
|
||||
interface.last_user = player
|
||||
interface.destructible = false
|
||||
@@ -433,7 +460,7 @@ function Vlayer.create_energy_interface(surface, position, player)
|
||||
end
|
||||
|
||||
local interface = assert(surface.create_entity{ name = interface_names.energy, position = position, force = "neutral" })
|
||||
register_interface(interface, "energy", player)
|
||||
register_interface(surface.index, interface, "energy", player)
|
||||
interface.operable = false
|
||||
interface.electric_buffer_size = 0
|
||||
interface.power_production = 0
|
||||
@@ -449,7 +476,7 @@ end
|
||||
--- @return LuaEntity
|
||||
function Vlayer.create_circuit_interface(surface, position, player)
|
||||
local interface = assert(surface.create_entity{ name = interface_names.circuit, position = position, force = "neutral" })
|
||||
register_interface(interface, "circuit", player)
|
||||
register_interface(surface.index, interface, "circuit", player)
|
||||
interface.combinator_description = circuit_description
|
||||
return interface
|
||||
end
|
||||
@@ -461,7 +488,7 @@ end
|
||||
--- @return LuaEntity
|
||||
function Vlayer.create_input_interface(surface, position, player)
|
||||
local interface = assert(surface.create_entity{ name = interface_names.storage_input, position = position, force = "neutral" })
|
||||
register_interface(interface, "storage_input", player)
|
||||
register_interface(surface.index, interface, "storage_input", player)
|
||||
-- A filter nothing can match stops robots filling it with anything
|
||||
interface.storage_filter = { name = "deconstruction-planner", quality = "normal" }
|
||||
return interface
|
||||
@@ -474,7 +501,7 @@ end
|
||||
--- @return LuaEntity
|
||||
function Vlayer.create_output_interface(surface, position, player)
|
||||
local interface = assert(surface.create_entity{ name = interface_names.storage_output, position = position, force = "neutral" })
|
||||
register_interface(interface, "storage_output", player)
|
||||
register_interface(surface.index, interface, "storage_output", player)
|
||||
return interface
|
||||
end
|
||||
|
||||
@@ -482,6 +509,7 @@ end
|
||||
--- @param interface LuaEntity
|
||||
--- @return ExpScenario_Vlayer.InterfaceType
|
||||
function Vlayer.remove_interface(interface)
|
||||
local s_index = interface.surface.index
|
||||
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{
|
||||
@@ -491,10 +519,10 @@ function Vlayer.remove_interface(interface)
|
||||
allow_creation = true,
|
||||
}
|
||||
elseif interface_type == "energy" then
|
||||
vlayer_data.storage.energy = vlayer_data.storage.energy + interface.energy
|
||||
vlayer_data[s_index].storage.energy = vlayer_data[s_index].storage.energy + interface.energy
|
||||
end
|
||||
|
||||
table.remove_element(vlayer_data.interfaces[interface_type], interface)
|
||||
table.remove_element(vlayer_data[s_index].interfaces[interface_type], interface)
|
||||
interface.destroy()
|
||||
return interface_type
|
||||
end
|
||||
@@ -511,34 +539,18 @@ end
|
||||
|
||||
--- Store the contents of the input interfaces
|
||||
local function handle_input_interfaces()
|
||||
local interfaces = vlayer_data.interfaces.storage_input
|
||||
prune_interfaces(interfaces)
|
||||
for _, interface in ipairs(interfaces) do
|
||||
local inventory = assert(interface.get_inventory(defines.inventory.chest))
|
||||
for _, item in pairs(inventory.get_contents()) do
|
||||
local name = item.name
|
||||
if allowed_items[name] then
|
||||
-- Quality is not tracked, so higher quality is stored as extra normal items in batches of ten
|
||||
local quality_level = prototypes.quality[item.quality].level
|
||||
local removed, stored = 0, 0
|
||||
if quality_level == 0 then
|
||||
removed, stored = item.count, item.count
|
||||
elseif item.count >= 10 then
|
||||
local batches = floor(item.count / 10)
|
||||
removed, stored = batches * 10, batches * (10 + quality_level * 3)
|
||||
end
|
||||
|
||||
if removed > 0 then
|
||||
local modded = items.modded_items[name]
|
||||
if modded and config.modded_auto_downgrade then
|
||||
Vlayer.insert_item(modded.base_game_equivalent, stored * modded.multiplier)
|
||||
elseif vlayer_data.storage.power_items[name] then
|
||||
local power_item = vlayer_data.storage.power_items[name]
|
||||
power_item.count = power_item.count + stored
|
||||
else
|
||||
Vlayer.insert_item(name, stored)
|
||||
end
|
||||
inventory.remove{ name = name, count = removed, quality = item.quality }
|
||||
for s_index, prop in pairs(vlayer_data) do
|
||||
local interfaces = prop.interfaces.storage_input
|
||||
prune_interfaces(interfaces)
|
||||
for _, interface in ipairs(interfaces) do
|
||||
local inventory = assert(interface.get_inventory(defines.inventory.chest))
|
||||
for _, item in pairs(inventory.get_contents()) do
|
||||
local name = item.name
|
||||
local count = item.count
|
||||
if allowed_items[name] then
|
||||
local quality_level = prototypes.quality[item.quality].level
|
||||
Vlayer.insert_item(s_index, name, count, quality_level)
|
||||
inventory.remove{ name = name, count = count, quality = item.quality }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -547,19 +559,23 @@ end
|
||||
|
||||
--- Fill the requests of the output interfaces from storage
|
||||
local function handle_output_interfaces()
|
||||
local interfaces = vlayer_data.interfaces.storage_output
|
||||
prune_interfaces(interfaces)
|
||||
for _, interface in ipairs(interfaces) do
|
||||
local inventory = assert(interface.get_inventory(defines.inventory.chest))
|
||||
for _, section in ipairs(assert(interface.get_logistic_sections()).sections) do
|
||||
for _, filter in pairs(section.filters) do
|
||||
local name = filter.value and filter.value.name
|
||||
if name and allowed_items[name] then
|
||||
local wanted = min(assert(filter.min) - inventory.get_item_count(name), vlayer_data.storage.items[name])
|
||||
if wanted > 0 and inventory.can_insert{ name = name, count = wanted } then
|
||||
local removed = Vlayer.remove_item(name, wanted)
|
||||
if removed > 0 then
|
||||
inventory.insert{ name = name, count = removed, quality = "normal" }
|
||||
for s_index, prop in pairs(vlayer_data) do
|
||||
local interfaces = prop.storage_output
|
||||
prune_interfaces(interfaces)
|
||||
for _, interface in ipairs(interfaces) do
|
||||
local inventory = assert(interface.get_inventory(defines.inventory.chest))
|
||||
for _, section in ipairs(assert(interface.get_logistic_sections()).sections) do
|
||||
for _, filter in pairs(section.filters) do
|
||||
local name = filter.value and filter.value.name
|
||||
local quality = filter.value and filter.value.quality
|
||||
if name and allowed_items[name] then
|
||||
local quality_level = prototypes.quality[quality].level
|
||||
local wanted = min(assert(filter.min) - inventory.get_item_count(name), prop.storage.items[name][quality_level])
|
||||
if wanted > 0 and inventory.can_insert{ name = name, count = wanted, quality = quality } then
|
||||
local removed = Vlayer.remove_item(s_index, name, wanted, quality_level)
|
||||
if removed > 0 then
|
||||
inventory.insert{ name = name, count = removed, quality = quality }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -572,118 +588,136 @@ end
|
||||
local function handle_unallocated()
|
||||
if config.unlimited_surface_area then return end
|
||||
|
||||
local unallocated_area = 0
|
||||
for name, count in pairs(vlayer_data.storage.unallocated) do
|
||||
unallocated_area = unallocated_area + allowed_items[name].required_area * count
|
||||
end
|
||||
if unallocated_area == 0 then return end
|
||||
for s_index, prop in pairs(vlayer_data) do
|
||||
local unallocated_area = 0
|
||||
for name, qnc in pairs(prop.storage.unallocated) do
|
||||
for _, count in pairs(qnc) do
|
||||
unallocated_area = unallocated_area + allowed_items[name].required_area * count
|
||||
end
|
||||
end
|
||||
if unallocated_area == 0 then return end
|
||||
|
||||
local properties = vlayer_data.properties
|
||||
local surplus_area = properties.total_surface_area - properties.used_surface_area
|
||||
for name, count in pairs(vlayer_data.storage.unallocated) do
|
||||
local allocated = min(count, floor(count * surplus_area / unallocated_area))
|
||||
if allocated > 0 then
|
||||
vlayer_data.storage.unallocated[name] = count - allocated
|
||||
allocate_item(name, allocated)
|
||||
count_unallocated_production(name, -allocated)
|
||||
local properties = prop.properties
|
||||
local surplus_area = properties.total_surface_area - properties.used_surface_area
|
||||
for name, qnc in pairs(prop.storage.unallocated) do
|
||||
for quality, count in pairs(qnc) do
|
||||
local allocated = min(count, floor(count * surplus_area / unallocated_area))
|
||||
if allocated > 0 then
|
||||
prop.storage.unallocated[name][quality] = count - allocated
|
||||
allocate_item(s_index, name, allocated, quality)
|
||||
count_unallocated_production(s_index, name, -allocated, quality)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the signals of the circuit interfaces to the statistics and stored items
|
||||
local function handle_circuit_interfaces()
|
||||
local interfaces = vlayer_data.interfaces.circuit
|
||||
prune_interfaces(interfaces)
|
||||
if #interfaces == 0 then return end
|
||||
for s_index, prop in pairs(vlayer_data) do
|
||||
local interfaces = prop.interfaces.circuit
|
||||
prune_interfaces(interfaces)
|
||||
if #interfaces == 0 then return end
|
||||
|
||||
local stats = Vlayer.get_statistics()
|
||||
for _, interface in ipairs(interfaces) do
|
||||
local control = interface.get_or_create_control_behavior() --[[@as LuaConstantCombinatorControlBehavior]]
|
||||
if control.sections_count == 0 then
|
||||
control.add_section()
|
||||
end
|
||||
local section = assert(control.sections[1])
|
||||
|
||||
-- Slots are cleared first because an item can not be set in two slots at once
|
||||
for index = section.filters_count, 1, -1 do
|
||||
section.clear_slot(index)
|
||||
end
|
||||
|
||||
local index = 1
|
||||
for stat_name, signal_name in pairs(circuit_signals) do
|
||||
local value = stats[stat_name] --[[@as number]]
|
||||
if stat_name:find("energy") then
|
||||
value = value / mega
|
||||
elseif stat_name == "production_multiplier" then
|
||||
value = value * 10000
|
||||
local stats = Vlayer.get_statistics()
|
||||
for _, interface in ipairs(interfaces) do
|
||||
local control = interface.get_or_create_control_behavior() --[[@as LuaConstantCombinatorControlBehavior]]
|
||||
if control.sections_count == 0 then
|
||||
control.add_section()
|
||||
end
|
||||
section.set_slot(index, { value = { type = "virtual", name = signal_name, quality = "normal" }, min = floor(value) })
|
||||
index = index + 1
|
||||
end
|
||||
local section = assert(control.sections[1])
|
||||
|
||||
for name, count in pairs(vlayer_data.storage.items) do
|
||||
if count > 0 and prototypes.item[name] then
|
||||
section.set_slot(index, { value = { type = "item", name = name, quality = "normal" }, min = count })
|
||||
-- Slots are cleared first because an item can not be set in two slots at once
|
||||
for index = section.filters_count, 1, -1 do
|
||||
section.clear_slot(index)
|
||||
end
|
||||
|
||||
local index = 1
|
||||
for stat_name, signal_name in pairs(circuit_signals) do
|
||||
local value = stats[stat_name] --[[@as number]]
|
||||
if stat_name:find("energy") then
|
||||
value = value / mega
|
||||
elseif stat_name == "production_multiplier" then
|
||||
value = value * 10000
|
||||
end
|
||||
section.set_slot(index, { value = { type = "virtual", name = signal_name, quality = "normal" }, min = floor(value) })
|
||||
index = index + 1
|
||||
end
|
||||
|
||||
for name, qnc in pairs(prop.storage.items) do
|
||||
for quality, count in pairs(qnc) do
|
||||
if count > 0 and prototypes.item[name][quality] then
|
||||
section.set_slot(index, { value = { type = "item", name = name, quality = quality_level_to_name[quality] }, min = count })
|
||||
index = index + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Produce energy, share it between the energy interfaces, and burn fuel when storage runs low
|
||||
local function handle_energy_interfaces()
|
||||
local storage = vlayer_data.storage
|
||||
local properties = vlayer_data.properties
|
||||
local production = properties.production * mega * (update_tick_energy / 60)
|
||||
storage.energy = storage.energy + floor(production * get_production_multiplier())
|
||||
for s_index, prop in pairs(vlayer_data) do
|
||||
local storage = prop.storage
|
||||
local properties = prop.properties
|
||||
local production = properties.production * mega * (update_tick_energy / 60)
|
||||
storage.energy = storage.energy + min(properties.input_limit, floor(production * get_production_multiplier(s_index)))
|
||||
|
||||
local interfaces = vlayer_data.interfaces.energy
|
||||
prune_interfaces(interfaces)
|
||||
if #interfaces > 0 then
|
||||
local available_energy = storage.energy
|
||||
for _, interface in ipairs(interfaces) do
|
||||
available_energy = available_energy + interface.energy
|
||||
local interfaces = prop.interfaces.energy
|
||||
prune_interfaces(interfaces)
|
||||
if #interfaces > 0 then
|
||||
local available_energy = storage.energy
|
||||
for _, interface in ipairs(interfaces) do
|
||||
available_energy = available_energy + interface.energy
|
||||
end
|
||||
|
||||
local discharge_rate = 2 * (production + properties.output_limit * mega) / #interfaces
|
||||
local fill_to = min(discharge_rate, floor(available_energy / #interfaces))
|
||||
for _, interface in ipairs(interfaces) do
|
||||
interface.electric_buffer_size = max(discharge_rate, interface.energy) -- A smaller buffer would lose energy
|
||||
local delta = fill_to - interface.energy
|
||||
storage.energy = storage.energy - delta
|
||||
interface.energy = interface.energy + delta
|
||||
end
|
||||
end
|
||||
|
||||
local discharge_rate = 2 * (production + properties.discharge * mega) / #interfaces
|
||||
local fill_to = min(discharge_rate, floor(available_energy / #interfaces))
|
||||
for _, interface in ipairs(interfaces) do
|
||||
interface.electric_buffer_size = max(discharge_rate, interface.energy) -- A smaller buffer would lose energy
|
||||
local delta = fill_to - interface.energy
|
||||
storage.energy = storage.energy - delta
|
||||
interface.energy = interface.energy + delta
|
||||
end
|
||||
end
|
||||
|
||||
local capacity = properties.capacity * mega
|
||||
if not config.unlimited_capacity and storage.energy > capacity then
|
||||
storage.energy = capacity
|
||||
return
|
||||
end
|
||||
|
||||
for _, power_item in pairs(storage.power_items) do
|
||||
local max_burn = capacity / 2 - storage.energy
|
||||
if power_item.count > 0 and max_burn > 0 then
|
||||
local burn = min(power_item.count, floor(max_burn / power_item.value))
|
||||
storage.energy = storage.energy + burn * power_item.value
|
||||
power_item.count = power_item.count - burn
|
||||
local capacity = properties.capacity * mega
|
||||
if not config.unlimited_capacity and storage.energy > capacity then
|
||||
storage.energy = capacity
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Take the day cycle from the mimic surface when it exists, otherwise from the config
|
||||
local function update_surface()
|
||||
if config.mimic_surface ~= "" then
|
||||
local surface = game.get_surface(config.mimic_surface)
|
||||
if surface then
|
||||
vlayer_data.surface = surface
|
||||
return
|
||||
end
|
||||
local function update_surface(event)
|
||||
-- global surface will have its data point to the main surface
|
||||
if not config.global_surface then
|
||||
return
|
||||
end
|
||||
|
||||
-- The config copy never has an index, so this avoids replacing it every time a surface changes
|
||||
if not vlayer_data.surface.index then
|
||||
vlayer_data.surface = table.deep_copy(surface_settings)
|
||||
if not vlayer_data[event.surface_index] then
|
||||
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
|
||||
end
|
||||
|
||||
@@ -706,11 +740,6 @@ Vlayer.on_init = update_surface -- The default surface exists before on_surface_
|
||||
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.events[Feature.events.on_config_updated] = function(event)
|
||||
if event.feature_name == feature.name and event.path == "mimic_surface" then
|
||||
update_surface()
|
||||
end
|
||||
end
|
||||
Vlayer.on_nth_tick[update_tick_storage] = update_storage
|
||||
Vlayer.on_nth_tick[update_tick_energy] = update_energy
|
||||
|
||||
|
||||
@@ -538,7 +538,7 @@ local function apply_personal_battery_recharge(player)
|
||||
local energy_to_give = math.min(math.floor(equipment.max_energy - equipment.energy), available_energy, recharge_amount)
|
||||
equipment.energy = equipment.energy + energy_to_give
|
||||
recharge_amount = recharge_amount - energy_to_give
|
||||
available_energy = Vlayer.energy_changed(-energy_to_give)
|
||||
available_energy = Vlayer.energy_changed(player.physical_surface_index, -energy_to_give)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,7 +32,7 @@ end
|
||||
--- Statistics shown as progress bars, in display order
|
||||
--- @type { name: string, caption: LocalisedString, tooltip: LocalisedString }[]
|
||||
local stats = {}
|
||||
for _, name in ipairs{ "solar", "accumulator", "surface-area", "sustained", "production", "capacity" } do
|
||||
for _, name in ipairs{ "production", "capacity", "sustained", "surface-area" } do
|
||||
stats[#stats + 1] = {
|
||||
name = name,
|
||||
caption = { "exp-gui_vlayer.caption-stat-" .. name },
|
||||
@@ -140,34 +140,26 @@ Elements.stats_table = Gui.define("vlayer/stats_table")
|
||||
--- Calculate the display data of every statistic, the same for every player
|
||||
--- @return table<string, ExpGui_Vlayer.elements.stat_bar.display_data>
|
||||
function Elements.stats_table.calculate_display_data()
|
||||
local statistics = Vlayer.get_statistics()
|
||||
local items = Vlayer.get_items()
|
||||
local allocated = Vlayer.get_allocated_items()
|
||||
local statistics = Vlayer.get_statistics(game.surfaces["nauvis"].index)
|
||||
local items = Vlayer.get_items(game.surfaces["nauvis"].index)
|
||||
local allocated = Vlayer.get_allocated_items(game.surfaces["nauvis"].index)
|
||||
return {
|
||||
solar = {
|
||||
value = allocated["solar-panel"] / max(items["solar-panel"], 1),
|
||||
caption = format_number(allocated["solar-panel"], false) .. " / " .. format_number(items["solar-panel"], false),
|
||||
},
|
||||
accumulator = {
|
||||
value = allocated["accumulator"] / max(items["accumulator"], 1),
|
||||
caption = format_number(allocated["accumulator"], false) .. " / " .. format_number(items["accumulator"], false),
|
||||
},
|
||||
["surface-area"] = {
|
||||
value = statistics.total_surface_area / max(statistics.surface_area, 1),
|
||||
caption = format_number(statistics.remaining_surface_area, false),
|
||||
},
|
||||
sustained = {
|
||||
value = statistics.energy_sustained / max(statistics.energy_total_production, 1),
|
||||
caption = format_energy(statistics.energy_sustained, "W") .. " / " .. format_energy(statistics.energy_total_production, "W"),
|
||||
},
|
||||
production = {
|
||||
value = statistics.energy_production / max(statistics.energy_max, 1),
|
||||
value = ceil(statistics.energy_production) / max(ceil(statistics.energy_max), 1),
|
||||
caption = format_energy(statistics.energy_production, "W") .. " / " .. format_energy(statistics.energy_max, "W"),
|
||||
},
|
||||
capacity = {
|
||||
value = statistics.energy_storage / max(statistics.energy_capacity, 1),
|
||||
caption = format_energy(statistics.energy_storage, "J") .. " / " .. format_energy(statistics.energy_capacity, "J"),
|
||||
},
|
||||
sustained = {
|
||||
value = ceil(statistics.energy_sustained) / max(statistics.energy_total_production, 1),
|
||||
caption = format_energy(statistics.energy_sustained, "W") .. " / " .. format_energy(statistics.energy_total_production, "W"),
|
||||
},
|
||||
["surface-area"] = {
|
||||
value = statistics.total_surface_area / max(statistics.surface_area, 1),
|
||||
caption = format_number(statistics.remaining_surface_area, false),
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
@@ -257,26 +249,6 @@ end
|
||||
--- @class ExpGui_Vlayer.elements.control_button.element_data
|
||||
--- @field controls LuaGuiElement
|
||||
|
||||
--- Button which refreshes the listed interfaces
|
||||
--- @class ExpGui_Vlayer.elements.refresh_button: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_Vlayer.elements.control_button.element_data>
|
||||
--- @overload fun(parent: LuaGuiElement, controls: LuaGuiElement): LuaGuiElement
|
||||
Elements.refresh_button = Gui.define("vlayer/refresh_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
caption = { "exp-gui_vlayer.caption-refresh" },
|
||||
}
|
||||
:style{
|
||||
width = 200,
|
||||
}
|
||||
:element_data{
|
||||
controls = Gui.from_argument(1),
|
||||
}
|
||||
:on_click(function(def, _, refresh_button)
|
||||
--- @cast def ExpGui_Vlayer.elements.refresh_button
|
||||
Elements.controls.refresh_interfaces(def.data[refresh_button].controls)
|
||||
end) --[[@as any]]
|
||||
|
||||
--- Button which opens the map at the selected interface
|
||||
--- @class ExpGui_Vlayer.elements.view_button: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_Vlayer.elements.control_button.element_data>
|
||||
@@ -367,7 +339,6 @@ Elements.controls = Gui.define("vlayer/controls")
|
||||
|
||||
local type_dropdown = Elements.type_dropdown(controls, controls)
|
||||
local interface_dropdown = Elements.interface_dropdown(controls)
|
||||
Elements.refresh_button(controls, controls)
|
||||
Elements.view_button(controls, controls)
|
||||
Elements.build_button(controls).visible = can_edit
|
||||
Elements.remove_button(controls, controls).visible = can_edit
|
||||
@@ -393,7 +364,7 @@ end
|
||||
function Elements.controls.get_selected_interface(controls)
|
||||
local elements = Elements.controls.data[controls]
|
||||
local interface_type = Elements.type_dropdown.get_selected(elements.type_dropdown)
|
||||
local interfaces = Vlayer.get_interfaces()[interface_type]
|
||||
local interfaces = Vlayer.get_interfaces(game.surfaces["nauvis"].index)[interface_type]
|
||||
return interface_type, Elements.interface_dropdown.get_selected(elements.interface_dropdown, interfaces)
|
||||
end
|
||||
|
||||
@@ -402,7 +373,7 @@ end
|
||||
function Elements.controls.refresh_interfaces(controls)
|
||||
local elements = Elements.controls.data[controls]
|
||||
local interface_type = Elements.type_dropdown.get_selected(elements.type_dropdown)
|
||||
Elements.interface_dropdown.refresh(elements.interface_dropdown, Vlayer.get_interfaces()[interface_type])
|
||||
Elements.interface_dropdown.refresh(elements.interface_dropdown, Vlayer.get_interfaces(game.surfaces["nauvis"].index)[interface_type])
|
||||
end
|
||||
|
||||
--- Refresh the listed interfaces of every online player, used when an interface is built or removed
|
||||
@@ -461,18 +432,7 @@ local function on_area_selected(event)
|
||||
interface_type = Elements.controls.get_selected_type(controls)
|
||||
end
|
||||
|
||||
-- Platforms have no chests, so a combinator marks the spot once the research allows it
|
||||
local marker_name = "steel-chest"
|
||||
if config.power_on_space and surface.platform and interface_type == "energy" then
|
||||
local research = config.power_on_space_research
|
||||
if force.technologies[research.name].level < research.level then
|
||||
player.print({ "exp-gui_vlayer.message-research", research.name, research.level }, Colors.orange_red)
|
||||
return
|
||||
end
|
||||
marker_name = "constant-combinator"
|
||||
end
|
||||
|
||||
local markers = surface.find_entities_filtered{ area = area, name = marker_name, force = force }
|
||||
local markers = surface.find_entities_filtered{ area = area, name = "steel-chest", force = force }
|
||||
if #markers == 0 then
|
||||
player.print({ "exp-gui_vlayer.message-no-chest" }, Colors.orange_red)
|
||||
return
|
||||
@@ -487,7 +447,7 @@ local function on_area_selected(event)
|
||||
return
|
||||
end
|
||||
|
||||
if #Vlayer.get_interfaces()[interface_type] >= config.interface_limit[interface_type] then
|
||||
if config.interface_limit[interface_type] >= 0 and #Vlayer.get_interfaces(game.surfaces["nauvis"].index)[interface_type] >= config.interface_limit[interface_type] then
|
||||
player.print({ "exp-gui_vlayer.message-limit", type_captions[interface_type] }, Colors.orange_red)
|
||||
return
|
||||
end
|
||||
|
||||
Reference in new issue
Block a user