print("AC autocrafter :D") local function agc(name) return assert(components:getFirst(name), "failed to get component "..name) end local computer = agc("computer") local fs = require("filesystem") local kernel = require("kernel") local crafter = agc("digitalCrafter") local interface = agc("adapter") local recipesToAutocraft = {} local function addRecipeDirect(recipe) assert(type(recipe) == "table", "recipe was not table but "..type(recipe)) assert(recipe.ingredients, "key ingredients was not contained in recipe") assert(recipe.result, "key result was not contained in recipe") assert(recipe.resultCount, "key resultCount was not contained in recipe") table.insert(recipesToAutocraft, recipe) end local function addSingleRecipeOfItem(name) -- ensures that there is exactly one recipe to use local recipesForItem = crafter:searchRecipesWithResult(name) assert(#recipesForItem == 1, "somehow there was not exactly one recipe for "..tostring(name)) local recipe = recipesForItem[1] addRecipeDirect(recipe) end local function addSingleRecipeForAllCsv(csv, prefixOrNil) for match in csv:gsub("%s",""):gmatch("[^,]+") do addSingleRecipeOfItem((prefixOrNil or "")..match) end end local function addSingleRecipeThatUsesItem(itemToConsume) local recipesForItem = crafter:searchRecipesWithIngredient(itemToConsume) assert(#recipesForItem == 1, "somehow there was not exactly one recipe that uses "..tostring(itemToConsume)) local recipe = recipesForItem[1] addRecipeDirect(recipe) end addSingleRecipeThatUsesItem("mysticalagriculture:sulfur_essence") addSingleRecipeThatUsesItem("mysticalagriculture:draconium_essence") -- to be prefixed with nuclearcraft:fuel_ local possibleFuelsRaw = --"leu-235,len-236,hen-236,hecf-249,hecm-245,mix-241,mix-239,lep-241,hep-241,heu-233,lecm-245,leu-233,lecf-249,hecm-243,lep-239,hep-239,lecm-243,heu-235,lea-242,tbu,hea_242,lecf_251,heb_248,leb_248" ([[ uranium_leu_235,neptunium_len_236,neptunium_hen_236,californium_hecf_249,curium_hecm_245,mixed_mix_241, mixed_mix_239,plutonium_lep_241,plutonium_hep_241,uranium_heu_233,curium_lecm_245,uranium_leu_233,californium_lecf_249,curium_hecm_243,plutonium_lep_239, plutonium_hep_239,curium_lecm_243,uranium_heu_235,americium_lea_242,thorium_tbu,americium_hea_242,californium_lecf_251,berkelium_heb_248, berkelium_leb_248,curium_hecm_247,californium_hecf_251,curium_lecm_247 ]]) addSingleRecipeForAllCsv(possibleFuelsRaw, "nuclearcraft:fuel_") addSingleRecipeForAllCsv([[osmium,uranium]], "mekanism:block_raw_") addSingleRecipeForAllCsv([[iron_block,copper_block,gold_block]], "minecraft:raw_") addSingleRecipeForAllCsv([[zinc_block]], "create:raw_") addSingleRecipeForAllCsv([[aluminum_block,platinum_block,iridium_block]], "alltheores:raw_") addSingleRecipeForAllCsv([[tin_block,lead_block,silver_block,nickel_block]], "thermal:raw_") print(("%s Recipes loaded."):format(#recipesToAutocraft)) local function safeCraft(...) while true do local cooldown = crafter.cooldownRemaining if cooldown <= 0 then break end sleep(cooldown) end return crafter:craft(...) end -- try to craft the given recipe as often as possible; greedy not optimal. Might need to be called multiple times in order to consume all valid items in case there are multiple options local function tryCraftRecipeAsOftenAsPossible(recipe) local ingredientsStacked = {} -- itemName: count_needed_per_craft local stockOfIngredientForCraftCountSelection = {} -- itemName: count_in_me_system local stockOfIngredientForItemSelection = {} local resultItemName = recipe.result local actualIngredients = {} -- pick concrete items that we have in stock for this recipe for i = 1, 9 do local currentSlotOptions = recipe.ingredients[i] if currentSlotOptions == nil then actualIngredients[i] = nil else local anyInStock = false for _, slotOption in ipairs(currentSlotOptions) do if stockOfIngredientForItemSelection[slotOption] == nil then local x = interface:getCount(slotOption) stockOfIngredientForItemSelection[slotOption] = x stockOfIngredientForCraftCountSelection[slotOption] = x end local selectionCountOfCurrItem = stockOfIngredientForItemSelection[slotOption] assert(selectionCountOfCurrItem >= 0, "somehow countOfCurrItem was not >= 0?") if selectionCountOfCurrItem > 0 then -- select this item and reduce the count stockOfIngredientForItemSelection[slotOption] = selectionCountOfCurrItem - 1 anyInStock = true ingredientsStacked[slotOption] = (ingredientsStacked[slotOption] or 0) + 1 actualIngredients[i] = slotOption break end end if not anyInStock then print(("We dont have enough to craft %s for slot %d."):format(resultItemName, i)) return false end end end -- at this point we found an item for every slot; so figure out how many recipes we can craft local maxStackSize = 64 -- fuels always stack 64, same for ingredients, so in principle we could craft 64 fuel at once local recipeCraftCount = 64 -- how many recipes to craft for ingredient, count in pairs(ingredientsStacked) do local maxCraftForCurrIngredient = math.floor(stockOfIngredientForCraftCountSelection[ingredient]/count) -- how often we could craft with this current ingredient recipeCraftCount = math.min(recipeCraftCount, maxCraftForCurrIngredient) end recipeCraftCount = math.min(recipeCraftCount, math.floor(maxStackSize/recipe.resultCount)) if recipeCraftCount == 0 then error(("We somehow dont have enough to craft %s. Is our math wrong?"):format(resultItemName)) else print(("Time to craft %dx %s."):format(recipeCraftCount, resultItemName)) --crafter:dumpInventoryUp() for itemName, count in pairs(ingredientsStacked) do local remainingCount = recipeCraftCount * count while remainingCount > 0 do local extracted = interface:extract(itemName, 1, remainingCount) assert(extracted > 0, "somehow we ran out of an item during exporting???") remainingCount = remainingCount - extracted end end safeCraft(actualIngredients, recipe.result, recipeCraftCount, false) return true end end local skipSleep = true while true do if not skipSleep then print("nothing to craft, waiting 30 seconds"); sleep(30) end print("New iteration started.") skipSleep = false for _, recipe in ipairs(recipesToAutocraft) do local maxCraft = (recipe.result:find("fuel") and 1 or 10) -- craft 10 stacks at once to speed things up, unless this is a fuel recipe for _ = 1, maxCraft do local success = tryCraftRecipeAsOftenAsPossible(recipe) if success then skipSleep = true else break end end end end