From 1606d60a062f85021da8fedab8c388e05738f476 Mon Sep 17 00:00:00 2001 From: MayaTheShy Date: Wed, 25 Mar 2026 18:11:23 -0400 Subject: [PATCH] feat: add new crafting recipes for cobblestone and stone variants; enhance auto-crafting logic for excess items --- data/craftable.lua | 108 +++++++++++++++++++++++++++++++++++++++++ inventoryManager.lua | 6 +-- lib/recipeBook.lua | 18 +++++++ manager/config.lua | 6 ++- manager/operations.lua | 74 ++++++++++++++++++++++++++-- 5 files changed, 203 insertions(+), 9 deletions(-) diff --git a/data/craftable.lua b/data/craftable.lua index 79d187d..6a3401f 100644 --- a/data/craftable.lua +++ b/data/craftable.lua @@ -123,6 +123,114 @@ return { "minecraft:cobblestone", "minecraft:cobblestone", "minecraft:cobblestone", }, }, + { + output = "minecraft:cobblestone_slab", + count = 6, + grid = { + "minecraft:cobblestone", "minecraft:cobblestone", "minecraft:cobblestone", + nil, nil, nil, + nil, nil, nil, + }, + }, + { + output = "minecraft:cobblestone_stairs", + count = 4, + grid = { + "minecraft:cobblestone", nil, nil, + "minecraft:cobblestone", "minecraft:cobblestone", nil, + "minecraft:cobblestone", "minecraft:cobblestone", "minecraft:cobblestone", + }, + }, + { + output = "minecraft:cobblestone_wall", + count = 6, + grid = { + "minecraft:cobblestone", "minecraft:cobblestone", "minecraft:cobblestone", + "minecraft:cobblestone", "minecraft:cobblestone", "minecraft:cobblestone", + nil, nil, nil, + }, + }, + { + output = "minecraft:stone_bricks", + count = 4, + grid = { + "minecraft:stone", "minecraft:stone", nil, + "minecraft:stone", "minecraft:stone", nil, + nil, nil, nil, + }, + }, + { + output = "minecraft:stone_slab", + count = 6, + grid = { + "minecraft:stone", "minecraft:stone", "minecraft:stone", + nil, nil, nil, + nil, nil, nil, + }, + }, + { + output = "minecraft:stone_stairs", + count = 4, + grid = { + "minecraft:stone", nil, nil, + "minecraft:stone", "minecraft:stone", nil, + "minecraft:stone", "minecraft:stone", "minecraft:stone", + }, + }, + { + output = "minecraft:smooth_stone_slab", + count = 6, + grid = { + "minecraft:smooth_stone", "minecraft:smooth_stone", "minecraft:smooth_stone", + nil, nil, nil, + nil, nil, nil, + }, + }, + { + output = "minecraft:polished_andesite", + count = 4, + grid = { + "minecraft:andesite", "minecraft:andesite", nil, + "minecraft:andesite", "minecraft:andesite", nil, + nil, nil, nil, + }, + }, + { + output = "minecraft:polished_diorite", + count = 4, + grid = { + "minecraft:diorite", "minecraft:diorite", nil, + "minecraft:diorite", "minecraft:diorite", nil, + nil, nil, nil, + }, + }, + { + output = "minecraft:polished_granite", + count = 4, + grid = { + "minecraft:granite", "minecraft:granite", nil, + "minecraft:granite", "minecraft:granite", nil, + nil, nil, nil, + }, + }, + { + output = "minecraft:polished_deepslate", + count = 4, + grid = { + "minecraft:cobbled_deepslate", "minecraft:cobbled_deepslate", nil, + "minecraft:cobbled_deepslate", "minecraft:cobbled_deepslate", nil, + nil, nil, nil, + }, + }, + { + output = "minecraft:polished_tuff", + count = 4, + grid = { + "minecraft:tuff", "minecraft:tuff", nil, + "minecraft:tuff", "minecraft:tuff", nil, + nil, nil, nil, + }, + }, { output = "minecraft:ladder", count = 3, diff --git a/inventoryManager.lua b/inventoryManager.lua index 95180e2..7b76854 100644 --- a/inventoryManager.lua +++ b/inventoryManager.lua @@ -445,11 +445,9 @@ local function main() -- Task 5c: Auto-craft excess items into target products function() - if #cfg.AUTO_CRAFT_RULES == 0 then - while true do sleep(3600) end - end sleep(12) -- let initial scan + discard settle first - log.info("AUTOCRAFT", "Auto-craft active with %d rule(s)", #cfg.AUTO_CRAFT_RULES) + log.info("AUTOCRAFT", "Auto-craft active (%d explicit rule(s), smart=%s)", + #cfg.AUTO_CRAFT_RULES, tostring(cfg.AUTO_CRAFT_FROM_EXCESS)) while true do if ctx.craftTurtleName then activity.autocrafting = true diff --git a/lib/recipeBook.lua b/lib/recipeBook.lua index 97eee57..af609c5 100644 --- a/lib/recipeBook.lua +++ b/lib/recipeBook.lua @@ -245,4 +245,22 @@ function recipeBook.count() return cc, sc end +--- Find all crafting recipes that use a given item as an ingredient. +-- @param ingredientName string — the input item to search for +-- @return array of recipe tables +function recipeBook.findRecipesUsing(ingredientName) + local results = {} + for _, recipe in pairs(recipes.crafting) do + if recipe.grid then + for _, item in ipairs(recipe.grid) do + if item == ingredientName then + table.insert(results, recipe) + break + end + end + end + end + return results +end + return recipeBook diff --git a/manager/config.lua b/manager/config.lua index 7f66406..43ea386 100644 --- a/manager/config.lua +++ b/manager/config.lua @@ -65,7 +65,9 @@ C.TRASH_DROPPERS = { -- droppers facing lava/void for destroying C.DISCARD_INTERVAL = 5 -- seconds between discard checks -- Auto-craft (overridable via config file) -C.AUTO_CRAFT_INTERVAL = 10 -- seconds between auto-craft checks +C.AUTO_CRAFT_INTERVAL = 10 -- seconds between auto-craft checks +C.AUTO_CRAFT_OUTPUT_CAP = 512 -- max items of any output before smart-craft stops crafting it +C.AUTO_CRAFT_FROM_EXCESS = true -- auto-discover recipes for over-stocked items -- Peripheral C.PERIPHERAL_CACHE_TTL = 5 @@ -130,6 +132,8 @@ function C.loadConfig() if cfg.trashDroppers then C.TRASH_DROPPERS = cfg.trashDroppers end if cfg.discardInterval then C.DISCARD_INTERVAL = cfg.discardInterval end if cfg.autoCraftInterval then C.AUTO_CRAFT_INTERVAL = cfg.autoCraftInterval end + if cfg.autoCraftOutputCap then C.AUTO_CRAFT_OUTPUT_CAP = cfg.autoCraftOutputCap end + if cfg.autoCraftFromExcess ~= nil then C.AUTO_CRAFT_FROM_EXCESS = cfg.autoCraftFromExcess end if cfg.stockLimits then for item, limit in pairs(cfg.stockLimits) do C.STOCK_LIMITS[item] = limit -- merge / override per-item diff --git a/manager/operations.lua b/manager/operations.lua index cd2bb5f..51c18d5 100644 --- a/manager/operations.lua +++ b/manager/operations.lua @@ -856,13 +856,13 @@ end ------------------------------------------------- function O.autoCraft() - if #cfg.AUTO_CRAFT_RULES == 0 then return false end if not ctx.craftEngine then return false end if not ctx.craftTurtleName then return false end local catalogue = cache.catalogue local didWork = false + -- Phase 1: Explicit rules from auto_craft.lua for _, rule in ipairs(cfg.AUTO_CRAFT_RULES) do local inputName = rule.input local reserve = rule.reserve or 0 @@ -876,15 +876,12 @@ function O.autoCraft() local excess = totalInStorage - reserve if excess > 0 then - -- Figure out how many input items per craft batch local recipe = cfg.recipeBook.getCraftingRecipe(outputName) if recipe then local ingredients = cfg.recipeBook.getIngredients(recipe) local inputPerCraft = ingredients[inputName] or 0 if inputPerCraft > 0 then - -- How many batches can we do with the excess? local batches = math.floor(excess / inputPerCraft) - -- Limit to a reasonable amount per cycle to avoid blocking batches = math.min(batches, 64) if batches > 0 then local craftCount = batches * recipe.count @@ -906,6 +903,75 @@ function O.autoCraft() end end + -- Phase 2: Smart excess-to-craft — auto-discover recipes for over-stocked items + if cfg.AUTO_CRAFT_FROM_EXCESS then + -- Track outputs we've already handled via explicit rules to avoid duplicates + local handledOutputs = {} + for _, rule in ipairs(cfg.AUTO_CRAFT_RULES) do + handledOutputs[rule.output] = true + end + + for itemName, maxCount in pairs(cfg.STOCK_LIMITS) do + if catalogue[itemName] then + local totalInStorage = 0 + for _, src in ipairs(catalogue[itemName]) do + totalInStorage = totalInStorage + src.total + end + + local excess = totalInStorage - maxCount + if excess > 0 then + -- Find all crafting recipes that use this item + local usingRecipes = cfg.recipeBook.findRecipesUsing(itemName) + for _, recipe in ipairs(usingRecipes) do + if not handledOutputs[recipe.output] then + -- Check how much of the output we already have + local outputTotal = O.getItemTotal(recipe.output) + if outputTotal < cfg.AUTO_CRAFT_OUTPUT_CAP then + local ingredients = cfg.recipeBook.getIngredients(recipe) + local inputPerCraft = ingredients[itemName] or 0 + if inputPerCraft > 0 then + -- Only craft up to the output cap + local outputRoom = cfg.AUTO_CRAFT_OUTPUT_CAP - outputTotal + local maxBatches = math.floor(excess / inputPerCraft) + local batchesByRoom = math.ceil(outputRoom / recipe.count) + local batches = math.min(maxBatches, batchesByRoom, 64) + if batches > 0 then + -- Check all other ingredients are available + local canCraft = true + for ingr, needed in pairs(ingredients) do + if ingr ~= itemName then + local have = O.getItemTotal(ingr) + if have < needed * batches then + canCraft = false + break + end + end + end + if canCraft then + local craftCount = batches * recipe.count + log.info("AUTOCRAFT", "Smart: %s over limit, crafting %d x %s", + itemName, craftCount, recipe.output) + local ok, err = O.recursiveCraft(recipe.output, craftCount) + if ok then + didWork = true + handledOutputs[recipe.output] = true + log.info("AUTOCRAFT", "Smart-crafted %s x%d", recipe.output, craftCount) + -- Recalculate excess after crafting + break + else + log.warn("AUTOCRAFT", "Smart craft failed %s: %s", recipe.output, tostring(err)) + end + end + end + end + end + end + end + end + end + end + end + return didWork end