UnrealisticReactors/scripts/heat/network.lua

666 lines
24 KiB
Lua

local rpath = (...):match("(.-)[^%.]+$")
local rroot = rpath:match("^([^%.]+%.)")
local get_reactor_core_power = require(rroot .. "entity.util").get_reactor_core_power
local mod = require(rpath .. "init")
local heat_buffer_transition_position = require(rpath .. "buffer").heat_buffer_transition_position
local heat_buffer_transitions = require(rpath .. "buffer").heat_buffer_transitions
local netmath = require(rpath .. "math")
local getpath = netmath.getpath
local testpath = netmath.testpath
local is_connected_outside = netmath.is_connected_outside
local chunk_nodes = netmath.chunk_nodes
local cell_nodes = netmath. cell_nodes
local connected_cells = netmath.connected_cells
local neighbour_cells = netmath.neighbour_cells
local get_chunk_neighbour = netmath.get_chunk_neighbour
local get_linked_entities = netmath.get_linked_entities
local get_entity_neighbour_cells = netmath.get_entity_neighbour_cells
local clear_heat_network_for_surface = netmath.clear_heat_network_for_surface
local cleanup_heat_network = netmath.cleanup_heat_network
local rm_heat_network_cell = netmath.rm_heat_network_cell
local get_heat_network_cell = netmath.get_heat_network_cell
local set_heat_network_cell = netmath.set_heat_network_cell
local get_heat_outlet = netmath.get_heat_outlet
local set_heat_outlet = netmath.set_heat_outlet
local isempty = require(rroot .. "util").isempty
local debug = require(rpath .. "debug")
local util = require(rpath .. "util")
local get2d = util.get2d
local set2d = util.set2d
local rm2d = util. rm2d
local sameposition = util.sameposition
-- local growarea = util. growarea
-- local subarea = util. subarea
-- local shrinkarea = util.shrinkarea
local function Coordinates(entity)
local x,y,z = entity.position.x,entity.position.y,entity.surface.index
return math.floor(x), math.floor(y), z
end
local CHUNK_SIZE = 32 -- in tiles
local function ChunkCoordinates(x,y,z)
return math.floor(x / CHUNK_SIZE), math.floor(y / CHUNK_SIZE), z
end
local function Vector(x,y,z) return {
x = x,
y = y,
z = z,
} end
-- FIXME area not used! could be removed or used to pimp split?
-- function Area(...) return {
-- left_top = Vector(...),
-- right_bottom = Vector(...),
-- } end
local function ChunkArea(x,y) return {
left_top = Vector(CHUNK_SIZE * (0 + x) - 0, CHUNK_SIZE * (0 + y) - 0),
right_bottom = Vector(CHUNK_SIZE * (1 + x) - 1, CHUNK_SIZE * (1 + y) - 1),
} end
local function ReactorPosition(entity) return {
id = entity.unit_number,
name = entity.name,
position = Vector(Coordinates(entity)),
-- cell = HeatNetworkCell(), -- HeatNetworkCell which the reactor belongs to
} end
local function HeatChunk(...) return {
position = Vector(ChunkCoordinates(...)),
area = ChunkArea(ChunkCoordinates(...)),
cells = {}, -- array of HeatNetworkCell indexed by itself
-- network = HeatNetwork(), -- network this chunk belongs to
border = {
[N] = {}, -- array of HeatNetworkCell indexed by x
[E] = {}, -- array of HeatNetworkCell indexed by y
[S] = {}, -- array of HeatNetworkCell indexed by x
[W] = {}, -- array of HeatNetworkCell indexed by y
},
count = {
cell = 0, -- number of HeatNetworkCell
[N] = 0, -- number of HeatNetworkCell
[E] = 0, -- number of HeatNetworkCell
[S] = 0, -- number of HeatNetworkCell
[W] = 0, -- number of HeatNetworkCell
},
} end
-- only required for debugging
local function HeatNetworkId()
local i = -1
for id in pairs(HEAT.ids) do
i = math.max(i,id)
end
local id = i + 1
HEAT.ids[id] = id
-- log("create new network " .. tostring(id))
return id -- uniq number
end
local function HeatNetwork() return {
id = HeatNetworkId(),
reactors = {}, -- array of ReactorPosition indexed by entity.unit_number
chunks = {}, -- array of HeatChunk indexed by x,y
count = {
chunk = 0, -- number of HeatChunk
cell = 0, -- number of HeatNetworkCell
reactor = 0, -- number of reactors
},
} end
local function HeatNetworkCell() return {
-- chunk = HeatChunk(), -- chunk this cell belongs to
entities = {}, -- matrix of heat-pipe and reactor entities indexed by x,y
reactors = {}, -- array of ReactorPosition indexed by entity.unit_number
-- area = Area(), -- bounding box of network
count = {
entity = 0, -- number of heat-pipes
reactor = 0, -- number of reactors
outlet = 0, -- number of reactor outlets
},
} end
local function set_chunk_borders(chunk, x,y, cell)
local p = Vector(x,y)
local count = cell and 1 or -1
for _,corner in ipairs{'left_top','right_bottom'} do
for k,v in pairs(p) do
if chunk.area[corner][k] == v then
local d = A[corner][k]
chunk.border[d][p[V[k]]] = cell
chunk.count[d] = chunk.count[d] + count
-- log(string.format("%s chunk border in network %s at x=%s y=%s", cell and "add cell to" or "remove cell from", chunk.network.id, x,y))
end
end
end
end
local function get_or_create_heat_network_chunk(x,y,z, network)
local cx,cy = ChunkCoordinates(x,y,z)
local chunk = get2d(network.chunks, cx,cy)
if chunk then return chunk end
chunk = HeatChunk(x,y,z)
chunk.network = network
-- log(string.format("create new chunk in network %s at x=%s y=%s z=%s", network.id, chunk.position.x,chunk.position.y,chunk.position.z))
set2d(network.chunks, cx,cy, chunk)
network.count.chunk = network.count.chunk + 1
return chunk
end
local function create_heat_network_cell(x,y,z, network)
local chunk = get_or_create_heat_network_chunk(x,y,z, network)
local cell = HeatNetworkCell()
-- log(string.format("create heat network cell in network %s at x=%s y=%s z=%s", network.id, x,y,z))
-- cell.area = growarea(cell.area, Area(x,y))
network.count.cell = network.count.cell + 1
chunk.count.cell = chunk.count.cell + 1
chunk.cells[cell] = cell
cell.chunk = chunk
return cell
end
local function create_heat_network(x,y,z)
local network = HeatNetwork()
local cell = create_heat_network_cell(x,y,z, network)
HEAT.network[network.id] = network
-- log(string.format("created heat network %s", network.id))
return cell
end
local function remove_heat_network(x,y,z, cell)
local chunk,network = cell.chunk,cell.chunk.network
rm_heat_network_cell(x,y,z)
set_chunk_borders(chunk, x,y, nil)
-- log(string.format("removed heat network %s", network.id))
if cell.count.entity + cell.count.reactor + cell.count.outlet > 0 then return end
chunk.cells[cell] = nil
chunk.count.cell = chunk.count.cell - 1
network.count.cell = network.count.cell - 1
if chunk.count.cell > 0 then return end
rm2d(network.chunks, chunk.position.x,chunk.position.y)
network.count.chunk = network.count.chunk - 1
if network.count.chunk > 0 then return end
-- network gets garbage collected
cleanup_heat_network(network.id)
end
local move_entities
local function move_cells(cell, position, offset, network, neighbours, inside, last, dst, ignore)
local old = cell.chunk
local x,y,z = position.x+offset.x,position.y+offset.y,old.position.z
if cell == ignore then
local entity = get2d(cell.entities, x,y)
if entity then
if inside[entity] == inside[last] then
-- log(string.format("leafing recursion cuz cell is connected inside at x=%s y=%s", x,y))
return
end
-- log(string.format("return to crawling at x=%s y=%s", x,y))
dst = create_heat_network_cell(x,y,z, network)
move_entities(entity, Vector(x,y), dst,cell, neighbours, inside)
end
return -- to crawling
end
local new = get_or_create_heat_network_chunk(x,y,z, network)
if old.network == new.network then return end
-- log(string.format("move cells into network %s from %s at x=%s y=%s z=%s", network.id,old.network.id, x,y,z))
cell.chunk = new
old.cells[cell] = nil
new.cells[cell] = cell
old.count.cell = old.count.cell - 1
new.count.cell = new.count.cell + 1
old.network.count.cell = old.network.count.cell - 1
network.count.cell = network.count.cell + 1
for id,reactor in pairs(cell.reactors) do
if not network.reactors[id] then
old.network.reactors[id] = nil
network.reactors[id] = reactor
old.network.count.reactor = old.network.count.reactor - 1
network.count.reactor = network.count.reactor + 1
end
end
if not (old.count.cell > 0) then
rm2d(old.network.chunks, ChunkCoordinates(x,y))
old.network.count.chunk = old.network.count.chunk - 1
end
neighbour_cells(old, cell, move_cells, network, neighbours, inside, last, dst, ignore)
set_chunk_borders(old, x,y, nil)
set_chunk_borders(new, x,y, cell)
for d in pairs(O) do
for c,other in pairs(old.border[d]) do
if other == cell then
old.border[d][c] = nil
new.border[d][c] = cell
old.count[d] = old.count[d] - 1
new.count[d] = new.count[d] + 1
end
end
end
end
move_entities = function (entity, position, new,old, neighbours, inside) -- salami tactics
local x,y,z = position.x,position.y,old.chunk.position.z -- use this instead of entity.position which could be in another cell
if not get2d(old.entities, x,y) then
local other = get_heat_network_cell(x,y,z)
if other ~= old then -- found outside
move_cells(other, position, Vector(0,0), new.chunk.network, neighbours,inside,entity,new,old)
end
return
end
-- log(string.format("move entity between networks from %s to %s at x=%s y=%s z=%s %s", old.chunk.network.id, new.chunk.network.id, x,y,z, serpent.line{from=old.count,to=new.count}))
-- new.area = growarea(new.area, Area(x,y))
if entity.type ~= "reactor" then
old.count.entity = old.count.entity - 1
new.count.entity = new.count.entity + 1
elseif old.reactors[entity.unit_number] then
old.count.reactor = old.count.reactor - 1
new.count.reactor = new.count.reactor + 1
local reactor = old.reactors[entity.unit_number]
old.reactors[reactor.id] = nil
new.reactors[reactor.id] = reactor
reactor.cell = new
old.chunk.network.reactors[reactor.id] = nil
new.chunk.network.reactors[reactor.id] = reactor
old.chunk.network.count.reactor = old.chunk.network.count.reactor - 1
new.chunk.network.count.reactor = new.chunk.network.count.reactor + 1
else
old.count.outlet = old.count.outlet - 1
new.count.outlet = new.count.outlet + 1
end
rm2d(old.entities, x,y)
set2d(new.entities, x,y, entity)
if old.chunk.network ~= new.chunk.network then
get_chunk_neighbour(old, x,y, move_cells, new.chunk.network, neighbours,inside,entity,new,old)
end
remove_heat_network(x,y,z, old)
set_heat_network_cell(x,y,z, new)
set_chunk_borders(new.chunk, x,y, new)
neighbours(entity, move_entities, new,old, neighbours, inside)
end
local function is_border(area,p)
for _,corner in ipairs{'left_top','right_bottom'} do
for k,v in pairs(p) do
if v == area[corner][k] then return true end
end
end
return false
end
local function counter(cell,_,count) count[cell], count.value = true, count.value + 1 end
local function insert_table(e,p,a,b) table.insert(a,e) table.insert(b,p) end
local function split_heat_network_cell(cell,x,y,z,entity)
local count = {value=0}
get_entity_neighbour_cells(entity, counter, count)
if count.value < 2 then return end -- this was the last
-- log(string.format("try to split network %s at at x=%s y=%s z=%s %s ", cell.chunk.network.id, x,y,z, entity.name))
-- log(dbgHeatNetwork(cell.chunk.network))
-- local area
local others,positions = {},{}
local outside,inside = get_linked_entities(cell)
local chunk_neighbours = chunk_nodes(cell.entities, outside)
local cell_neighbours = cell_nodes(cell.entities)
chunk_neighbours(entity, insert_table, others, positions)
local n,c = #others,table_size(count)-1
-- log(string.format("found %s entities in %s cells inside of %s total", n,c,count.value))
if n == 0 then return elseif n == 1 then
if not is_border(cell.chunk.area, Vector(x,y)) then return end
-- log(string.format("split heat network alone %s", serpent.line{count=cell.count}))
local connected = false
get_entity_neighbour_cells(entity, function (neighbour)
if not connected and cell.chunk ~= neighbour.chunk then
connected = testpath(cell, neighbour, connected_cells) -- outside
end
end)
if connected then -- outside connected
-- log(" ... but nothing happens, cuz cells are connected on the outside")
else
local p,other = positions[1],others[1]
local new = create_heat_network(p.x,p.y,z)
move_entities(other, p, new,cell, cell_neighbours, inside)
-- log("moved into new network " .. tostring(new.chunk.network.id))
-- log(dbgHeatNetwork(new.chunk.network))
end
return -- weird, lol
end
if c > 1 then
get_entity_neighbour_cells(entity, function (other,p)
if other ~= cell then
if not testpath(cell, other, connected_cells) then -- outside
local new = create_heat_network(p.x,p.y,z)
move_cells(other, p, Vector(0,0), new.chunk.network, cell_neighbours,new,cell)
-- log("moved neighbour into new network " .. tostring(new.chunk.network.id))
end
end
end)
end
local before = others[n]
-- log(string.format("split heat network %s", serpent.line{count=cell.count}))
for i,other in ipairs(others) do
local p = positions[i]
if get2d(cell.entities, p.x,p.y) then
if before and before ~= other then
local path = getpath(before, other, chunk_neighbours)
if path and #path == 2 and path[1] == entity then path = nil --[[log"WTF"]] end
local outside = is_connected_outside(path)
if path then
-- log(string.format("found path of length %s %sside", #path, outside and "out" or "in"))
for _,node in ipairs(path) do
-- log(node.name .. ": " .. dbgVector(node.position))
end
end
if not path or outside then
-- TODO determine which half is now smaller then the other and fill-move the smaller one. -- maybe impossibru ? -- maybe with area?
local network
if path then -- outside
if not testpath(before, other, cell_neighbours) then -- inside
-- log("splitting cell inside network")
local new = create_heat_network_cell(p.x,p.y,z, cell.chunk.network)
move_entities(other, p, new,cell, cell_neighbours, inside)
network = new.chunk.network
end
else -- inside
local new = create_heat_network(p.x,p.y,z)
move_entities(other, p, new,cell, cell_neighbours, inside)
network = new.chunk.network
end
-- area = growarea(area, new.area)
other = nil -- skip this before
if not path then
-- log("moved into new network " .. tostring(network.id))
-- log(dbgHeatNetwork(network))
end
end
end
before = other or before
end
end
-- cell.area = subarea(area, cell.area)
end
local function network_score(network)
local count = network.count
return count.chunk + count.cell + count.reactor
end
local function chunk_score(chunk)
local sum = 0 for _,count in pairs(chunk.count) do sum = sum + count end
return sum + network_score(chunk.network)
end
local function cell_score(cell)
local count = cell.count
return 2 * count.entity + count.reactor + count.outlet + chunk_score(cell.chunk)
end
local function merge_heat_chunk(a,b)
if chunk_score(a) < chunk_score(b) then a,b = b,a end -- spare some work
-- log(string.format("merge heat chunk at x=%s y=%s z=%s", a.position.x,a.position.y,a.position.z))
for k,count in pairs(b.count) do
a.count[k] = a.count[k] + count
end
for cell in pairs(b.cells) do
a.cells[cell] = cell
cell.chunk = a
end
for d,border in pairs(b.border) do
for c,cell in pairs(border) do
a.border[d][c] = cell
end
end
return a
end
local function merge_heat_network(a,b)
local an,bn = a.chunk.network, b.chunk.network
if an ~= bn then
if cell_score(a) < cell_score(b) then an,bn = bn,an end -- spare some work
-- log(string.format("merge heat network %s into %s %s", bn.id, an.id, serpent.line{from=bn.count,to=an.count}))
for k,count in pairs(bn.count) do
an.count[k] = an.count[k] + count
end
for id,reactor in pairs(bn.reactors) do
an.reactors[id] = reactor
end
for x,xs in pairs(bn.chunks) do
for y,chunk in pairs(xs) do
local current = get2d(an.chunks, x,y)
chunk.network = an
if current then
an.count.chunk = an.count.chunk - 1
chunk = merge_heat_chunk(current, chunk)
end
set2d(an.chunks, x,y, chunk)
end
end
cleanup_heat_network(bn.id)
end
return a
end
local function merge_heat_network_cells(x,y,z, a,b)
if not b or b == a then return a end
if sameposition(a.chunk.position, b.chunk.position) then
if cell_score(a) < cell_score(b) then a,b = b,a end -- spare some work
-- log(string.format("merge heat network cells %s into %s %s", b.chunk.network.id, a.chunk.network.id, serpent.line{from=b.count,to=a.count}))
-- a.area = growarea(a.area, b.area)
for k,count in pairs(b.count) do
a.count[k] = a.count[k] + count
end
local z = a.chunk.position.z
for x,xs in pairs(b.entities) do
for y,entity in pairs(xs) do
set2d(a.entities, x,y, entity)
set_heat_network_cell(x,y,z, a)
set_chunk_borders(b.chunk, x,y, nil)
set_chunk_borders(a.chunk, x,y, a)
end
end
for _,reactor in pairs(b.reactors) do
local p = reactor.position
reactor.cell = a
a.reactors[reactor.id] = reactor
end
for d,border in pairs(b.chunk.border) do
for c,cell in pairs(border) do
if cell == b then
a.chunk.border[d][c] = a
end
end
end
b.chunk.cells[b] = nil
b.chunk.count.cell = b.chunk.count.cell - 1
b.chunk.network.count.cell = b.chunk.network.count.cell - 1
end
return merge_heat_network(a,b)
end
local function add_entity_to_network_cell(x,y,z,entity)
local cell = create_heat_network(x,y,z)
local is_reactor = entity.type == 'reactor'
for i,p,o in heat_buffer_transitions(entity) do
-- add heat pipe neighbours
-- log(string.format("looking at x=%s y=%s for heat network cell", o.x,o.y))
cell = merge_heat_network_cells(x,y,z, cell, get_heat_network_cell(o.x,o.y,z))
-- add reactor neighbours
if is_reactor or i == 1 then -- assuming heat pipe is just one tile in size (all connection positions are the same)
local reactors = get_heat_outlet(p.x,p.y,z, {})
-- log(string.format("test x=%s y=%s for outlet with %s reactors", p.x,p.y, table_size(reactors)))
for _,reactor in pairs(reactors) do
local q = heat_buffer_transition_position(reactor, reactor.position,p)
cell = merge_heat_network_cells(x,y,z, cell, get_heat_network_cell(q.x,q.y,z))
end
end
end
set_heat_network_cell(x,y,z, cell)
set_chunk_borders(cell.chunk, x,y, cell)
set2d(cell.entities, x,y, entity)
if is_reactor then
cell.chunk.network.count.reactor = cell.chunk.network.count.reactor + 1
cell.count.reactor = cell.count.reactor + 1
else
cell.count.entity = cell.count.entity + 1
end
-- log(string.format("added cell to network %s at x=%s y=%s z=%s %s", cell.chunk.network.id, x,y,z, serpent.line{count=cell.count}))
return cell
end
local function remove_entity_from_network_cell(x,y,z,entity,cell)
local network = cell.chunk.network
if entity.type ~= "reactor" then
cell.count.entity = cell.count.entity - 1
else
cell.chunk.network.count.reactor = cell.chunk.network.count.reactor - 1
cell.count.reactor = cell.count.reactor - 1
end
rm2d(cell.entities, x,y)
remove_heat_network(x,y,z, cell)
if cell.count.entity + cell.count.reactor + cell.count.outlet > 0 then
split_heat_network_cell(cell, x,y,z, entity)
end
-- shrinkarea(cell.area,cell.entities) -- shrink area by entity on border
-- log(string.format("removed cell from network %s at x=%s y=%s z=%s %s", cell.chunk.network.id, x,y,z, serpent.line{count=cell.count}))
-- log(dbgHeatNetwork(network))
end
local function get_heat_network(entity)
local cell = get_heat_network_cell(Coordinates(entity))
return cell and cell.chunk.network
end
local function get_connected_reactors(entity)
local network = get_heat_network(entity)
return network and network.reactors or {}
end
local function calculate_corner_index(area, x,y)
local i = 1
if x < area.left_top.x or area.right_bottom.x < x then i = i + 1 end
if y < area.left_top.y or area.right_bottom.y < y then i = i + 2 end
return i -- {1=(x,y inside area), 2=(x outside area), 3=(y outside area), 4=(x,y outside area)}
end
local function add_reactor_to_network(entity)
if get_reactor_core_power(entity) then return end -- ignore reactor cores
local x,y,z = Coordinates(entity)
-- log(string.format("add reactor to network x=%s y=%s z=%s", x,y,z))
local cell = add_entity_to_network_cell(x,y,z,entity)
local reactor = ReactorPosition(entity)
cell.chunk.network.reactors[reactor.id] = reactor
cell.reactors[reactor.id] = reactor
reactor.cell = cell
-- merge outlets
local corner = {cell} -- up to 4 cells
for _,p,o in heat_buffer_transitions(entity) do
local reactors = get_heat_outlet(o.x,o.y,z, {})
-- log(string.format("outlet at x=%s y=%s z=%s with %s others", o.x,o.y,z, table_size(reactors)))
reactors[reactor.id] = reactor
set_heat_outlet(o.x,o.y,z, reactors)
local i = calculate_corner_index(cell.chunk.area, p.x,p.y)
local other = corner[i] or create_heat_network_cell(p.x,p.y,z, cell.chunk.network)
if not get2d(other.entities, p.x,p.y) then
other.count.outlet = other.count.outlet + 1
set2d(other.entities, p.x,p.y, entity)
set_chunk_borders(other.chunk, p.x,p.y, other)
set_heat_network_cell(p.x,p.y,z, other)
end
other = merge_heat_network_cells(p.x,p.y,z, other, get_heat_network_cell(o.x,o.y,z))
corner[i] = other
end
debug.update()
end
local function remove_reactor_from_network(entity)
if get_reactor_core_power(entity) then return end -- ignore reactor cores
local x,y,z = Coordinates(entity)
local cell = get_heat_network_cell(x,y,z)
local reactor = cell and cell.reactors[entity.unit_number]
if not reactor then return end
-- log(string.format("remove reactor from network cell %s at x=%s y=%s z=%s %s", cell.chunk.network.id, x,y,z, serpent.line{count=cell.count}))
-- cleanup outlets
local remove = {}
for _,p,o in heat_buffer_transitions(entity) do
local reactors = get_heat_outlet(o.x,o.y,z, {})
reactors[reactor.id] = nil
if isempty(reactors) then reactors = nil end
set_heat_outlet(o.x,o.y,z, reactors)
set2d(remove, p.x,p.y, get_heat_network_cell(p.x,p.y,z))
end
-- remove from cells now cuz of duplicate positions
for x,xs in pairs(remove) do
for y,other in pairs(xs) do
other.count.outlet = other.count.outlet - 1
remove_heat_network(x,y,z, other)
set_chunk_borders(other.chunk, x,y)
rm2d(other.entities, x,y)
end
end
remove_entity_from_network_cell(x,y,z, entity, cell)
cell.chunk.network.reactors[reactor.id] = nil
cell.reactors[reactor.id] = nil
reactor.cell = nil
debug.update()
end
local function add_heat_pipe_to_network(entity)
local x,y,z = Coordinates(entity)
-- log(string.format("add heat pipe to network cell at x=%s y=%s z=%s", x,y,z))
add_entity_to_network_cell(x,y,z,entity)
debug.update()
end
local function remove_heat_pipe_from_network(entity)
local x,y,z = Coordinates(entity)
local cell = get_heat_network_cell(x,y,z)
if not cell then return end
-- log(string.format("remove heat pipe from network cell %s at x=%s y=%s z=%s %s", cell.chunk.network.id, x,y,z, serpent.line{count=cell.count}))
remove_entity_from_network_cell(x,y,z, entity, cell)
debug.update()
end
local function remove_heat_network_from_surface(z)
-- log("clear heat networks on surface " .. tostring(z))
clear_heat_network_for_surface(z)
debug.update()
end
local function remove_heat_network_from_chunk(x,y,z) -- chunk coords
-- log(string.format("clear heat networks from chunk at x=%s y=%s z=%s", x,y,z))
local area = ChunkArea(ChunkCoordinates(x,y,z))
for x = area.left_top.x, area.right_bottom.x do
for y = area.left_top.y, area.right_bottom.y do
local cell = get_heat_network_cell(x,y,z)
if cell then remove_heat_network(x,y,z, cell) end
end
end
debug.update()
end
-- circular dependency
mod.add_reactor = add_reactor_to_network
mod.add_heat_pipe = add_heat_pipe_to_network
return { -- exports
init=mod.init, load=mod.load,
get = get_heat_network,
get_connected_reactors = get_connected_reactors,
add_reactor = add_reactor_to_network,
remove_reactor = remove_reactor_from_network,
add_heat_pipe = add_heat_pipe_to_network,
remove_heat_pipe = remove_heat_pipe_from_network,
remove_from_surface = remove_heat_network_from_surface,
remove_from_chunk = remove_heat_network_from_chunk,
debug = debug,
}