174 lines
5.4 KiB
Lua
174 lines
5.4 KiB
Lua
local fmath = require("__flib__.math")
|
|
|
|
--- @alias chest_merged_event { player_index: number, surface: LuaSurface, split_chests: LuaEntity[], merged_chest: LuaEntity }
|
|
|
|
--- @param entity LuaEntity
|
|
--- @return integer
|
|
local function non_blank_inventory_slots_count(entity)
|
|
local count = 0
|
|
local inventory = entity.get_inventory(defines.inventory.chest)
|
|
if inventory then
|
|
for i = 1, #inventory do
|
|
if inventory[i].valid_for_read then
|
|
count = count + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
return count
|
|
end
|
|
|
|
--- @param from_entities LuaEntity[]
|
|
--- @param to_entity_name string
|
|
--- @param to_entity_count integer
|
|
--- @return boolean
|
|
function MergingChests.can_move_inventories(from_entities, to_entity_name, to_entity_count)
|
|
local from_item_count = 0
|
|
for _, from_entity in ipairs(from_entities) do
|
|
from_item_count = from_item_count + non_blank_inventory_slots_count(from_entity)
|
|
end
|
|
|
|
local to_inventory_size = game.entity_prototypes[to_entity_name].get_inventory_size(defines.inventory.chest) or 0
|
|
|
|
local is_merged_chest, _, _ = MergingChests.get_merged_chest_info(to_entity_name)
|
|
|
|
return from_item_count <= (is_merged_chest and MergingChests.get_inventory_size(to_inventory_size, to_entity_count, to_entity_name) or to_inventory_size * to_entity_count)
|
|
end
|
|
|
|
--- @param from_entities LuaEntity[]
|
|
--- @param to_entities LuaEntity[]
|
|
function MergingChests.move_inventories(from_entities, to_entities)
|
|
local to_entity_index = 1
|
|
local to_inventory_index = 1
|
|
|
|
for _, from_entity in ipairs(from_entities) do
|
|
local from_inventory = from_entity.get_inventory(defines.inventory.chest)
|
|
if from_inventory then
|
|
for i = 1, #from_inventory do
|
|
local item = from_inventory[i]
|
|
if item.valid_for_read then
|
|
local to_inventory = to_entities[to_entity_index].get_inventory(defines.inventory.chest)
|
|
if to_inventory then
|
|
to_inventory[to_inventory_index].set_stack(item)
|
|
to_inventory_index = to_inventory_index + 1
|
|
|
|
if to_inventory_index > #to_inventory then
|
|
to_entity_index = to_entity_index + 1
|
|
to_inventory_index = 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--- @param from_entities LuaEntity[]
|
|
--- @param to_entities LuaEntity[]
|
|
function MergingChests.move_inventory_bar(from_entities, to_entities)
|
|
local bar_count = 0
|
|
for _, entity in ipairs(from_entities) do
|
|
local inventory = entity.get_inventory(defines.inventory.chest)
|
|
if inventory and inventory.supports_bar() then
|
|
bar_count = bar_count + inventory.get_bar() - 1
|
|
end
|
|
end
|
|
|
|
local to_entities_count = table_size(to_entities)
|
|
for _, entity in ipairs(to_entities) do
|
|
local inventory = entity.get_inventory(defines.inventory.chest)
|
|
if inventory and inventory.supports_bar() then
|
|
local bar = fmath.round(bar_count / to_entities_count)
|
|
inventory.set_bar(bar + 1)
|
|
bar_count = bar_count - bar
|
|
to_entities_count = to_entities_count - 1
|
|
end
|
|
end
|
|
end
|
|
|
|
--- @param from_entities LuaEntity[]
|
|
--- @param to_entities LuaEntity[]
|
|
function MergingChests.reconnect_circuits(from_entities, to_entities)
|
|
local from_entities_set = { }
|
|
for _, from_entity in ipairs(from_entities) do
|
|
from_entities_set[from_entity] = from_entity
|
|
end
|
|
|
|
local connections = { }
|
|
local red = false
|
|
local green = false
|
|
for _, from_entity in ipairs(from_entities) do
|
|
for _, connection in ipairs(from_entity.circuit_connection_definitions) do
|
|
if not from_entities_set[connection.target_entity] then
|
|
table.insert(connections, connection)
|
|
|
|
red = red or connection.wire == defines.wire_type.red
|
|
green = green or connection.wire == defines.wire_type.green
|
|
end
|
|
end
|
|
end
|
|
|
|
if #connections > 0 then
|
|
-- connect all "to_entities" entities together
|
|
local grid = MergingChests.entities_to_grid(to_entities)
|
|
for x = grid.min_x, grid.max_x do
|
|
for y = grid.min_y, grid.max_y do
|
|
if red then
|
|
if x + 1 <= grid.max_x then
|
|
grid[x][y].connect_neighbour{wire = defines.wire_type.red, target_entity = grid[x + 1][y]}
|
|
end
|
|
if y + 1 <= grid.max_y then
|
|
grid[x][y].connect_neighbour{wire = defines.wire_type.red, target_entity = grid[x][y + 1]}
|
|
end
|
|
end
|
|
|
|
if green then
|
|
if x + 1 <= grid.max_x then
|
|
grid[x][y].connect_neighbour{wire = defines.wire_type.green, target_entity = grid[x + 1][y]}
|
|
end
|
|
if y + 1 <= grid.max_y then
|
|
grid[x][y].connect_neighbour{wire = defines.wire_type.green, target_entity = grid[x][y + 1]}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
-- connect to all outside entities
|
|
for _, connection in ipairs(connections) do
|
|
local closest_entity = nil
|
|
local min = nil
|
|
|
|
for _, to_entity in ipairs(to_entities) do
|
|
local diffX = to_entity.position.x - connection.target_entity.position.x
|
|
local diffY = to_entity.position.y - connection.target_entity.position.y
|
|
|
|
if not min or (diffX * diffX + diffY * diffY < min) then
|
|
min = diffX * diffX + diffY * diffY
|
|
closest_entity = to_entity
|
|
end
|
|
end
|
|
|
|
if closest_entity then
|
|
closest_entity.connect_neighbour(connection)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
MergingChests.on_chest_merged_event_name = script.generate_event_name()
|
|
MergingChests.on_chest_split_event_name = script.generate_event_name()
|
|
|
|
local function get_chest_merged_event_name()
|
|
return MergingChests.on_chest_merged_event_name
|
|
end
|
|
|
|
local function get_chest_split_event_name()
|
|
return MergingChests.on_chest_split_event_name
|
|
end
|
|
|
|
remote.add_interface('MergingChests', {
|
|
get_chest_merged_event_name = get_chest_merged_event_name,
|
|
get_chest_split_event_name = get_chest_split_event_name
|
|
})
|