Refactor crafting logic to improve turtle inventory management and enhance error handling
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user