toastonrye

[CC]: Applied Energistics 2 Autocrafter

Jul 29th, 2022
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2. Steps:
  3. 1. Build a Computer and download this script onto your computer (pastebin get)
  4. 2. Create a file named "recipes" (without .lua - on my version i had to use "rename recipes.lua recipes")
  5. 3. Build a ME Bridge (Mod: Advanced Peripherals) and connect it to your computer
  6. 4. Build a Vanilla Minecraft Chest! and connect it to your computer
  7. 5. Start the script
  8. 6. Insert any (ME System) craftable item into the chest, like 10 Pistons
  9. 7. Wait for the recipe beeing registered (Registered recipe: 10x minecraft:piston)
  10. 8. You can remove the 10 pistons from the chest
  11. 9. If you want to edit the 10, either close the script and edit the recipes file OR just insert 20 pistons into the chest and wait for the computer to edit the recipe
  12.  
  13. Now the computer will always make sure you have 10 pistons in your me system
  14.  
  15. ]]
  16. print("Loading autocrafter...")
  17.  
  18. local bridge = peripheral.find("meBridge")
  19. local inventory = peripheral.find("minecraft:chest")
  20.  
  21. local maxTaskCount = 4
  22. local maxCoWorker = 1
  23.  
  24. local recipeList = {}
  25. local craftingQueue = {}
  26.  
  27. local function StringSeperate(str, seperator)
  28. local words = {}
  29. local word = ""
  30.  
  31.     if(string.sub(str, str:len(), str:len())~=seperator)then
  32.         str = str..""..seperator        
  33.     end
  34.     for x=1,str:len() do
  35.         local s = string.sub(str,x,x)
  36.         if(s==seperator)then
  37.             table.insert(words, word)
  38.             word = ""
  39.         else
  40.             word = word..s
  41.         end
  42.     end
  43.     return words
  44. end
  45.  
  46. local f = io.open("recipes", ab)
  47.  
  48.     for line in io.lines("recipes")do
  49.         local tab = StringSeperate(line, "|")
  50.         if(tab[1]~=nil)and(tab[2]~=nil)and(tab[3]~=nil)and(tab[4]~=nil)and(tab[5]~=nil)then
  51.             print("Registered recipe: "..tab[3].."x "..tab[1]..":"..tab[2])
  52.             os.sleep(0.2)
  53.             local recipe = {name=tab[1],damage=tonumber(tab[2]),minAmount=tonumber(tab[3]),maxCraftAmount=tonumber(tab[4]),fails=0,timer=0}
  54.             if(tab[5]=="true")then
  55.                 recipe.useDmg=true
  56.             else
  57.                 recipe.useDmg=false
  58.             end
  59.             table.insert(recipeList, recipe)
  60.         end  
  61.     end
  62. f:close()
  63.  
  64. function SaveToFile()
  65.     local file = io.open("recipes", "wb")
  66.     for k,v in pairs(recipeList)do
  67.         if(v.useDmg)then
  68.             file:write(v.name.."|"..v.damage.."|"..v.minAmount.."|"..v.maxCraftAmount.."|true|", "\n")
  69.         else
  70.             file.write(v.name.."|"..v.damage.."|"..v.minAmount.."|"..v.maxCraftAmount.."|false|", "\n")
  71.         end
  72.     end
  73.     file:close()
  74. end
  75.  
  76. local function GetActiveTaskCount()
  77.     local n = 0
  78.     for k,v in pairs(bridge.getCraftingCPUs())do
  79.         if(type(v)=="table")then
  80.             if(v.isBusy==true)then
  81.                 n = n+1
  82.             end
  83.         end
  84.     end
  85.     return n
  86. end
  87.  
  88. local function GetAvailableCpuCount()
  89.     return #bridge.getCraftingCPUs() - GetActiveTaskCount()
  90. end    
  91.    
  92. local function GetRecipe(pattern)
  93.     for k,v in pairs(recipeList)do
  94.         if(v.name==pattern.name)then
  95.             if(pattern.damage==nil)then
  96.                 return v
  97.             end
  98.             if(v.useDmg)then
  99.                 if(v.damage==pattern.damage)then
  100.                     return v
  101.                 end
  102.             else
  103.                 return v
  104.             end
  105.         end
  106.     end
  107.    return nil
  108. end
  109.  
  110. local function GetStoredItemAmountNetwork(recipe)
  111.     return bridge.getItem(recipe).count
  112. end
  113.  
  114. local function GetAmount(itemAmount, recipe)
  115.     local amount = 0
  116.     if(itemAmount < recipe.minAmount)then
  117.         if(recipe.maxCraftAmount > 0)then
  118.             if(recipe.minAmount-itemAmount > recipe.maxCraftAmount)then
  119.                 amount = recipe.maxCraftAmount
  120.             else
  121.                 amount = recipe.minAmount-itemAmount
  122.             end
  123.         else
  124.             amount = recipe.minAmount-itemAmount
  125.         end
  126.     end
  127.     return amount
  128. end
  129.    
  130. function GetRecipeKey(pattern)
  131.     for k,v in pairs(recipeList)do
  132.         if(v.name == pattern.name)then
  133.             if(pattern.damage==nil)then return k end
  134.             if(v.useDmg)then
  135.                 if(v.damage == pattern.damage)then
  136.                     return k
  137.                 end
  138.             else
  139.                 return k
  140.             end
  141.         end
  142.     end
  143.     return nil
  144. end
  145.  
  146. local function CheckCraftingRecipe(pattern)
  147.     local recipe = GetRecipe(pattern)
  148.     local item = {item=pattern}
  149.     if(recipe~=nil)then
  150.       local storedAmount = pattern.count
  151.       local neededItemAmount = GetAmount(storedAmount, recipe)
  152.       if(neededItemAmount > 0)then
  153.         item.count = neededItemAmount
  154.         table.insert(craftingQueue, item)
  155.         return true
  156.       end
  157.     end
  158.     return false
  159. end
  160.  
  161. local function CheckAllRecipes()
  162.     for k,v in pairs(bridge.listCraftableItems())do
  163.         if(type(v)=="table")then
  164.             CheckCraftingRecipe(v)
  165.         end
  166.     end
  167. end
  168.  
  169. function RemoveRecipe(item)
  170.     local key = -1
  171.         for k,v in pairs(recipeList)do
  172.             if(v.name == item.name)and(v.damage== item.damage)then
  173.                 key = k
  174.             end
  175.         end
  176.         if(key>=0)then
  177.             table.remove(recipeList, key)
  178.         end
  179.         SaveToFile()
  180. end
  181.  
  182. local function GetCraftable(item)
  183.       for k,v in pairs(bridge.listCraftableItems())do
  184.         if(item.useDmg)then
  185.             if(bridge.getItem(v).name==item.name)then
  186.             if(item.useDmg)then
  187.                 if(v.damage==item.damage)then
  188.                 return v          
  189.                 end
  190.             end
  191.             return v
  192.             end
  193.         end
  194.     end
  195. end
  196.  
  197. local function FindKeyInTable(table, item)
  198.     for k,v in pairs(table)do
  199.         if(v==item)then
  200.             return k
  201.         end
  202.     end
  203.     return nil
  204. end
  205.  
  206. local function isItemCrafting(itemState)
  207. local meItem = bridge.getItem({name=itemState.item.name})
  208.     if(meItem.amount > 0)then
  209.         return bridge.isItemCrafting(meItem)
  210.     else
  211.         print(meItem.amount.."   "..itemState.curAmount + itemState.amountToCraft)
  212.         return (meItem.count < itemState.curAmount + itemState.amountToCraft)
  213.     end
  214. end
  215.  
  216. local function UpdateCraftingQueue()
  217.     while(#craftingQueue > 0)do
  218.         local activeCoWorkers = {}
  219.         local craftingQueuesToRemove = {}
  220.         for k,v in pairs(craftingQueue)do
  221.             if(#activeCoWorkers+1 <= maxCoWorker)then
  222.                 local stack = v.item
  223.                 local recipeKey = GetRecipeKey(stack)
  224.  
  225.                 local waittimer = 0
  226.                 local multiplier = 1
  227.  
  228.                 if(recipeList[recipeKey].fails > 0)and(recipeList[recipeKey].fails <=10)then
  229.                     multiplier = recipeList[recipeKey].fails
  230.                 elseif(recipeList[recipeKey].fails > 10)then
  231.                     multiplier = 20
  232.                 end
  233.                 waittimer = multiplier * 30
  234.                 if(os.clock()>=recipeList[recipeKey].timer+waittimer)then
  235.                     if not(bridge.isItemCrafting({name=stack.name, count=v.count}))then
  236.                         local currentItemState = {item=stack, curAmount = stack.count, amountToCraft = v.count}
  237.                         local task, errormsg = bridge.craftItem({name=stack.name, count=v.count})
  238.                         if(task~=nil)then
  239.                             print("Scheduled Task: "..v.count.." ("..stack.name..") "..stack.displayName)    
  240.                             table.insert(activeCoWorkers, currentItemState)
  241.                             recipeList[recipeKey].fails = 0
  242.                         else
  243.                             print("------------------")
  244.                             print("Error scheduling task: "..v.count.." ("..stack.name..") "..stack.displayName)
  245.                             print(errormsg)
  246.                             print("------------------")
  247.                             recipeList[recipeKey].fails = recipeList[recipeKey].fails + 1
  248.                             recipeList[recipeKey].timer = os.clock()
  249.                         end
  250.                     end
  251.                 end
  252.                 table.insert(craftingQueuesToRemove, v)
  253.             end
  254.         end
  255.  
  256.         if(#craftingQueuesToRemove > 0)then
  257.             for k,v in pairs(craftingQueuesToRemove)do
  258.                 local id = FindKeyInTable(craftingQueue, v)
  259.                 table.remove(craftingQueue, id)
  260.             end
  261.         end
  262.  
  263.         while(#activeCoWorkers > 0)do
  264.             local finishedCoworker = {}
  265.             for k,v in pairs(activeCoWorkers)do
  266.                 if not(bridge.isItemCrafting({name=v.item.name, count=v.amountToCraft}))then
  267.                     print("Task done: "..v.amountToCraft.." ("..v.item.name..") "..v.item.displayName)    
  268.                     table.insert(finishedCoworker, v)
  269.                 end
  270.             end
  271.             if(#finishedCoworker>0)then
  272.                 for k,v in pairs(finishedCoworker)do
  273.                     local id = FindKeyInTable(activeCoWorkers, v)
  274.                     table.remove(activeCoWorkers, id)
  275.                 end
  276.             end
  277.             os.sleep(0.75)
  278.         end
  279.         os.sleep(0.75)
  280.     end
  281. end
  282.  
  283. function FindKeyWithItemName(table, itemname, damage)
  284.     for k,v in pairs(table)do
  285.         if(v.name==itemname)and(v.damage == damage)then
  286.             return k
  287.         end
  288.     end
  289.     return nil
  290. end
  291.  
  292. local function CheckChestForNewEntrys()
  293.     local items = {}
  294.     local itemAmounts = {}
  295.     local somethingChanged = false
  296.      
  297.         if(inventory~=nil)then
  298.             for x=1,inventory.size(), 1 do
  299.                 local item = inventory.getItemDetail(x)
  300.                 if(item~=nil)then
  301.                     if(item.damage==nil)then item.damage = 0 end
  302.                     table.insert(items, item)
  303.                 end
  304.             end
  305.             os.sleep(0.5)
  306.         end
  307.         os.sleep(1)
  308.      
  309.         if(#items > 0)then
  310.             for k,v in pairs(items)do
  311.                 local key = FindKeyWithItemName(itemAmounts, v.name, v.damage)
  312.                 if(key~=nil)then
  313.                     itemAmounts[key].count = itemAmounts[key].count + v.count
  314.                 else
  315.                     table.insert( itemAmounts, {name=v.name, damage=v.damage, count = v.count})
  316.                 end
  317.      
  318.             end
  319.         end
  320.      
  321.         if(#itemAmounts > 0)then
  322.             for k,v in pairs(itemAmounts)do
  323.                 local key = FindKeyWithItemName(recipeList, v.name, v.damage)
  324.                 if(key~=nil)then
  325.                     if(recipeList[key].minAmount ~= v.count)then
  326.                         print("Edited recipe: "..v.name.. ":"..v.damage.." new count: "..v.count)
  327.                     end
  328.                     somethingChanged = true
  329.                     recipeList[key].minAmount = v.count
  330.                 else
  331.                     table.insert( recipeList, {name=v.name, damage=v.damage, minAmount = v.count, maxCraftAmount = 0, useDmg = true, fails = 0, timer = 0})
  332.                     somethingChanged = true
  333.                     print("Registered recipe: "..v.count.."x "..v.name.. ":"..v.damage)
  334.                 end
  335.             end
  336.             if(somethingChanged)then
  337.                 SaveToFile()        
  338.             end
  339.         end
  340. end
  341.  
  342. print("Autocrafter successfully loaded!")
  343.  
  344. while true do
  345.   CheckChestForNewEntrys()
  346.   os.sleep(1)
  347.   if(GetActiveTaskCount()<maxTaskCount)then
  348.     CheckAllRecipes()
  349.     os.sleep(1)
  350.     UpdateCraftingQueue()
  351.     --if not(pcall(UpdateCraftingQueue))then
  352.     --    print("Autocrafter got an unexpected error")
  353.     --end
  354.   else
  355.     os.sleep(5)
  356.   end
  357.   os.sleep(1)
  358. end
Add Comment
Please, Sign In to add comment