diff --git a/autocrafter.lua b/autocrafter.lua index 65db8bc..d52d4f0 100644 --- a/autocrafter.lua +++ b/autocrafter.lua @@ -35,28 +35,62 @@ end local function autocraft(inventory, craft) if not craft then return false end - local output_item = craft.output.item - -- check if we have enough room in dst - if not inventory:room_for_item("dst", output_item) then return false end + local output_item = craft.output.item + -- check if we have enough room in dst for output item(s) + -- we'll check replacements later + if not inventory:room_for_item("dst", output_item) then return false end + local consumption = craft.consumption local inv_index = count_index(inventory:get_list("src")) -- check if we have enough material available for itemname, number in pairs(consumption) do if (not inv_index[itemname]) or inv_index[itemname] < number then return false end end - -- consume material + + -- since there is no inv:room_for_items() method, we use history/undo system + -- see: https://github.com/mt-mods/pipeworks/issues/61 + -- keep track of stacks we add to dst inventory + local history = { output_item } + -- add the result into the dst inventory + inventory:add_item("dst", output_item) + + -- add any "replacements" as well and keep track of what didn't fit + local leftover, replacement, undo, diff + for i = 1, 9 do + replacement = craft.decremented_input.items[i] + if not replacement:is_empty() then + leftover = inventory:add_item("dst", replacement) + if not leftover:is_empty() then + -- hold up, there isn't room, we need to undo + undo = true + -- adjust count (mostly is just 1) so diff will mostly be 0 + diff = replacement:get_count() - leftover:get_count() + -- make a copy with adjusted count + replacement = ItemStack(replacement) + replacement:set_count(diff) + end + -- add to history what had fit + table.insert(history, replacement) + -- if not all fit, let's not make it worse + if undo then break end + end + end + + if undo then + -- we need to remove what we put in dst + for _, stack in ipairs(history) do + inventory:remove_item("dst", stack) + end + return false + end + + -- consume materials for itemname, number in pairs(consumption) do for _ = 1, number do -- We have to do that since remove_item does not work if count > stack_max inventory:remove_item("src", ItemStack(itemname)) end end - - -- craft the result into the dst inventory and add any "replacements" as well - inventory:add_item("dst", output_item) - for i = 1, 9 do - inventory:add_item("dst", craft.decremented_input.items[i]) - end return true end