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
--- 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,