Files
AcScripts/genericAutocraft.lua
T

157 lines
7.1 KiB
Lua

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