Fix metadata loss and. Improve placement for some corner cases.

This commit is contained in:
Andrey Kozlovskiy 2019-10-19 13:51:05 +03:00
parent b73bbd323e
commit 334f0a5065
1 changed files with 31 additions and 25 deletions

View File

@ -317,6 +317,8 @@ can be one of the source lists.
If destination list position is already occupied with some other item If destination list position is already occupied with some other item
then function tries to move it to the source lists if possible. then function tries to move it to the source lists if possible.
Warning!!! Moving oversized stacks is undefined and can lead to item loss!
Arguments: Arguments:
inv: minetest inventory reference inv: minetest inventory reference
src_lists: names of source lists src_lists: names of source lists
@ -328,44 +330,48 @@ function unified_inventory.move_match(inv, src_lists, dst_list, match_table, amo
local moved_positions = {} local moved_positions = {}
for item, pos_set in pairs(match_table) do for item, pos_set in pairs(match_table) do
local stack_max = ItemStack(item):get_stack_max() local needed = {}
local remained = {}
local stack = ItemStack(item)
local stack_max = stack:get_stack_max()
local bounded_amount = math.min(stack_max, amount) local bounded_amount = math.min(stack_max, amount)
local pos_count = 0;
for _ in pairs(pos_set) do -- Pass 1: Remove stacks needed for craft
pos_count = pos_count + 1 stack:set_count(bounded_amount)
end
local total = ItemStack{
name = item,
count = bounded_amount * pos_count
}
local removed = unified_inventory.remove_item(inv, src_lists, total)
local current = ItemStack(removed)
current:set_count(bounded_amount)
for pos in pairs(pos_set) do for pos in pairs(pos_set) do
needed[pos] = unified_inventory.remove_item(inv, src_lists, stack)
end
-- Pass 2: Remove remainder to free up positions
stack:set_count(stack_max)
for pos in pairs(pos_set) do
remained[pos] = unified_inventory.remove_item(inv, src_lists, stack)
end
-- Pass 3: Move only needed stacks
for pos, current in pairs(needed) do
local occupied = inv:get_stack(dst_list, pos) local occupied = inv:get_stack(dst_list, pos)
inv:set_stack(dst_list, pos, current) inv:set_stack(dst_list, pos, current)
repeat if not occupied:is_empty() then
if not occupied:is_empty() then local leftover = unified_inventory.add_item(inv, src_lists, occupied)
local leftover = unified_inventory.add_item(inv, src_lists, occupied)
if not leftover:is_empty() then if not leftover:is_empty() then
inv:set_stack(dst_list, pos, leftover) inv:set_stack(dst_list, pos, leftover)
break unified_inventory.add_item(inv, src_lists, current)
end
end end
end
removed:take_item(bounded_amount)
until true
moved_positions[pos] = true moved_positions[pos] = true
end end
unified_inventory.add_item(inv, src_lists, removed) -- Pass 4: Re-add remainder stacks
for _, current in pairs(remained) do
unified_inventory.add_item(inv, src_lists, current)
end
end end
unified_inventory.swap_items(inv, dst_list, src_lists, moved_positions) unified_inventory.swap_items(inv, dst_list, src_lists, moved_positions)