235 lines
7.9 KiB
Lua

local Fluid = {}
Fluid.color = {r = 167/255, g = 229/255, b = 255/255}
Fluid.entity_types = {'pipe', 'pipe-to-ground', 'pump', 'storage-tank', 'infinity-pipe', 'offshore-pump'}
Fluid.unlocked = function(force) return force.technologies['factory-connection-type-fluid'].researched end
local blacklist = {
['factory-fluid-dummy-connector-' .. defines.direction.north] = true,
['factory-fluid-dummy-connector-' .. defines.direction.east] = true,
['factory-fluid-dummy-connector-' .. defines.direction.south] = true,
['factory-fluid-dummy-connector-' .. defines.direction.west] = true
}
local function is_connected(dummy_connector, entity)
if blacklist[entity.name] then return false end
for _, e in pairs(dummy_connector.neighbours[1]) do
if e.unit_number == entity.unit_number then return true end
end
end
Fluid.replace_entity = function(original, new_name)
if original.name == new_name then return original end
local surface, position, force, direction, player
surface = original.surface
position = original.position
force = original.force
direction = original.direction
player = original.last_user
local boxes = original.fluidbox
local box = boxes[1]
original.destroy()
local new = surface.create_entity{
name = new_name,
position = position,
force = force,
direction = direction,
player = player,
raise_built = false,
create_build_effect_smoke = false
}
if box ~= nil then
local new_boxes = new.fluidbox
new_boxes[1] = box
end
return new
end
remote_api.replace_entity = Fluid.replace_entity
Fluid.connect = function(factory, cid, cpos, outside_entity, inside_entity, settings)
if inside_entity == outside_entity then return nil end
if not (outside_entity.fluidbox.get_capacity(1) > 0 and inside_entity.fluidbox.get_capacity(1) > 0) then return nil end
local inside_connector = factory.inside_surface.create_entity{
name = 'factory-fluid-dummy-connector-' .. cpos.direction_in,
position = {factory.inside_x + cpos.inside_x + cpos.indicator_dx, factory.inside_y + cpos.inside_y + cpos.indicator_dy}
}
inside_connector.destructible = false
inside_connector.operable = false
inside_connector.rotatable = false
local outside_connector = factory.outside_surface.create_entity{
name = 'factory-fluid-dummy-connector-' .. cpos.direction_out,
position = {factory.outside_x + cpos.outside_x - cpos.indicator_dx, factory.outside_y + cpos.outside_y - cpos.indicator_dy}
}
outside_connector.destructible = false
outside_connector.operable = false
outside_connector.rotatable = false
if not is_connected(inside_connector, inside_entity) or not is_connected(outside_connector, outside_entity) then
inside_connector.destroy()
outside_connector.destroy()
return nil
end
local p = game.entity_prototypes
local names = {
original_inside = inside_entity.name,
original_outside = outside_entity.name,
inside_input = p['factory-' .. inside_entity.name .. '-input'] and ('factory-' .. inside_entity.name .. '-input') or inside_entity.name,
outside_input = p['factory-' .. outside_entity.name .. '-input'] and ('factory-' .. outside_entity.name .. '-input') or outside_entity.name,
inside_output = p['factory-' .. inside_entity.name .. '-output'] and ('factory-' .. inside_entity.name .. '-output') or inside_entity.name,
outside_output = p['factory-' .. outside_entity.name .. '-output'] and ('factory-' .. outside_entity.name .. '-output') or outside_entity.name
}
if settings.input_mode then
outside_entity = Fluid.replace_entity(outside_entity, names.outside_input)
inside_entity = Fluid.replace_entity(inside_entity, names.inside_output)
else
outside_entity = Fluid.replace_entity(outside_entity, names.outside_output)
inside_entity = Fluid.replace_entity(inside_entity, names.inside_input)
end
return {
names = names,
outside = outside_entity,
inside = inside_entity,
inside_connector = inside_connector,
outside_connector = outside_connector,
outside_capacity = outside_entity.fluidbox.get_capacity(1),
inside_capacity = inside_entity.fluidbox.get_capacity(1),
do_tick_update = true
}
end
Fluid.recheck = function(conn)
return conn.outside.valid and conn.inside.valid and conn.inside_connector.valid and conn.outside_connector.valid
and is_connected(conn.inside_connector, conn.inside) and is_connected(conn.outside_connector, conn.outside)
end
local DELAYS = {5, 10, 30, 120}
local DEFAULT_DELAY = 30
Fluid.indicator_settings = {'d0'}
for _,v in pairs(DELAYS) do
table.insert(Fluid.indicator_settings, 'd' .. v)
end
local function make_valid_delay(delay)
for _,v in pairs(DELAYS) do
if v == delay then return v end
end
return 0 -- Catchall
end
Fluid.direction = function(conn)
if conn._settings.input_mode then
return 'd' .. make_valid_delay(conn._settings.delay or DEFAULT_DELAY), conn._factory.layout.connections[conn._id].direction_in
else
return 'd' .. make_valid_delay(conn._settings.delay or DEFAULT_DELAY), conn._factory.layout.connections[conn._id].direction_out
end
end
Fluid.rotate = function(conn)
conn._settings.input_mode = not conn._settings.input_mode
if conn._settings.input_mode then
conn.outside = Fluid.replace_entity(conn.outside, conn.names.outside_input)
conn.inside = Fluid.replace_entity(conn.inside, conn.names.inside_output)
return {'factory-connection-text.input-mode'}
else
conn.outside = Fluid.replace_entity(conn.outside, conn.names.outside_output)
conn.inside = Fluid.replace_entity(conn.inside, conn.names.inside_input)
return {'factory-connection-text.output-mode'}
end
conn.outside_capacity, conn.inside_capacity = conn.inside_capacity, conn.outside_capacity
end
Fluid.adjust = function(conn, positive)
local delay = conn._settings.delay or DEFAULT_DELAY
if positive then
for i = #DELAYS,1,-1 do
if DELAYS[i] < delay then
delay = DELAYS[i]
break
end
end
conn._settings.delay = delay
return {'factory-connection-text.update-faster', delay}
else
for i = 1,#DELAYS do
if DELAYS[i] > delay then
delay = DELAYS[i]
break
end
end
conn._settings.delay = delay
return {'factory-connection-text.update-slower', delay}
end
end
local function transfer(from, to, from_cap, to_cap)
local from_boxes = from.fluidbox
local from_box = from_boxes[1]
local to_boxes = to.fluidbox
local to_box = to_boxes[1]
if from_box ~= nil then
if to_box == nil then
if from_box.amount <= to_cap then
from_boxes[1] = nil
to_boxes[1] = from_box
else
from_box.amount = from_box.amount - to_cap
from_boxes[1] = from_box
from_box.amount = to_cap
to_boxes[1] = from_box
end
elseif to_box.name == from_box.name then
local total = from_box.amount + to_box.amount
if total <= to_cap then
from_boxes[1] = nil
to_box.temperature = (from_box.amount*from_box.temperature + to_box.amount*to_box.temperature)/total
to_box.amount = total
to_boxes[1] = to_box
else
to_box.temperature = (to_box.amount*to_box.temperature + (to_cap-to_box.amount)*from_box.temperature)/to_cap
to_box.amount = to_cap
to_boxes[1] = to_box
from_box.amount = total - to_cap
from_boxes[1] = from_box
end
end
end
end
Fluid.tick = function(conn)
local outside = conn.outside
local inside = conn.inside
local outside_cap = conn.outside_capacity
local inside_cap = conn.inside_capacity
if outside.valid and inside.valid then
local input_mode = conn._settings.input_mode or false
if input_mode then -- Input
transfer(outside, inside, outside_cap, inside_cap)
else -- Output
transfer(inside, outside, inside_cap, outside_cap)
end
return conn._settings.delay or DEFAULT_DELAY
else
return false
end
end
Fluid.destroy = function(conn)
if conn.outside_connector.valid then conn.outside_connector.destroy() end
if conn.inside_connector.valid then conn.inside_connector.destroy() end
if conn.outside.valid then Fluid.replace_entity(conn.outside, conn.names.original_outside) end
if conn.inside.valid then Fluid.replace_entity(conn.inside, conn.names.original_inside) end
end
return Fluid