** I played around in the code for version 1.2.3 and I'm happy with the outcome, but not sure if it's a proper fix...
I decided to look at the code and found the balance() function in chest.lua.
Items with metadata get moved by stack, so the count of stacks versus count of items is required. Doesn't matter if science packs differ by 40, the stack count is only off by one. Moving "40 science packs" could end up moving 100 because it's the first stack found when balancing. That plus the while loop checks for count > 0, and the count is decremented by only 0 because the swapped stacks replace each other; the value removed from count will always be 0 from the empty stack retrieved from the destination inventory.
Hope this helps for a real fix.
local function move_item(item, count, input_inv, output_inv)
if check_for_basic_item(item) then
-- basic item being transfered
local inserted_count = output_inv.insert{name = item, count = count}
if inserted_count > 0 then
input_inv.remove{name = item, count = inserted_count}
end
else
-- advanced item being transfered, need to preserve tags, durablity, ect
-- not safe to "split" the stack here, may result in some item sloshing
while count > 0 do
local stack = input_inv.find_item_stack(item)
local empty_slot, i = output_inv.find_empty_stack(item)
if not stack or not empty_slot then break end
if output_inv.supports_bar() and output_inv.get_bar() == i then break end
if not stack.swap_stack(empty_slot) then break end
-- Changed stack to empty_slot
count = count - empty_slot.count
end
output_inv.sort_and_merge()
end
end
-- Added function to just add stacks of items
local function move_advanced_item(item, count, input_inv, output_inv)
while count > 0 do
local stack = input_inv.find_item_stack(item)
local empty_slot, i = output_inv.find_empty_stack(item)
if not stack or not empty_slot then break end
if output_inv.supports_bar() and output_inv.get_bar() == i then break end
if not stack.swap_stack(empty_slot) then break end
count = count - 1
end
output_inv.sort_and_merge()
end
local floor = math.floor
local function balance(outside_inv, inside_inv)
outside_inv.sort_and_merge()
inside_inv.sort_and_merge()
local outside_contents = outside_inv.get_contents()
local inside_contents = inside_inv.get_contents()
for item, count in pairs(outside_contents) do
if check_for_basic_item(item) then
local count2 = inside_contents[item] or 0
local diff = count - count2
if diff > 1 then
move_item(item, floor(diff / 2), outside_inv, inside_inv)
elseif diff < -1 then
move_item(item, floor(-diff / 2), inside_inv, outside_inv)
end
else
-- Non-basic items will be balanced by stacks instead
local stack = outside_inv.find_item_stack(item)
local stack_size = stack.prototype.stack_size
local stack_count = floor(count/stack_size)
local stack_count2 = floor((inside_contents[item] or 0)/stack_size)
local diff = stack_count - stack_count2
if diff > 1 then
move_advanced_item(item, floor(diff / 2), outside_inv, inside_inv)
elseif diff < -1 then
move_advanced_item(item, floor(-diff / 2), inside_inv, outside_inv)
end
end
end
for item, count in pairs(inside_contents) do
if check_for_basic_item(item) then
if count > 1 and not outside_contents[item] then
move_item(item, floor(count / 2), inside_inv, outside_inv)
end
else
-- Non-basic items will be balanced by stacks instead
local stack = inside_inv.find_item_stack(item)
local stack_size = stack.prototype.stack_size
local stack_count = floor(count/stack_size)
if stack_count > 1 and not outside_contents[item] then
move_advanced_item(item, floor(stack_count / 2), inside_inv, outside_inv)
end
end
end
end