158 lines
5.7 KiB
Lua

return function(source_module_inventory, target_entity, player, interact_with_player, create_logistic_request)
-- prepare commonly used variables
local target_inventory = target_entity.get_module_inventory()
if not target_inventory then
return
end
local player_inventory = player.get_main_inventory()
-- before start, remove existing logistic requests for modules
local target_requests = target_entity.surface.find_entities_filtered({
area = {
{ target_entity.position.x - 0.01, target_entity.position.y - 0.01 },
{ target_entity.position.x + 0.01, target_entity.position.y + 0.01 }
},
name = "item-request-proxy",
force = player.force
})
for _,request in pairs(target_requests) do
if request.proxy_target == target_entity then
local item_requests = request.item_requests
for name,_ in pairs(item_requests) do
if game.item_prototypes[name].type == "module" then
item_requests[name] = nil
end
end
if next(item_requests) == nil then
request.destroy()
else
request.item_requests = item_requests
end
end
end
-- next, prepare the "diff" for message display, positive number indicates direction from player to target
local diff = {}
-- keep modules from target machine in a variable for now, give them to player (or dump them on the ground) at the end
local modules_to_give = target_inventory.get_contents()
-- and clear target inventory
target_inventory.clear()
-- then, (re)insert modules from previous modules or the player to target machine
local missing = {}
for i=1,math.min(#target_inventory, #source_module_inventory),1 do
local currentItem = source_module_inventory[i];
if currentItem.valid_for_read then -- item present
local name = currentItem.name
local module_taken = false
if (modules_to_give[name] or 0) > 0 then -- first, try to take from previous modules
modules_to_give[name] = modules_to_give[name] - 1
module_taken = true
elseif interact_with_player then -- if that fails, try to take it from the player
local taken = player_inventory.remove({ name = name, count = 1 })
if taken > 0 then
diff[name] = (diff[name] or 0) + 1
module_taken = true
end
end
if module_taken then -- we took the module and can now give it to the target machine
target_inventory[i].set_stack({ name = name, count = 1 })
else -- module is missing: save that info for creating a logistic request later
missing[name] = (missing[name] or 0) + 1
end
end
end
-- next, give remaining items to the player or dump them on the ground
for name,count in pairs(modules_to_give) do
if count > 0 then
local given = 0;
if interact_with_player then
given = player_inventory.insert({ name = name, count = count })
if given > 0 then -- items given to player, save that info to "diff" to display message later
diff[name] = (diff[name] or 0) - given
end
end
if given < count then -- not all items could be given, "dump" them the ground
if (interact_with_player) then
player.print({ "message.kajacx_copy-paste-modules_no-inventory-space", game.item_prototypes[name].localised_name })
end
target_entity.surface.spill_item_stack(
target_entity.position,
{ name = name, count = count - given },
true,
player.force,
false
)
end
end
end
-- process the created "diff" to display "items moved" text and play sound
if interact_with_player then
local message_position = { x = target_entity.position.x, y = target_entity.position.y }
local play_sound = false;
for name,count in pairs(diff) do
if count > 0 then -- moving items from the player to a machine
target_entity.surface.create_entity({
name = "flying-text",
position = message_position,
text = {
"message.kajacx_copy-paste-modules_items-removed",
count,
game.item_prototypes[name].localised_name,
player_inventory.get_item_count(name)
}
})
message_position.y = message_position.y - 0.5
play_sound = true;
elseif count < 0 then -- moving items from a machine to the player
target_entity.surface.create_entity({
name = "flying-text",
position = message_position,
text = {
"message.kajacx_copy-paste-modules_items-added",
-count,
game.item_prototypes[name].localised_name,
player_inventory.get_item_count(name)
}
})
message_position.y = message_position.y - 0.5
play_sound = true;
end
end
if play_sound then
player.play_sound({ path = "utility/inventory_move" })
end
end
-- finally, create logistic request in the target entity
if next(missing) ~= nil and create_logistic_request then
local free_slots = target_inventory.count_empty_stacks()
if free_slots > 0 then
local request = {} -- fill from missing to request as long as there are free slots avaliable
for name,count in pairs(missing) do
if count <= free_slots then
request[name] = count
free_slots = free_slots - count
else
request[name] = free_slots
break
end
end
target_entity.surface.create_entity({
name = "item-request-proxy",
position = target_entity.position,
force = player.force,
target = target_entity,
modules = request,
raise_built = true
})
-- TODO: sort the items once the request is completed?
end
end
end