173 lines
4.8 KiB
Lua

local util = require("lualib.util")
local M = {}
local function inserters_in_position(bp_entities, starting_index)
local out = {}
local x = bp_entities[starting_index].position.x
local y = bp_entities[starting_index].position.y
for i=starting_index,#bp_entities do
local ent = bp_entities[i]
if ent.position.x == x and ent.position.y == y and util.is_miniloader_inserter(ent) then
out[#out+1] = ent
else
break
end
end
return out
end
local function tag_with_configuration(surface, bp_entity)
local inserters = surface.find_entities_filtered{ type = "inserter", position = bp_entity.position }
if not inserters[1] then return end
if not global.split_lane_configuration[inserters[1].unit_number] then return end
local right_lane_inserter = inserters[2]
if right_lane_inserter and util.is_output_miniloader_inserter(right_lane_inserter) then
bp_entity.tags = {
right_lane_settings = util.capture_settings(right_lane_inserter),
}
end
end
local function find_slaves(miniloader_inserters, to_remove)
for i = 2, #miniloader_inserters do
local inserter = miniloader_inserters[i]
to_remove[inserter.entity_number] = true
end
end
local function remove_connections(bp_entity, to_remove_set)
local connections = bp_entity.connections
if not connections then
return
end
for circuit_id, circuit_connections in pairs(connections) do
if not circuit_id:find("^Cu") then -- ignore copper cables on power switch
for wire_name, wire_connections in pairs(circuit_connections) do
local new_wire_connections = {}
for _, connection in ipairs(wire_connections) do
if not to_remove_set[connection.entity_id] then
new_wire_connections[#new_wire_connections+1] = connection
end
end
if next(new_wire_connections) then
circuit_connections[wire_name] = new_wire_connections
else
circuit_connections[wire_name] = nil
end
end
end
end
end
local function remove_entities(bp_entities, to_remove_set)
local cnt = #bp_entities
for i=1,cnt do
remove_connections(bp_entities[i], to_remove_set)
end
local w = 1
for r=1,cnt do
if not to_remove_set[bp_entities[r].entity_number] then
bp_entities[w] = bp_entities[r]
w = w + 1
end
end
for i=w,cnt do
bp_entities[i] = nil
end
end
function M.is_setup_bp(stack)
return stack and
stack.valid and
stack.valid_for_read and
stack.is_blueprint and
stack.is_blueprint_setup()
end
local huge = math.huge
function M.bounding_box(bp_entities)
local left = math.huge
local top = math.huge
local right = -math.huge
local bottom = -math.huge
for _, e in pairs(bp_entities) do
local pos = e.position
if pos.x < left then left = pos.x - 0.5 end
if pos.y < top then top = pos.y - 0.5 end
if pos.x > right then right = pos.x + 0.5 end
if pos.y > bottom then bottom = pos.y + 0.5 end
end
local center_x = (right + left) / 2
local center_y = (bottom + top) / 2
return {
left_top = {x = left - center_x, y = top - center_y},
right_bottom = {x = right - center_x, y = bottom - center_y},
}
end
function M.get_blueprint_to_setup(player_index)
local player = game.players[player_index]
-- normal drag-select
local blueprint_to_setup = player.blueprint_to_setup
if blueprint_to_setup
and blueprint_to_setup.valid_for_read
and blueprint_to_setup.is_blueprint_setup() then
return blueprint_to_setup
end
-- alt drag-select (skips configuration dialog)
local cursor_stack = player.cursor_stack
if cursor_stack
and cursor_stack.valid_for_read
and cursor_stack.is_blueprint
and cursor_stack.is_blueprint_setup() then
local bp = cursor_stack
while bp.is_blueprint_book do
bp = bp.get_inventory(defines.inventory.item_main)[bp.active_index]
end
return bp
end
-- update of existing blueprint
local opened_blueprint = global.previous_opened_blueprint_for[player_index]
if opened_blueprint
and opened_blueprint.tick == game.tick
and opened_blueprint.blueprint
and opened_blueprint.blueprint.valid_for_read
and opened_blueprint.blueprint.is_blueprint_setup() then
return opened_blueprint.blueprint
end
end
function M.filter_miniloaders(bp, surface)
local bp_entities = bp.get_blueprint_entities()
if not bp_entities then
return
end
local to_remove = {}
local i = 1
while i <= #bp_entities do
local ent = bp_entities[i]
if util.is_miniloader_inserter(ent) then
local overlapping = inserters_in_position(bp_entities, i)
tag_with_configuration(surface, overlapping[1])
find_slaves(overlapping, to_remove)
i = i + #overlapping
else
i = i + 1
end
end
if next(to_remove) then
remove_entities(bp_entities, to_remove)
bp.set_blueprint_entities(bp_entities)
end
end
return M