226 lines
5.9 KiB
Lua
226 lines
5.9 KiB
Lua
local M = {}
|
|
|
|
-- Position adjustments
|
|
|
|
function M.moveposition(position, offset)
|
|
return {x=position.x + offset.x, y=position.y + offset.y}
|
|
end
|
|
|
|
function M.offset(direction, longitudinal, orthogonal)
|
|
if direction == defines.direction.north then
|
|
return {x=orthogonal, y=-longitudinal}
|
|
end
|
|
|
|
if direction == defines.direction.south then
|
|
return {x=-orthogonal, y=longitudinal}
|
|
end
|
|
|
|
if direction == defines.direction.east then
|
|
return {x=longitudinal, y=orthogonal}
|
|
end
|
|
|
|
if direction == defines.direction.west then
|
|
return {x=-longitudinal, y=-orthogonal}
|
|
end
|
|
end
|
|
|
|
function M.box_centered_at(position, radius)
|
|
return {
|
|
left_top = M.moveposition(position, M.offset(defines.direction.north, radius, -radius)),
|
|
right_bottom = M.moveposition(position, M.offset(defines.direction.south, radius, -radius)),
|
|
}
|
|
end
|
|
|
|
function M.expand_box(box, delta)
|
|
return {
|
|
left_top = { x = box.left_top.x - delta, y = box.left_top.y - delta },
|
|
right_bottom = { x = box.right_bottom.x + delta, y = box.right_bottom.y + delta },
|
|
}
|
|
end
|
|
|
|
function M.is_empty_box(box)
|
|
local size_x = box.right_bottom.x - box.left_top.x
|
|
local size_y = box.right_bottom.y - box.left_top.y
|
|
return size_x < 0.01 and size_y < 0.01
|
|
end
|
|
|
|
function M.opposite_direction(direction)
|
|
if direction >= 4 then
|
|
return direction - 4
|
|
end
|
|
return direction + 4
|
|
end
|
|
|
|
function M.orthogonal_direction(direction)
|
|
if direction < 6 then
|
|
return direction + 2
|
|
end
|
|
return 0
|
|
end
|
|
|
|
function M.position_key(entity)
|
|
return entity.surface.name .. "@" .. entity.position.x .. "," .. entity.position.y
|
|
end
|
|
|
|
function M.railloader_inserters(entity, pattern)
|
|
local out = {}
|
|
local inserters = entity.surface.find_entities_filtered{
|
|
type = "inserter",
|
|
position = entity.position,
|
|
force = entity.force,
|
|
}
|
|
if not pattern then
|
|
return inserters
|
|
end
|
|
for _, e in ipairs(inserters) do
|
|
if string.find(e.name, pattern) ~= nil then
|
|
out[#out+1] = e
|
|
end
|
|
end
|
|
return out
|
|
end
|
|
|
|
function M.railloader_filter_inserters(entity)
|
|
return M.railloader_inserters(entity, "^railu?n?loader%-inserter$")
|
|
end
|
|
|
|
function M.railloader_universal_inserters(entity)
|
|
return M.railloader_inserters(entity, "^railu?n?loader%-universal%-inserter$")
|
|
end
|
|
|
|
function M.railloader_cargo_wagon_inserters(entity)
|
|
local filter_inserters = M.railloader_filter_inserters(entity)
|
|
if next(filter_inserters) then
|
|
return filter_inserters
|
|
end
|
|
return M.railloader_universal_inserters(entity)
|
|
end
|
|
|
|
function M.railloader_interface_inserters(entity)
|
|
return M.railloader_inserters(entity, "^railu?n?loader%-interface%-inserter$")
|
|
end
|
|
|
|
function M.is_railloader_chest(entity)
|
|
return string.find(entity.name, "^railu?n?loader%-chest$") ~= nil
|
|
end
|
|
|
|
function M.is_filter_inserter(inserter)
|
|
return string.find(inserter.name, "loader%-inserter$") ~= nil
|
|
end
|
|
|
|
function M.find_railloaders_from_chest(chest)
|
|
local out = {}
|
|
local area = M.expand_box(chest.bounding_box, 1)
|
|
local es = chest.surface.find_entities_filtered{
|
|
type = "container",
|
|
area = area,
|
|
force = chest.force,
|
|
}
|
|
for _, e in ipairs(es) do
|
|
if M.is_railloader_chest(e) then
|
|
out[#out+1] = e
|
|
end
|
|
end
|
|
return out
|
|
end
|
|
|
|
function M.railloader_type(name)
|
|
return string.match(name, "^rail(u?n?loader)%-")
|
|
end
|
|
|
|
function M.loader_direction(loader)
|
|
local rail = loader.surface.find_entities_filtered{
|
|
type = "straight-rail",
|
|
area = M.box_centered_at(loader.position, 0.6),
|
|
}[1]
|
|
if rail and rail.valid then
|
|
return rail.direction
|
|
end
|
|
end
|
|
|
|
function M.interface_inserter_name_for_loader(loader)
|
|
return "rail" .. M.railloader_type(loader.name) .. "-interface-inserter"
|
|
end
|
|
|
|
function M.find_inserter_for_interface(loader, interface)
|
|
local type = M.railloader_type(loader.name)
|
|
local interface_position = interface.position
|
|
local inserters = loader.surface.find_entities_filtered{
|
|
name = M.interface_inserter_name_for_loader(loader),
|
|
position = loader.position,
|
|
}
|
|
for _, inserter in ipairs(inserters) do
|
|
local target_interface_position = inserter[type == "loader" and "pickup_position" or "drop_position"]
|
|
if target_interface_position.x == interface_position.x and
|
|
target_interface_position.y == interface_position.y then
|
|
return inserter
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function M.loader_position_for_interface(loader, interface)
|
|
local offset = { x = 1.5, y = 1.5 }
|
|
for _, axis in ipairs{"x", "y"} do
|
|
if interface.position[axis] < loader.position[axis] then
|
|
offset[axis] = offset[axis] * -1
|
|
end
|
|
end
|
|
return { x = loader.position.x + offset.x, y = loader.position.y + offset.y }
|
|
end
|
|
|
|
function M.find_chests_from_railloader(loader)
|
|
local position = loader.position
|
|
local is_horiz = M.loader_direction(loader) == defines.direction.east
|
|
local area = {
|
|
left_top = {
|
|
x = position.x - (is_horiz and 2.5 or 1.5),
|
|
y = position.y - (is_horiz and 1.5 or 2.5),
|
|
},
|
|
right_bottom = {
|
|
x = position.x + (is_horiz and 2.5 or 1.5),
|
|
y = position.y + (is_horiz and 1.5 or 2.5),
|
|
},
|
|
}
|
|
local entities = loader.surface.find_entities_filtered{
|
|
area = area,
|
|
force = loader.force,
|
|
}
|
|
local out = {}
|
|
for _, e in ipairs(entities) do
|
|
if string.find(e.type, "container$") and not M.is_railloader_chest(e) then
|
|
out[#out+1] = e
|
|
end
|
|
end
|
|
return out
|
|
end
|
|
|
|
function M.insert_or_spill(entity, stack, inventories)
|
|
if not stack or not stack.valid_for_read then
|
|
return
|
|
end
|
|
|
|
if stack.prototype.stackable then
|
|
for _, inv in ipairs(inventories) do
|
|
local inserted = inv.insert(stack)
|
|
stack.count = stack.count - inserted
|
|
if not stack.valid_for_read then
|
|
return
|
|
end
|
|
end
|
|
else
|
|
for _, inv in ipairs(inventories) do
|
|
for slot=1,#inv do
|
|
if not inv[slot].valid_for_read then
|
|
inv[slot].swap_stack(stack)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
entity.surface.spill_item_stack(entity.position, stack)
|
|
stack.clear()
|
|
end
|
|
|
|
return M |