hunter3216

compDude.lua

Mar 31st, 2023 (edited)
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.97 KB | None | 0 0
  1. -- This script is part of the compactor automation
  2.  
  3. ----- CONFIG VALUES -----
  4. inputSide = "minecraft:chest_15" -- side of input chest
  5. outputSide = "minecraft:chest_16" -- side of output chest which connects to AE network
  6. robotNum = 8
  7. -------------------------
  8.  
  9. robot = {} -- a list where each element is a table with keys chest, name (name of chest peripheral), recipe, and busy flag
  10. inputItems = {} -- list of input items from chest.list()
  11.  
  12. -- structure of recipes
  13. -- recipes
  14. -- recipes[i].inputs (inputs to recipe)
  15. -- recipes[i].inputs[j].name (name of ingredient)
  16. -- recipes[i].inputs[j].count (number of ingredient per craft)
  17. -- recipes[i].inputs[j].liquid (is the input a liquid - may be more than one bucket)
  18. -- recipes[i].outputs (outputs of recipes)
  19. -- recipes[i].outputs[j].name (name of output)
  20. -- recipes[i].outputs[j].count (number of the output)
  21. -- recipes[i].outputs[j].liquid (is the output a liquid - may be more than one bucket)
  22. -- recipes[i].heated (if the item is heated - false, true, and blazed are possible values)
  23. -- recipes[i].craftNum (number of times the machines operates to craft the recipe - will pull items out and put new items in for each craftNum)
  24.  
  25. -- This function loads the recipes.txt file from pastebin and refreshes the recipes
  26. -- This function gets run when the an unknown recipe shows up
  27. function loadRecipes()
  28. -- delete the old recipes.txt file and get a new one from pastebin
  29. shell.run("rm recipes.txt")
  30. shell.run("pastebin get q0DyXpAc recipes.txt")
  31.  
  32. -- open file for reading
  33. local file = io.open("recipes.txt", "r")
  34.  
  35. if file ~= nil then
  36. -- read file contents into a string
  37. local contents = file:read("*all")
  38.  
  39. -- close file
  40. file:close()
  41.  
  42. -- load contents as a Lua chunk and execute it to set the recipes variable
  43. recipes = load("return " .. contents)()
  44. end
  45. end
  46.  
  47. -- function that initializes input and output chests and all chests that go to the robots
  48. -- it will get chests until there are no more - this way more mixers can be added without needing to change the code
  49. function initChests()
  50. inputChest = peripheral.wrap(inputSide)
  51. outputChest = peripheral.wrap(outputSide)
  52.  
  53. local i = 1
  54. local k = 0
  55. local chest = peripheral.find("minecraft:chest_0") -- Check name that CC gives when connecting chests to modems
  56. local chestStr = "minecraft:chest_" .. tostring(k)
  57. while robotNum - i >= 0 do
  58. if chest ~= nil and chestStr ~= inputSide and chestStr ~= outputSide then
  59. robot[i] = {}
  60. robot[i].name = "minecraft:chest_" .. tostring(k)
  61. robot[i].recipe = nil
  62. robot[i].busy = false
  63. robot[i].chest = chest
  64. i = i + 1
  65. end
  66. k = k + 1
  67. chestStr = "minecraft:chest_" .. tostring(k)
  68. chest = peripheral.wrap(chestStr)
  69. end
  70. end
  71.  
  72. -- iterates through all robots to clear out anything that's in their chests
  73. -- takes everything that's in the robot's chest and sends it to the output chest
  74. function clearItems()
  75. local items
  76. for i = 1, #robot do
  77. items = robot[i].chest.list()
  78.  
  79. for k, v in pairs(items) do
  80. outputChest.pullItems(robot[i].name, k)
  81. end
  82. end
  83. end
  84.  
  85. -- return the index of the first robot that is free
  86. -- returns false if not robot is free
  87. function findNextFree()
  88. for i = 1, # robot do
  89. if not robot[i].busy then
  90. return i
  91. end
  92. end
  93. return false
  94. end
  95.  
  96. -- checks if the recipe matches the items
  97. -- courtesy of GPT3
  98. function checkRecipe(items, recipe)
  99. -- First, we need to check if the tables have the same number of elements
  100. if #items ~= #recipe then
  101. return false
  102. end
  103.  
  104. -- Next, we need to create a copy of recipe to keep track of the elements that we've already matched
  105. local recipe_copy = {}
  106. for i, v in ipairs(recipe) do
  107. recipe_copy[i] = v
  108. end
  109.  
  110. -- Then, we loop through each element in items
  111. for _, element1 in ipairs(items) do
  112. local match_found = false
  113.  
  114. -- We loop through each element in recipe_copy to find a match for element1
  115. for i, element2 in ipairs(recipe_copy) do
  116. if element1.name == element2.name and element1.count == element2.count then
  117. -- We found a match, so we remove element2 from recipe_copy and move on to the next element in items
  118. table.remove(recipe_copy, i)
  119. match_found = true
  120. break
  121. end
  122. end
  123.  
  124. -- If we didn't find a match for element1 in recipe, then the tables don't match
  125. if not match_found then
  126. return false
  127. end
  128. end
  129.  
  130. -- If we got through all of the elements in items without finding any mismatches, and recipe_copy is now empty, then the tables match
  131. return #recipe_copy == 0
  132. end
  133.  
  134.  
  135. -- returns the recipe corresponding to the items in the input chest
  136. -- first checks if the correct recipe is the previous recipe
  137. function findRecipe(inputItems, prevRecipe)
  138. if prevRecipe == nil then
  139. prevRecipe = recipes[1] -- sets prevRecipe to the first recipe if there wasn't a prev recipe.
  140. end
  141.  
  142. if checkRecipe(inputItems, prevRecipe.inputs) then
  143. return prevRecipe
  144. end
  145.  
  146. rIx = nil
  147. for i = 1, #recipes do
  148. if checkRecipe(inputItems, recipes[i].inputs) then
  149. rIx = i
  150. break
  151. end
  152. end
  153.  
  154. if rIx ~= nil then
  155. return recipes[rIx]
  156. else
  157. print("Couldn't find recipe - updating list and trying again")
  158. loadRecipes()
  159. rIx = nil
  160. for i = 1, #recipes do
  161. if checkRecipe(inputItems, recipes[i].inputs) then
  162. rIx = i
  163. break
  164. end
  165. end
  166. end
  167.  
  168. if rIx ~= nil then
  169. return recipes[rIx]
  170. else
  171. local errStr = inputItems[1].count .. " " .. inputItems[1].name .. "\n"
  172. for i = 2, #inputItems do
  173. errStr = errStr .. inputItems[i].count .. " " .. inputItems[i].name .. "\n"
  174. end
  175. error("Recipe could not be found! Check the recipe list for the following\n" .. errStr)
  176. end
  177. end
  178.  
  179. -- Sends the items to the avaliable robot
  180. function sendToRobot(robot, inputItems, nextRecipe)
  181. for k, v in pairs(inputItems) do
  182. inputChest.pushItems(robot.name, k)
  183. end
  184. robot.recipe = nextRecipe
  185. robot.busy = true
  186. end
  187.  
  188. -- checks of the output of a recipe given to a robot is finished
  189. -- if the output is finished the result is placed in the output chest and the robot's busy flag is set to false
  190. function getOutput(robot)
  191. outputItems = robot.chest.list()
  192.  
  193. if outputItems ~= nil and checkRecipe(outputItems, robot.recipe.outputs) then
  194. robot.busy = false
  195. for k,v in pairs(outputItems) do
  196. outputChest.pullItems(robot.name, k)
  197. end
  198. end
  199. end
  200.  
  201. -- Initializes the computer for mixer automation
  202. function init()
  203. os.sleep(0) -- wait for robots to dump anything that was in the process of being crafted
  204.  
  205. loadRecipes()
  206. initChests()
  207.  
  208. clearItems()
  209. end
  210.  
  211. -- The main function which handles the automation
  212. function main()
  213. init()
  214. local nextRecipe = nil
  215. while true do
  216. local inputItems = inputChest.list()
  217. if inputItems[1] ~= nil then
  218. local freeIx = findNextFree()
  219. if freeIx then
  220. nextRecipe = findRecipe(inputItems, nextRecipe)
  221. sendToRobot(robot[freeIx], inputItems, nextRecipe)
  222. end
  223. end
  224.  
  225. -- loop through all busy robots to check for outputs
  226. for i = 1, #robot do
  227. if robot[i].busy then
  228. getOutput(robot[i])
  229. end
  230. end
  231. os.sleep(0) -- sleep to prevent 'Too long without yielding' error
  232. end
  233. end
  234.  
  235. args = ...
  236. if args == "debug" or args == "d" then
  237. os.loadAPI("mixerDude.lua")
  238. else
  239. main()
  240. end
Add Comment
Please, Sign In to add comment