From 11c959986341474dd0ef829aed2fee1f2edba821 Mon Sep 17 00:00:00 2001 From: MayaTheShy Date: Mon, 16 Mar 2026 00:17:41 -0400 Subject: [PATCH] Refactor crafting logic to improve turtle inventory management and enhance error handling --- inventoryManager.lua | 86 +++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/inventoryManager.lua b/inventoryManager.lua index 0f763c7..f4051cf 100644 --- a/inventoryManager.lua +++ b/inventoryManager.lua @@ -1467,14 +1467,18 @@ local function getMissingIngredients(recipe) end --- Execute a craft via the networked turtle +-- Uses chest-side pullItems/pushItems to move items to/from the turtle, +-- since remote turtles may not expose the inventory API (list/pushItems). local function craftItem(recipeIdx) local recipe = CRAFTABLE[recipeIdx] if not recipe then return false, "Invalid recipe" end if not craftTurtleName then return false, "No turtle" end if not networkModem then return false, "No modem" end - local turtleInv = peripheral.wrap(craftTurtleName) - if not turtleInv then return false, "Turtle offline" end + -- Verify the turtle is still on the network + if not peripheral.isPresent(craftTurtleName) then + return false, "Turtle offline" + end activity.crafting = true needsRedraw = true @@ -1482,21 +1486,29 @@ local function craftItem(recipeIdx) local chests = getChests() - -- 1. Clear turtle inventory (pull everything out) - local tc = turtleInv.list() - if tc then - for slot, item in pairs(tc) do + -- Helper: pull all 16 turtle slots into chests (chest-side) + local function clearTurtle(knownItems) + for slot = 1, 16 do for _, ch in ipairs(chests) do - local n = turtleInv.pushItems(ch, slot) - if n and n > 0 then - adjustCache(item.name, ch, n) - break + local chest = peripheral.wrap(ch) + if chest then + local n = chest.pullItems(craftTurtleName, slot) + if n and n > 0 then + if knownItems and knownItems[slot] then + adjustCache(knownItems[slot], ch, n) + end + break + end end end end end - -- 2. Push ingredients into correct grid slots + -- 1. Clear turtle inventory (safety – turtle should be empty) + clearTurtle(nil) + + -- 2. Push ingredients into correct grid slots, track what we placed + local placedItems = {} -- turtleSlot -> itemName for gridPos = 1, 9 do local itemName = recipe.grid[gridPos] if itemName then @@ -1511,6 +1523,7 @@ local function craftItem(recipeIdx) local n = chest.pushItems(craftTurtleName, slot, 1, turtleSlot) if n and n > 0 then adjustCache(itemName, source.chest, -n) + placedItems[turtleSlot] = itemName placed = true break end @@ -1521,20 +1534,9 @@ local function craftItem(recipeIdx) end end if not placed then - -- Cleanup: pull items back from turtle + -- Cleanup: pull placed items back using tracked names print("[CRAFT] Missing ingredient, aborting") - local cleanup = turtleInv.list() - if cleanup then - for s, it in pairs(cleanup) do - for _, ch in ipairs(chests) do - local n = turtleInv.pushItems(ch, s) - if n and n > 0 then - adjustCache(it.name, ch, n) - break - end - end - end - end + clearTurtle(placedItems) activity.crafting = false needsRedraw = true smelterNeedsRedraw = true @@ -1565,14 +1567,23 @@ local function craftItem(recipeIdx) end -- 5. Pull all items from turtle back to chests - tc = turtleInv.list() - if tc then - for s, it in pairs(tc) do - for _, ch in ipairs(chests) do - local n = turtleInv.pushItems(ch, s) + -- On success: slots contain crafted output (recipe.output) + -- On failure/timeout: slots still have placed ingredients + local resultItems = success and {} or placedItems + if success then + -- After a successful craft, only the output item remains + for slot = 1, 16 do resultItems[slot] = recipe.output end + end + + for slot = 1, 16 do + for _, ch in ipairs(chests) do + local chest = peripheral.wrap(ch) + if chest then + local n = chest.pullItems(craftTurtleName, slot) if n and n > 0 then - adjustCache(it.name, ch, n) - print(string.format("[CRAFT] Result %s x%d -> %s", it.name, n, ch)) + local itemName = resultItems[slot] or recipe.output + adjustCache(itemName, ch, n) + print(string.format("[CRAFT] Result %s x%d -> %s", itemName, n, ch)) break end end @@ -2540,10 +2551,13 @@ end -- Order ------------------------------------------------- -local function orderItem(itemName, amount) +local function orderItem(itemName, amount, dropperOverride) activity.dispensing = true needsRedraw = true + -- Use client-specified dropper if provided, otherwise master's default + local dropperTarget = (dropperOverride and dropperOverride ~= "") and dropperOverride or DROPPER_NAME + local catalogue = cache.catalogue if not catalogue[itemName] then @@ -2555,9 +2569,9 @@ local function orderItem(itemName, amount) return false end - local dropper = peripheral.wrap(DROPPER_NAME) + local dropper = peripheral.wrap(dropperTarget) if not dropper then - statusMessage = "Dropper offline!" + statusMessage = "Dropper offline: " .. dropperTarget statusColor = colors.red statusTimer = 5 activity.dispensing = false @@ -2572,7 +2586,7 @@ local function orderItem(itemName, amount) for slot, slotItem in pairs(chest.list()) do if slotItem.name == itemName then local toMove = math.min(remaining, slotItem.count) - local moved = chest.pushItems(DROPPER_NAME, slot, toMove) + local moved = chest.pushItems(dropperTarget, slot, toMove) if moved and moved > 0 then remaining = remaining - moved adjustCache(itemName, entry.chest, -moved) @@ -3121,7 +3135,7 @@ local function main() if channel == ORDER_CHANNEL and type(message) == "table" then if message.type == "order" and message.itemName and message.amount then print(string.format("[NET] Order: %s x%d", message.itemName, message.amount)) - local success = orderItem(message.itemName, message.amount) + local success = orderItem(message.itemName, message.amount, message.dropperName) networkModem.transmit(replyChannel, ORDER_CHANNEL, { type = "order_result", success = success,