Refactor crafting logic to improve turtle inventory management and enhance error handling

This commit is contained in:
MayaTheShy
2026-03-16 00:17:41 -04:00
parent 50d38b86a2
commit 11c9599863

View File

@@ -1467,14 +1467,18 @@ local function getMissingIngredients(recipe)
end end
--- Execute a craft via the networked turtle --- 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 function craftItem(recipeIdx)
local recipe = CRAFTABLE[recipeIdx] local recipe = CRAFTABLE[recipeIdx]
if not recipe then return false, "Invalid recipe" end if not recipe then return false, "Invalid recipe" end
if not craftTurtleName then return false, "No turtle" end if not craftTurtleName then return false, "No turtle" end
if not networkModem then return false, "No modem" end if not networkModem then return false, "No modem" end
local turtleInv = peripheral.wrap(craftTurtleName) -- Verify the turtle is still on the network
if not turtleInv then return false, "Turtle offline" end if not peripheral.isPresent(craftTurtleName) then
return false, "Turtle offline"
end
activity.crafting = true activity.crafting = true
needsRedraw = true needsRedraw = true
@@ -1482,21 +1486,29 @@ local function craftItem(recipeIdx)
local chests = getChests() local chests = getChests()
-- 1. Clear turtle inventory (pull everything out) -- Helper: pull all 16 turtle slots into chests (chest-side)
local tc = turtleInv.list() local function clearTurtle(knownItems)
if tc then for slot = 1, 16 do
for slot, item in pairs(tc) do
for _, ch in ipairs(chests) do for _, ch in ipairs(chests) do
local n = turtleInv.pushItems(ch, slot) local chest = peripheral.wrap(ch)
if n and n > 0 then if chest then
adjustCache(item.name, ch, n) local n = chest.pullItems(craftTurtleName, slot)
break if n and n > 0 then
if knownItems and knownItems[slot] then
adjustCache(knownItems[slot], ch, n)
end
break
end
end end
end 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 for gridPos = 1, 9 do
local itemName = recipe.grid[gridPos] local itemName = recipe.grid[gridPos]
if itemName then if itemName then
@@ -1511,6 +1523,7 @@ local function craftItem(recipeIdx)
local n = chest.pushItems(craftTurtleName, slot, 1, turtleSlot) local n = chest.pushItems(craftTurtleName, slot, 1, turtleSlot)
if n and n > 0 then if n and n > 0 then
adjustCache(itemName, source.chest, -n) adjustCache(itemName, source.chest, -n)
placedItems[turtleSlot] = itemName
placed = true placed = true
break break
end end
@@ -1521,20 +1534,9 @@ local function craftItem(recipeIdx)
end end
end end
if not placed then if not placed then
-- Cleanup: pull items back from turtle -- Cleanup: pull placed items back using tracked names
print("[CRAFT] Missing ingredient, aborting") print("[CRAFT] Missing ingredient, aborting")
local cleanup = turtleInv.list() clearTurtle(placedItems)
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
activity.crafting = false activity.crafting = false
needsRedraw = true needsRedraw = true
smelterNeedsRedraw = true smelterNeedsRedraw = true
@@ -1565,14 +1567,23 @@ local function craftItem(recipeIdx)
end end
-- 5. Pull all items from turtle back to chests -- 5. Pull all items from turtle back to chests
tc = turtleInv.list() -- On success: slots contain crafted output (recipe.output)
if tc then -- On failure/timeout: slots still have placed ingredients
for s, it in pairs(tc) do local resultItems = success and {} or placedItems
for _, ch in ipairs(chests) do if success then
local n = turtleInv.pushItems(ch, s) -- 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 if n and n > 0 then
adjustCache(it.name, ch, n) local itemName = resultItems[slot] or recipe.output
print(string.format("[CRAFT] Result %s x%d -> %s", it.name, n, ch)) adjustCache(itemName, ch, n)
print(string.format("[CRAFT] Result %s x%d -> %s", itemName, n, ch))
break break
end end
end end
@@ -2540,10 +2551,13 @@ end
-- Order -- Order
------------------------------------------------- -------------------------------------------------
local function orderItem(itemName, amount) local function orderItem(itemName, amount, dropperOverride)
activity.dispensing = true activity.dispensing = true
needsRedraw = 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 local catalogue = cache.catalogue
if not catalogue[itemName] then if not catalogue[itemName] then
@@ -2555,9 +2569,9 @@ local function orderItem(itemName, amount)
return false return false
end end
local dropper = peripheral.wrap(DROPPER_NAME) local dropper = peripheral.wrap(dropperTarget)
if not dropper then if not dropper then
statusMessage = "Dropper offline!" statusMessage = "Dropper offline: " .. dropperTarget
statusColor = colors.red statusColor = colors.red
statusTimer = 5 statusTimer = 5
activity.dispensing = false activity.dispensing = false
@@ -2572,7 +2586,7 @@ local function orderItem(itemName, amount)
for slot, slotItem in pairs(chest.list()) do for slot, slotItem in pairs(chest.list()) do
if slotItem.name == itemName then if slotItem.name == itemName then
local toMove = math.min(remaining, slotItem.count) 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 if moved and moved > 0 then
remaining = remaining - moved remaining = remaining - moved
adjustCache(itemName, entry.chest, -moved) adjustCache(itemName, entry.chest, -moved)
@@ -3121,7 +3135,7 @@ local function main()
if channel == ORDER_CHANNEL and type(message) == "table" then if channel == ORDER_CHANNEL and type(message) == "table" then
if message.type == "order" and message.itemName and message.amount then if message.type == "order" and message.itemName and message.amount then
print(string.format("[NET] Order: %s x%d", message.itemName, message.amount)) 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, { networkModem.transmit(replyChannel, ORDER_CHANNEL, {
type = "order_result", type = "order_result",
success = success, success = success,