From 473570f39803998c220299e19a24024fcbb81c86 Mon Sep 17 00:00:00 2001 From: MayaTheShy Date: Mon, 16 Mar 2026 00:37:32 -0400 Subject: [PATCH] Refactor crafting logic to enable auto-crafting by the turtle and improve item retrieval process --- craftingTurtle.lua | 101 ++++++++++++++++++++++++++++++------------- inventoryManager.lua | 69 ++++++++++++++++------------- 2 files changed, 111 insertions(+), 59 deletions(-) diff --git a/craftingTurtle.lua b/craftingTurtle.lua index 0a55a4d..c66ce80 100644 --- a/craftingTurtle.lua +++ b/craftingTurtle.lua @@ -1,45 +1,88 @@ -- Crafting Turtle Script -- Run this on the crafting turtle (turtle with crafting table). --- Listens for craft commands from the master computer via wired modem. +-- Polls its own crafting grid slots and auto-crafts when items appear. +-- No modem required — works via the wired network inventory access. -local CRAFT_CHANNEL = 4203 -local CRAFT_REPLY_CHANNEL = 4204 +-- Crafting grid slots in a turtle's 4x4 inventory +local CRAFT_SLOTS = {1, 2, 3, 5, 6, 7, 9, 10, 11} --- Find modem (wired or wireless) -local modem = peripheral.find("modem") -if not modem then - print("[ERR] No modem found! Attach a wired modem.") +-- How long to wait after detecting items before crafting, +-- giving the master time to finish placing all ingredients. +local SETTLE_DELAY = 1.0 + +-- Polling interval (seconds) +local POLL_INTERVAL = 0.5 + +print("=================================") +print(" Crafting Turtle (Auto-Craft)") +print("=================================") +print("") + +-- Verify this is a crafting turtle +if not turtle or not turtle.craft then + print("[ERR] No turtle.craft() available!") + print(" This must be a Crafting Turtle.") return end -modem.open(CRAFT_CHANNEL) +print("Polling crafting slots for items...") +print("Ready. Items placed in grid will be auto-crafted.") +print("") -print("=================================") -print(" Crafting Turtle (Listener)") -print("=================================") -print("") -print("Listening on channel " .. CRAFT_CHANNEL) -print("Ready for craft commands from master.") -print("") +local function hasCraftingItems() + for _, slot in ipairs(CRAFT_SLOTS) do + if turtle.getItemCount(slot) > 0 then + return true + end + end + return false +end + +local function describeGrid() + local parts = {} + for _, slot in ipairs(CRAFT_SLOTS) do + local detail = turtle.getItemDetail(slot) + if detail then + table.insert(parts, string.format(" slot %d: %s x%d", slot, detail.name, detail.count)) + end + end + return table.concat(parts, "\n") +end while true do - local event, side, channel, replyChannel, message = os.pullEvent("modem_message") - if channel == CRAFT_CHANNEL and type(message) == "table" and message.type == "craft" then - local count = message.count or 1 - print(string.format("[CRAFT] Received craft request (count=%d)", count)) + if hasCraftingItems() then + -- Wait for the master to finish placing all ingredients + print("[CRAFT] Items detected in grid, waiting " .. SETTLE_DELAY .. "s...") + sleep(SETTLE_DELAY) - local ok, err = turtle.craft(count) + -- Check again — items might have been pulled back (abort) + if hasCraftingItems() then + print("[CRAFT] Grid contents:") + print(describeGrid()) + print("[CRAFT] Attempting craft...") - if ok then - print("[CRAFT] Success!") + local ok, err = turtle.craft() + + if ok then + -- Show what was crafted + local results = {} + for slot = 1, 16 do + local detail = turtle.getItemDetail(slot) + if detail then + table.insert(results, string.format("%s x%d", detail.name, detail.count)) + end + end + print("[CRAFT] Success! Result: " .. table.concat(results, ", ")) + else + print("[CRAFT] Failed: " .. tostring(err)) + end + + -- Wait for master to pull results before polling again + sleep(2) else - print("[CRAFT] Failed: " .. tostring(err)) + print("[CRAFT] Items removed before crafting (aborted by master)") end - - modem.transmit(replyChannel, CRAFT_CHANNEL, { - type = "craft_result", - success = ok, - error = not ok and tostring(err) or nil, - }) end + + sleep(POLL_INTERVAL) end diff --git a/inventoryManager.lua b/inventoryManager.lua index 24c954c..c7b84e5 100644 --- a/inventoryManager.lua +++ b/inventoryManager.lua @@ -1545,45 +1545,54 @@ local function craftItem(recipeIdx) end end - -- 3. Signal turtle to craft - networkModem.transmit(CRAFT_CHANNEL, CRAFT_REPLY_CHANNEL, { type = "craft", count = 1 }) - print(string.format("[CRAFT] Sent craft request: %s", recipe.output)) + -- 3. Wait for turtle to auto-craft + -- The turtle polls its crafting slots and crafts automatically. + -- Give it time: SETTLE_DELAY (1s) + craft time + margin. + print(string.format("[CRAFT] Ingredients placed for %s, waiting for turtle...", recipe.output)) + sleep(3) - -- 4. Wait for reply with timeout - local timer = os.startTimer(5) - local success = false - local errMsg = "Turtle timeout" - while true do - local event = {os.pullEvent()} - if event[1] == "modem_message" and event[3] == CRAFT_REPLY_CHANNEL - and type(event[5]) == "table" and event[5].type == "craft_result" then - os.cancelTimer(timer) - success = event[5].success - errMsg = event[5].error - break - elseif event[1] == "timer" and event[2] == timer then - break + -- 4. Pull all items from turtle back to chests + -- Strategy: first check crafting grid slots. If they're empty, + -- the turtle consumed the ingredients = craft succeeded. + -- Then pull everything remaining (output items or leftover ingredients). + + local ingredientsRemain = false + + -- Check crafting grid slots first + for gridPos = 1, 9 do + if placedItems[GRID_TO_SLOT[gridPos]] then + for _, ch in ipairs(chests) do + local chest = peripheral.wrap(ch) + if chest then + local n = chest.pullItems(craftTurtleName, GRID_TO_SLOT[gridPos]) + if n and n > 0 then + -- Ingredient still there = craft failed for this slot + ingredientsRemain = true + local itemName = placedItems[GRID_TO_SLOT[gridPos]] + adjustCache(itemName, ch, n) + print(string.format("[CRAFT] Ingredient returned: %s x%d from slot %d", itemName, n, GRID_TO_SLOT[gridPos])) + break + end + end + end end end - -- 5. Pull all items from turtle back to chests - -- 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 + local success = not ingredientsRemain + local pulledOutput = 0 + -- Pull everything remaining (output on success, or stray items) 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 - local itemName = resultItems[slot] or recipe.output + -- On success these are crafted output; on failure, leftovers + local itemName = success and recipe.output or (placedItems[slot] or recipe.output) adjustCache(itemName, ch, n) - print(string.format("[CRAFT] Result %s x%d -> %s", itemName, n, ch)) + if success then pulledOutput = pulledOutput + n end + print(string.format("[CRAFT] Pulled %s x%d from slot %d -> %s", itemName, n, slot, ch)) break end end @@ -1596,11 +1605,11 @@ local function craftItem(recipeIdx) if success then local short = recipe.output:gsub("^minecraft:", ""):gsub("_", " ") - print(string.format("[CRAFT] OK: %s x%d", short, recipe.count)) + print(string.format("[CRAFT] OK: %s x%d", short, pulledOutput)) return true else - print(string.format("[CRAFT] Failed: %s", errMsg or "unknown")) - return false, errMsg or "Craft failed" + print("[CRAFT] Failed: ingredients were not consumed by turtle") + return false, "Craft failed" end end