|
local remove_entry = table.remove_entry |
|
local max_grid_updates = 10 |
|
local MulDivRound = MulDivRound |
|
local Min, Max, Clamp = Min, Max, Clamp |
|
local HighestConsumePriority = config.FluidGridHighestConsumePriority or 1 |
|
local LowestConsumePriority = config.FluidGridLowestConsumePriority or 1 |
|
local BeyondHighestConsumePriority = HighestConsumePriority - 1 |
|
|
|
|
|
|
|
|
|
DefineClass.FluidGrid = { |
|
__parents = { "InitDone" }, |
|
grid_resource = "electricity", |
|
player = false, |
|
|
|
elements = false, |
|
producers = false, |
|
consumers = false, |
|
storages = false, |
|
switches = false, |
|
|
|
smart_connections = 0, |
|
|
|
total_production = 0, |
|
total_throttled_production = 0, |
|
total_consumption = 0, |
|
total_variable_consumption = 0, |
|
total_charge = 0, |
|
total_discharge = 0, |
|
total_storage_capacity = 0, |
|
|
|
current_storage_delta = 0, |
|
current_production = 0, |
|
current_production_delta = 0, |
|
current_throttled_production = 0, |
|
current_consumption = 0, |
|
current_variable_consumption = 0, |
|
current_storage = 0, |
|
|
|
visual_mesh = false, |
|
visuals_thread = false, |
|
needs_visual_update = false, |
|
|
|
update_thread = false, |
|
needs_update = false, |
|
update_consumers = false, |
|
consumers_supplied = false, |
|
|
|
production_thread = false, |
|
production_interval = config.FluidGridProductionInterval or 10000, |
|
restart_supply_delay = config.FluidGridRestartDelay or 10000, |
|
restart_supply_time = 0, |
|
|
|
LogChangedElements = empty_func, |
|
} |
|
|
|
function FluidGrid:Init() |
|
self.elements = {} |
|
self.producers = {} |
|
self.consumers = {} |
|
assert(HighestConsumePriority <= LowestConsumePriority) |
|
for priority = HighestConsumePriority, LowestConsumePriority do |
|
self.consumers[priority] = { consumption = 0, variable_consumption = 0 } |
|
end |
|
self.storages = {} |
|
self.switches = {} |
|
self:RestartThreads() |
|
end |
|
|
|
function FluidGrid:RestartThreads() |
|
DeleteThread(self.update_thread) |
|
self.update_thread = CreateGameTimeThread(function(self) |
|
local updates, last_element_count, last_update = 0, #self.elements |
|
while true do |
|
local now = GameTime() |
|
local elem_count = #self.elements |
|
if last_update ~= now or elem_count ~= last_element_count then |
|
last_update = now |
|
last_element_count = elem_count |
|
updates = 0 |
|
end |
|
while self.needs_update do |
|
if updates == max_grid_updates then |
|
self:LogChangedElements() |
|
assert(false, "Infinite grid update recursion!") |
|
break |
|
end |
|
self.needs_update = false |
|
procall(self.UpdateGrid, self) |
|
updates = updates + 1 |
|
end |
|
WaitWakeup() |
|
end |
|
end, self) |
|
|
|
DeleteThread(self.production_thread) |
|
self.production_thread = CreateGameTimeThread(function(self, production_interval) |
|
while true do |
|
Sleep(production_interval) |
|
procall(self.Production, self, production_interval) |
|
end |
|
end, self, self.production_interval) |
|
|
|
DeleteThread(self.visuals_thread) |
|
self.visuals_thread = CreateGameTimeThread(function() |
|
while true do |
|
while self.needs_visual_update do |
|
self.needs_visual_update = false |
|
procall(self.UpdateVisuals, self) |
|
end |
|
WaitWakeup() |
|
end |
|
end) |
|
end |
|
|
|
function FluidGrid:Done() |
|
local grid_resource = self.grid_resource |
|
for priority = HighestConsumePriority, LowestConsumePriority do |
|
for _, consumer in ipairs(self.consumers[priority]) do |
|
if consumer.current_consumption > 0 and consumer.grid == self then |
|
local old = consumer.current_consumption |
|
consumer.current_consumption = 0 |
|
consumer.owner:SetConsumption(grid_resource, old, 0) |
|
end |
|
end |
|
end |
|
for _, element in ipairs(self.elements) do |
|
if element.grid == self then |
|
element.grid = false |
|
end |
|
end |
|
DeleteThread(self.update_thread) |
|
self.update_thread = false |
|
DeleteThread(self.production_thread) |
|
self.production_thread = false |
|
DeleteThread(self.visuals_thread) |
|
self.visuals_thread = false |
|
DoneObject(self.visual_mesh) |
|
self.visual_mesh = false |
|
Msg("FluidGridDestroyed", self) |
|
end |
|
|
|
function FluidGrid:AddElement(element, skip_update) |
|
element.grid = self |
|
self.elements[#self.elements + 1] = element |
|
if element.production then |
|
self.total_production = self.total_production + element.production |
|
self.total_throttled_production = self.total_throttled_production + element.throttled_production |
|
self.producers[#self.producers + 1] = element |
|
end |
|
local consumption = element.consumption |
|
if consumption then |
|
local consumer_list = self.consumers[element.consume_priority] |
|
if element.variable_consumption then |
|
self.total_variable_consumption = self.total_variable_consumption + consumption |
|
consumer_list.variable_consumption = consumer_list.variable_consumption + consumption |
|
else |
|
self.total_consumption = self.total_consumption + consumption |
|
consumer_list.consumption = consumer_list.consumption + consumption |
|
end |
|
consumer_list[#consumer_list + 1] = element |
|
end |
|
if element.charge then |
|
self.total_charge = self.total_charge + element.charge |
|
self.total_discharge = self.total_discharge + element.discharge |
|
if element.discharge > 0 then |
|
self.current_storage = self.current_storage + element.current_storage |
|
end |
|
self.total_storage_capacity = self.total_storage_capacity + element.storage_capacity |
|
self.storages[#self.storages + 1] = element |
|
end |
|
if element.is_switch then |
|
self.switches[#self.switches + 1] = element |
|
self:UpdateSmartConnections() |
|
end |
|
|
|
if not skip_update then |
|
self:DelayedUpdateGrid(consumption) |
|
self:DelayedUpdateVisuals() |
|
end |
|
Msg("FluidGridAddElement", self, element) |
|
end |
|
|
|
function FluidGrid:RemoveElement(element, skip_update) |
|
if element.grid ~= self then return end |
|
if element.current_consumption > 0 then |
|
local old = element.current_consumption |
|
element.current_consumption = 0 |
|
element.owner:SetConsumption(self.grid_resource, old, 0) |
|
end |
|
element.grid = false |
|
remove_entry(self.elements, element) |
|
if element.production then |
|
self.total_production = self.total_production - element.production |
|
self.total_throttled_production = self.total_throttled_production - element.throttled_production |
|
remove_entry(self.producers, element) |
|
end |
|
local consumption = element.consumption |
|
if consumption then |
|
local consumer_list = self.consumers[element.consume_priority] |
|
if element.variable_consumption then |
|
self.total_variable_consumption = self.total_variable_consumption - consumption |
|
consumer_list.variable_consumption = consumer_list.variable_consumption - consumption |
|
else |
|
self.total_consumption = self.total_consumption - consumption |
|
consumer_list.consumption = consumer_list.consumption - consumption |
|
end |
|
remove_entry(consumer_list, element) |
|
end |
|
if element.current_storage then |
|
self.total_charge = self.total_charge - element.charge |
|
self.total_discharge = self.total_discharge - element.discharge |
|
if element.discharge > 0 then |
|
self.current_storage = self.current_storage - element.current_storage |
|
end |
|
self.total_storage_capacity = self.total_storage_capacity - element.storage_capacity |
|
remove_entry(self.storages, element) |
|
end |
|
if element.is_switch then |
|
remove_entry(self.switches, element) |
|
self:UpdateSmartConnections() |
|
end |
|
|
|
if #(self.elements or "") == 0 then |
|
self:delete() |
|
return |
|
end |
|
if not skip_update then |
|
self:DelayedUpdateGrid() |
|
self:DelayedUpdateVisuals() |
|
end |
|
Msg("FluidGridRemoveElement", self, element) |
|
end |
|
|
|
function FluidGrid:CountConsumers(func, ...) |
|
local count = 0 |
|
func = func or return_true |
|
for priority = HighestConsumePriority, LowestConsumePriority do |
|
for _, consumer in ipairs(self.consumers[priority]) do |
|
if func(consumer, ...) then |
|
count = count + 1 |
|
end |
|
end |
|
end |
|
return count |
|
end |
|
|
|
function FluidGrid:DelayedUpdateGrid(update_consumers) |
|
self.update_consumers = self.update_consumers or update_consumers |
|
self.needs_update = true |
|
Wakeup(self.update_thread) |
|
end |
|
|
|
function FluidGrid:UpdateGrid(update_consumers) |
|
update_consumers = self.update_consumers or update_consumers |
|
self.update_consumers = false |
|
local total_production = self.total_production |
|
local total_discharge = self.total_discharge |
|
local current_consumption = 0 |
|
local current_variable_consumption = 0 |
|
local consumers_supplied = false |
|
|
|
local ConsumePriorityLimit = (GameTime() - self.restart_supply_time < 0) and (self.consumers_supplied or BeyondHighestConsumePriority) or LowestConsumePriority |
|
|
|
local total_supply = total_production + total_discharge |
|
for priority = HighestConsumePriority, ConsumePriorityLimit do |
|
local consumer_list = self.consumers[priority] |
|
|
|
assert(consumer_list) |
|
if #(consumer_list or "") > 0 and current_consumption + current_variable_consumption + consumer_list.consumption <= total_supply then |
|
consumers_supplied = priority |
|
current_consumption = current_consumption + current_variable_consumption + consumer_list.consumption |
|
current_variable_consumption = consumer_list.variable_consumption |
|
if current_consumption + current_variable_consumption >= total_supply then |
|
current_variable_consumption = Min(current_variable_consumption, total_supply - current_consumption) |
|
break |
|
end |
|
end |
|
end |
|
assert(current_consumption <= self.total_consumption) |
|
current_consumption = current_consumption + current_variable_consumption |
|
assert(current_consumption <= total_supply) |
|
local storage_delta = Clamp(total_production - current_consumption, - total_discharge, self.total_charge) |
|
self.current_throttled_production = Min(total_production - current_consumption - storage_delta, self.total_throttled_production) |
|
self.current_storage_delta = storage_delta |
|
self.current_consumption = current_consumption |
|
self.current_production = total_production - self.current_throttled_production |
|
self.current_production_delta = self.current_production - current_consumption |
|
|
|
local old_consumers_supplied = self.consumers_supplied |
|
local old_current_variable_consumption = self.current_variable_consumption |
|
self.consumers_supplied = consumers_supplied |
|
self.current_variable_consumption = current_variable_consumption |
|
if consumers_supplied ~= old_consumers_supplied then |
|
update_consumers = true |
|
if (consumers_supplied or BeyondHighestConsumePriority) < (old_consumers_supplied or BeyondHighestConsumePriority) then |
|
self.restart_supply_time = GameTime() + self.restart_supply_delay |
|
end |
|
Msg("FluidGridConsumersSupplied", self, old_consumers_supplied, consumers_supplied) |
|
end |
|
if old_current_variable_consumption ~= current_variable_consumption then |
|
update_consumers = true |
|
Msg("FluidGridVariableConsumption", self, old_consumers_supplied, consumers_supplied) |
|
end |
|
|
|
if update_consumers then |
|
local grid_resource = self.grid_resource |
|
local consumers_variable_consumption = consumers_supplied and self.consumers[consumers_supplied].variable_consumption |
|
consumers_supplied = consumers_supplied or BeyondHighestConsumePriority |
|
for priority = HighestConsumePriority, LowestConsumePriority do |
|
for _, consumer in ipairs(self.consumers[priority]) do |
|
local consumption = priority > consumers_supplied and 0 |
|
or priority < consumers_supplied and consumer.consumption |
|
or consumer.variable_consumption and MulDivRound(consumer.consumption, current_variable_consumption, consumers_variable_consumption) or consumer.consumption |
|
local old_consumption = consumer.current_consumption |
|
if old_consumption ~= consumption then |
|
consumer.current_consumption = consumption |
|
consumer.owner:SetConsumption(grid_resource, old_consumption, consumption) |
|
end |
|
end |
|
end |
|
end |
|
ObjModifiedDelayed(self) |
|
end |
|
|
|
function FluidGrid:DelayedUpdateVisuals() |
|
self.needs_visual_update = true |
|
Wakeup(self.visuals_thread) |
|
end |
|
|
|
function FluidGrid:UpdateVisuals() |
|
local active = self.consumers_supplied |
|
local color = active and const.PowerGridActiveColor or const.PowerGridInactiveColor |
|
local joint_color = active and const.PowerGridActiveJointColor or const.PowerGridInactiveJointColor |
|
local mesh_pstr = pstr("") |
|
local pos |
|
for i, element in ipairs(self.elements) do |
|
local owner = element.owner |
|
assert(IsValid(owner)) |
|
if IsValid(owner) then |
|
pos = pos or owner:GetPos() |
|
owner:AddFluidGridVisuals(self.grid_resource, pos, color, joint_color, mesh_pstr) |
|
end |
|
end |
|
local mesh |
|
if #mesh_pstr > 0 then |
|
mesh = self.visual_mesh |
|
mesh = IsValid(mesh) and mesh or PlaceObject("Mesh") |
|
mesh:SetDepthTest(true) |
|
mesh:SetMesh(mesh_pstr) |
|
mesh:SetPos(pos) |
|
end |
|
if self.visual_mesh ~= mesh then |
|
DoneObject(self.visual_mesh) |
|
self.visual_mesh = mesh |
|
end |
|
end |
|
|
|
function FluidGrid:UpdateSmartConnections() |
|
local smart_connections = 0 |
|
for _, switch in ipairs(self.switches) do |
|
smart_connections = smart_connections | switch.switch_mask |
|
end |
|
if self.smart_connections == smart_connections then return end |
|
local changed_connections = self.smart_connections ~ smart_connections |
|
self.smart_connections = smart_connections |
|
local grid_resource = self.grid_resource |
|
for _, producer in ipairs(self.producers) do |
|
if (producer.smart_connection or 0) & changed_connections ~= 0 then |
|
producer.owner:SmartConnectionChange(grid_resource) |
|
end |
|
end |
|
for priority = HighestConsumePriority, LowestConsumePriority do |
|
for _, consumer in ipairs(self.consumers[priority]) do |
|
if (consumer.smart_connection or 0) & changed_connections ~= 0 then |
|
consumer.owner:SmartConnectionChange(grid_resource) |
|
end |
|
end |
|
end |
|
end |
|
|
|
function FluidGrid:IsSmartConnectionOn(smart_connection) |
|
if not smart_connection then return true end |
|
return (self.smart_connections & smart_connection) ~= 0 |
|
end |
|
|
|
function FluidGrid:Production(production_interval) |
|
local grid_resource = self.grid_resource |
|
|
|
local current_throttled_production = self.current_throttled_production |
|
local total_throttled_production = self.total_throttled_production |
|
for _, producer in ipairs(self.producers) do |
|
producer.current_throttled_production = total_throttled_production > 0 |
|
and MulDivRound(producer.throttled_production, current_throttled_production, total_throttled_production) or 0 |
|
local production = producer.production - producer.current_throttled_production |
|
producer.owner:OnProduce(grid_resource, production, production_interval) |
|
end |
|
|
|
for priority = HighestConsumePriority, LowestConsumePriority do |
|
for _, consumer in ipairs(self.consumers[priority]) do |
|
consumer.owner:OnConsume(grid_resource, consumer.current_consumption, production_interval) |
|
end |
|
end |
|
|
|
local total_charge = self.total_charge |
|
local total_discharge = self.total_discharge |
|
local storage_delta = self.current_storage_delta |
|
if storage_delta > 0 and total_charge > 0 then |
|
for _, storage in ipairs(self.storages) do |
|
storage:AddStoredCharge(MulDivRound(storage_delta, storage.charge_efficiency * storage.charge, 100 * total_charge), self) |
|
end |
|
elseif storage_delta < 0 and total_discharge > 0 then |
|
for _, storage in ipairs(self.storages) do |
|
storage:AddStoredCharge(MulDivRound(storage_delta, storage.discharge, total_discharge), self) |
|
end |
|
end |
|
if Platform.developer then |
|
|
|
local current_storage, total_charge, total_discharge = 0, 0, 0 |
|
for _, storage in ipairs(self.storages) do |
|
if storage.discharge > 0 then |
|
current_storage = current_storage + storage.current_storage |
|
end |
|
total_charge = total_charge + storage.charge |
|
total_discharge = total_discharge + storage.discharge |
|
end |
|
assert(self.current_storage == current_storage) |
|
assert(self.total_charge == total_charge) |
|
assert(self.total_discharge == total_discharge) |
|
self.current_storage = current_storage |
|
self.total_charge = total_charge |
|
self.total_discharge = total_discharge |
|
end |
|
self:DelayedUpdateGrid() |
|
end |
|
|
|
function MergeGrids(new_grid, grid) |
|
if grid == new_grid then return end |
|
for i, element in ipairs(grid.elements) do |
|
new_grid:AddElement(element) |
|
end |
|
grid:delete() |
|
end |
|
|
|
|
|
|
|
|
|
DefineClass.FluidGridElementOwner = { |
|
__parents = { "InitDone" }, |
|
} |
|
|
|
|
|
AutoResolveMethods.SetConsumption = true |
|
function FluidGridElementOwner:SetConsumption(resource, old_amount, new_amount) |
|
end |
|
|
|
|
|
function FluidGridElementOwner:SetStorageState(resource, state) |
|
end |
|
|
|
|
|
function FluidGridElementOwner:OnProduce(resource, amount, production_interval) |
|
end |
|
|
|
|
|
function FluidGridElementOwner:OnConsume(resource, amount, production_interval) |
|
end |
|
|
|
|
|
AutoResolveMethods.ChangeStoredAmount = true |
|
function FluidGridElementOwner:ChangeStoredAmount(resource, storage, old_storage) |
|
end |
|
|
|
|
|
function FluidGridElementOwner:SmartConnectionChange(resource) |
|
end |
|
|
|
|
|
function FluidGridElementOwner:AddFluidGridVisuals(grid_resource, origin, color, joint_color, mesh_pstr) |
|
end |
|
|
|
|
|
|
|
|
|
DefineClass.FluidGridElement = { |
|
__parents = { "InitDone" }, |
|
grid = false, |
|
owner = false, |
|
smart_connection = false, |
|
smart_connection2 = false, |
|
|
|
production = false, |
|
throttled_production = 0, |
|
current_throttled_production = 0, |
|
|
|
consumption = false, |
|
variable_consumption = false, |
|
current_consumption = 0, |
|
consume_priority = config.FluidGridDefaultConsumePriority or HighestConsumePriority, |
|
|
|
storage_active = false, |
|
charge = false, |
|
discharge = false, |
|
storage_capacity = false, |
|
current_storage = false, |
|
max_charge = false, |
|
max_discharge = false, |
|
charge_efficiency = 100, |
|
storage_state = "", |
|
min_discharge_amount = 0, |
|
|
|
is_connector = false, |
|
|
|
is_switch = false, |
|
switch_state = 0, |
|
switch_mask = 0, |
|
|
|
RegisterConsumptionChange = empty_func, |
|
} |
|
|
|
function NewFluidConnector(owner) |
|
assert(IsValid(owner)) |
|
return FluidGridElement:new{ |
|
owner = owner, |
|
is_connector = true, |
|
} |
|
end |
|
|
|
function NewFluidSwitch(owner, consumption, variable_consumption) |
|
assert(IsValid(owner)) |
|
return FluidGridElement:new{ |
|
owner = owner, |
|
is_switch = true, |
|
smart_connection = 1, |
|
switch_mask = 1, |
|
consumption = consumption or false, |
|
variable_consumption = variable_consumption, |
|
} |
|
end |
|
|
|
function NewFluidProducer(owner, production, throttled_production) |
|
assert(IsValid(owner)) |
|
return FluidGridElement:new{ |
|
owner = owner, |
|
production = production or 0, |
|
throttled_production = throttled_production or 0, |
|
} |
|
end |
|
|
|
function NewFluidConsumer(owner, consumption, variable_consumption) |
|
assert(IsValid(owner)) |
|
return FluidGridElement:new{ |
|
owner = owner, |
|
consumption = consumption or 0, |
|
variable_consumption = variable_consumption, |
|
} |
|
end |
|
|
|
function NewFluidStorage(owner, storage_capacity, current_storage, max_charge, max_discharge, charge_efficiency, min_discharge_amount) |
|
assert(IsValid(owner)) |
|
return FluidGridElement:new{ |
|
owner = owner, |
|
charge = max_charge, |
|
discharge = 0, |
|
current_storage = current_storage, |
|
storage_capacity = storage_capacity, |
|
max_charge = max_charge, |
|
max_discharge = max_discharge, |
|
charge_efficiency = charge_efficiency, |
|
storage_state = "empty", |
|
min_discharge_amount = min_discharge_amount, |
|
} |
|
end |
|
|
|
function FluidGridElement:Done() |
|
if self.grid then |
|
self.grid:RemoveElement(self) |
|
self.grid = nil |
|
end |
|
end |
|
|
|
function FluidGridElement:SetProduction(new_production, new_throttled_production, skip_update) |
|
assert(self.production) |
|
new_production = Max(new_production, 0) |
|
new_throttled_production = Max(new_throttled_production, 0) |
|
if self.production == new_production and self.throttled_production == new_throttled_production then return end |
|
local grid = self.grid |
|
if grid then |
|
grid.total_production = grid.total_production + new_production - self.production |
|
grid.total_throttled_production = grid.total_throttled_production - self.throttled_production + new_throttled_production |
|
end |
|
self.production = new_production |
|
self.throttled_production = new_throttled_production |
|
if grid and not skip_update then |
|
grid:DelayedUpdateGrid() |
|
end |
|
return true |
|
end |
|
|
|
function FluidGridElement:SetConsumption(new_consumption, skip_update) |
|
assert(self.consumption) |
|
new_consumption = Max(new_consumption, 0) |
|
if self.consumption == new_consumption then return end |
|
self:RegisterConsumptionChange() |
|
local grid = self.grid |
|
if grid then |
|
local delta = new_consumption - self.consumption |
|
local consumer_list = grid.consumers[self.consume_priority] |
|
if self.variable_consumption then |
|
grid.total_variable_consumption = grid.total_variable_consumption + delta |
|
consumer_list.variable_consumption = consumer_list.variable_consumption + delta |
|
else |
|
grid.total_consumption = grid.total_consumption + delta |
|
consumer_list.consumption = consumer_list.consumption + delta |
|
end |
|
end |
|
self.consumption = new_consumption |
|
|
|
if grid and not skip_update then |
|
grid:DelayedUpdateGrid(true) |
|
end |
|
return true |
|
end |
|
|
|
function FluidGridElement:SetConsumePriority(new_priority, skip_update) |
|
assert(self.consumption) |
|
new_priority = Clamp(new_priority, HighestConsumePriority, LowestConsumePriority) |
|
if self.consume_priority == new_priority then return end |
|
self:RegisterConsumptionChange() |
|
local grid = self.grid |
|
if grid then |
|
local old_consumer_list = grid.consumers[self.consume_priority] |
|
local consumer_list = grid.consumers[new_priority] |
|
if self.variable_consumption then |
|
old_consumer_list.variable_consumption = old_consumer_list.variable_consumption - self.consumption |
|
consumer_list.variable_consumption = consumer_list.variable_consumption + self.consumption |
|
else |
|
old_consumer_list.consumption = old_consumer_list.consumption - self.consumption |
|
consumer_list.consumption = consumer_list.consumption + self.consumption |
|
end |
|
remove_entry(old_consumer_list, self) |
|
consumer_list[#consumer_list + 1] = self |
|
end |
|
self.consume_priority = new_priority |
|
|
|
if grid and not skip_update then |
|
grid:DelayedUpdateGrid(true) |
|
end |
|
return true |
|
end |
|
|
|
|
|
function FluidGridElement:SetStorageCapacity(new_storage_capacity) |
|
if self.storage_capacity == new_storage_capacity then return end |
|
local grid = self.grid |
|
if grid then |
|
grid.total_storage_capacity = grid.total_storage_capacity - self.storage_capacity + Max(new_storage_capacity, 0) |
|
end |
|
self.storage_capacity = new_storage_capacity |
|
if grid then |
|
grid:DelayedUpdateGrid() |
|
end |
|
end |
|
|
|
function FluidGridElement:SetStorage(max_charge, max_discharge) |
|
if self.max_charge == max_charge and self.max_discharge == max_discharge then return end |
|
self.max_charge = max_charge |
|
self.max_discharge = max_discharge |
|
local grid = self.grid |
|
self:UpdateStorageChargeDischarge(grid) |
|
if grid then |
|
grid:DelayedUpdateGrid() |
|
end |
|
end |
|
|
|
function FluidGridElement:UpdateStorageChargeDischarge(grid) |
|
local current_storage = self.current_storage |
|
local new_charge = Min(self.storage_capacity - current_storage, self.max_charge) |
|
local new_discharge = self.storage_state == "charging" and current_storage < self.min_discharge_amount and 0 |
|
or Min(current_storage, self.max_discharge) |
|
local old_charge, old_discharge = self.charge, self.discharge |
|
if new_charge == old_charge and new_discharge == old_discharge then return end |
|
self.charge = new_charge |
|
self.discharge = new_discharge |
|
if grid then |
|
grid.total_charge = grid.total_charge - old_charge + new_charge |
|
grid.total_discharge = grid.total_discharge - old_discharge + new_discharge |
|
if new_discharge ~= old_discharge then |
|
if new_discharge == 0 then |
|
|
|
grid.current_storage = grid.current_storage - current_storage |
|
elseif old_discharge == 0 then |
|
|
|
grid.current_storage = grid.current_storage + current_storage |
|
end |
|
end |
|
end |
|
end |
|
|
|
function FluidGridElement:AddStoredCharge(delta, grid) |
|
assert(self.current_storage) |
|
local storage_capacity = self.storage_capacity |
|
local old_storage = self.current_storage |
|
local current_storage = Clamp(old_storage + delta, 0, storage_capacity) |
|
if current_storage == old_storage then return end |
|
self.current_storage = current_storage |
|
if self.discharge > 0 then |
|
grid.current_storage = grid.current_storage + current_storage - old_storage |
|
end |
|
self:UpdateStorageChargeDischarge(grid) |
|
|
|
local state |
|
if current_storage >= storage_capacity then |
|
state = "full" |
|
elseif current_storage <= 0 then |
|
state = "empty" |
|
elseif current_storage < old_storage then |
|
state = "discharging" |
|
else |
|
state = "charging" |
|
end |
|
if self.storage_state ~= state then |
|
self.storage_state = state |
|
self.owner:SetStorageState(grid.grid_resource, state) |
|
end |
|
self.owner:ChangeStoredAmount(grid.grid_resource, current_storage, old_storage) |
|
end |
|
|
|
function FluidGridElement:SetStoredAmount(amount) |
|
return self:AddStoredCharge(amount - self.current_storage, self.grid) |
|
end |
|
|
|
function FluidGridElement:SetSmartConnection(smart_connection_index) |
|
local smart_connection = smart_connection_index and (1 << (smart_connection_index - 1)) or false |
|
local old_value = self.smart_connection |
|
if old_value == smart_connection then return end |
|
self.smart_connection = smart_connection |
|
self:SetSwitchState(self.switch_state) |
|
end |
|
|
|
function FluidGridElement:GetSmartConnection() |
|
local smart_connection = self.smart_connection |
|
local result = smart_connection and LastSetBit(smart_connection) |
|
return result and result + 1 |
|
end |
|
|
|
function FluidGridElement:SetSmartConnection2(smart_connection_index) |
|
local smart_connection2 = smart_connection_index and (1 << (smart_connection_index - 1)) or 0 |
|
local old_value = self.smart_connection2 |
|
if old_value == smart_connection2 then return end |
|
self.smart_connection2 = smart_connection2 |
|
self:SetSwitchState(self.switch_state) |
|
end |
|
|
|
function FluidGridElement:GetSmartConnection2() |
|
local smart_connection2 = self.smart_connection2 |
|
local result = smart_connection2 and LastSetBit(smart_connection2) |
|
return result and result + 1 |
|
end |
|
|
|
function FluidGridElement:GetSwitchState() |
|
return self.switch_state |
|
end |
|
|
|
function FluidGridElement:SetSwitchState(state) |
|
self.switch_state = state |
|
local mask = ((state & 1 == 1) and self.smart_connection or 0) |
|
| ((state & 2 == 2) and self.smart_connection2 or 0) |
|
if self.switch_mask == mask then return end |
|
self.switch_mask = mask |
|
if self.grid then |
|
self.grid:UpdateSmartConnections() |
|
end |
|
return true |
|
end |
|
|
|
function FluidGridElementOwner:AsyncCheatShowGrid() |
|
DbgToggleFluidGrid(self:GetPowerGrid()) |
|
end |
|
|
|
if Platform.developer then |
|
|
|
FluidGridElement.grid_changed = false |
|
FluidGridElement.grid_changes = 0 |
|
function FluidGridElement:RegisterConsumptionChange() |
|
local now = GameTime() |
|
if self.grid_changed == now then |
|
self.grid_changes = self.grid_changes + 1 |
|
else |
|
self.grid_changed = now |
|
self.grid_changes = nil |
|
end |
|
end |
|
|
|
|
|
function FluidGrid:LogChangedElements() |
|
local changed = {} |
|
for _, element in ipairs(self.elements) do |
|
if element.grid_changes > 0 then |
|
changed[#changed + 1] = element |
|
end |
|
end |
|
table.sortby_field_descending(changed, "grid_changes") |
|
print("Most changed elements in the last", max_grid_updates, "grid updates:") |
|
for i=1,Min(#changed, 10) do |
|
local element = changed[i] |
|
local owner = element.owner |
|
print(owner and owner.class or "<no owner>", element.grid_changes) |
|
end |
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|