Advertisement
tobast

[CC] turtleFactory_v2

Apr 18th, 2015
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.74 KB | None | 0 0
  1. function makeEnum(vals)
  2.     -- Expects vals to be a numeric array, ie vals = {blah,blah2, ...}
  3.     out = {}
  4.     for k,v in pairs(vals) do
  5.         out[v]=k
  6.     end
  7.     return out
  8. end
  9.  
  10. --================ ASSEMBLY LINE FORMAT ================--
  11. -- Each var describes the position of a block along the production line.
  12. -- The turtle will attempt to seek those blocks on its bottom, and starts
  13. -- at position 0.
  14. INPUT_CHEST_POS = 0
  15. MF_EXTRUDE_POS = 1
  16. TEMP_CHEST_POS = 2
  17. MF_ROLL_POS = 3
  18. OUTPUT_CHEST_POS = 4
  19.  
  20. PROD_LINE_ORIENTATION = 'up' -- the direction the turtle is from the
  21.     -- production line's point of view.
  22.  
  23. --================ GENERATE RECIPES =====================--
  24. --[[ Recipe format : table 't'
  25.     * t.tool = raw | craft | mf_roll | mf_extrude
  26.     * if raw : the material is a raw material, gathered from input chest.
  27.     * if craft:
  28.         o t.recipe = 3*3 array, recipe. Values belong to recipes enum.
  29.         o Must be crafted as turtle craft.
  30.     * if mf_roll:
  31.         o Must be processed by a metal former in roll mode
  32.         o t.material : belongs to the recipes enum, to be fed to the MF
  33.     * if mf_extrude:
  34.         o Must be processed by a metal former in extrude mode
  35.         o t.material : idem mf_roll
  36. --]]
  37.  
  38. RECIPES_NAMES = { 'air','iron_plate','tin_plate','tin_casing','tin_cable',
  39.     'tin_ins_cable','re_batt','copper_cable','copper_ins_cable',
  40.     'elec_circ','iron_casing','coil','elec_motor','power_unit',
  41.     'chainsaw','drill','tin','iron','rubber','copper','redstone' }
  42.  
  43. NAMES_ENUM = makeEnum(RECIPES_NAMES)
  44.  
  45. CC_NAMES = {'','ic2.itemplateiron','ic2.itemplatetin','ic2.itemcasingtin',
  46.     'ic2.itemtincable','ic2.itemtincablei','ic2.itembatredischarged',
  47.     'ic2.itemcableo','ic2.itemcable','ic2.itempartcircuit','ic2.itemironcasing',
  48.     'ic2.itempartcoil','ic2.itempartelemotor','ic2.itempowerunit',
  49.     'ic2.itemtoolchainsaw','ic2.itemtooldrill', 'ic2.itemingottin',
  50.     'item.ingotiron','ic2.itemrubber','ic2.itemingotcopper','item.redstone'
  51. }
  52. REVERSE_CC_NAMES = makeEnum(CC_NAMES)
  53.  
  54. STACK_SIZES = {64,64,64,64,64,64,16,64,64,64,64,64,64,64,1,1,64,64,64,64,64}
  55. CRAFT_RATIO = {1,1,1,2,3,1,1,3,1,1,2,1,1,1,1,1,1,1,1,1,1}
  56. CRAFT_ORDER = {1,17,18,19,20,21,2,3,4,5,8,11,6,9,7,10,12,13,14,15,16}
  57.  
  58. RECIPES = {}
  59. RECIPES[NAMES_ENUM['air']] = { tool='raw' }
  60. RECIPES[NAMES_ENUM['iron_plate']] = { tool='mf_roll', material=NAMES_ENUM['iron'] }
  61. RECIPES[NAMES_ENUM['tin_plate']] = { tool='mf_roll', material=NAMES_ENUM['tin'] }
  62. RECIPES[NAMES_ENUM['tin_casing']] = { tool='mf_roll',
  63.     material=NAMES_ENUM['tin_plate'] }
  64. RECIPES[NAMES_ENUM['tin_cable']] = { tool='mf_extrude', material=NAMES_ENUM['tin'] }
  65. RECIPES[NAMES_ENUM['tin_ins_cable']] = { tool='craft', recipe={
  66.     {NAMES_ENUM['tin_cable'],NAMES_ENUM['rubber'],1},{1,1,1},{1,1,1}} }
  67. RECIPES[NAMES_ENUM['re_batt']] = { tool='craft', recipe={
  68.     {1,NAMES_ENUM['tin_ins_cable'],1},
  69.     {NAMES_ENUM['tin_casing'],NAMES_ENUM['redstone'],NAMES_ENUM['tin_casing']},
  70.     {NAMES_ENUM['tin_casing'],NAMES_ENUM['redstone'],NAMES_ENUM['tin_casing']}}}
  71. RECIPES[NAMES_ENUM['copper_cable']] = { tool='mf_extrude',
  72.     material=NAMES_ENUM['copper'] }
  73. RECIPES[NAMES_ENUM['copper_ins_cable']] = { tool='craft', recipe={
  74.     {NAMES_ENUM['copper_cable'],NAMES_ENUM['rubber'],1},{1,1,1},{1,1,1}} }
  75. RECIPES[NAMES_ENUM['elec_circ']] = { tool='craft', recipe={
  76.     {NAMES_ENUM['copper_ins_cable'],NAMES_ENUM['copper_ins_cable'],NAMES_ENUM['copper_ins_cable']},
  77.     {NAMES_ENUM['redstone'],NAMES_ENUM['iron_plate'],NAMES_ENUM['redstone']},
  78.     {NAMES_ENUM['copper_ins_cable'],NAMES_ENUM['copper_ins_cable'],NAMES_ENUM['copper_ins_cable']}}}
  79. RECIPES[NAMES_ENUM['iron_casing']] = { tool='mf_roll',
  80.     material=NAMES_ENUM['iron_plate'] }
  81. RECIPES[NAMES_ENUM['coil']] = { tool='craft', recipe={
  82.     {NAMES_ENUM['copper_cable'],NAMES_ENUM['copper_cable'],NAMES_ENUM['copper_cable']},
  83.     {NAMES_ENUM['copper_cable'],NAMES_ENUM['iron'],NAMES_ENUM['copper_cable']},
  84.     {NAMES_ENUM['copper_cable'],NAMES_ENUM['copper_cable'],NAMES_ENUM['copper_cable']}}}
  85. RECIPES[NAMES_ENUM['elec_motor']] = { tool='craft', recipe={
  86.     {1,NAMES_ENUM['tin_casing'],1},
  87.     {NAMES_ENUM['coil'],NAMES_ENUM['iron'],NAMES_ENUM['coil']},
  88.     {1,NAMES_ENUM['tin_casing'],1}}}
  89. RECIPES[NAMES_ENUM['power_unit']] = { tool='craft', recipe={
  90.     {NAMES_ENUM['re_batt'],NAMES_ENUM['copper_cable'],NAMES_ENUM['iron_casing']},
  91.     {NAMES_ENUM['re_batt'],NAMES_ENUM['elec_circ'],NAMES_ENUM['elec_motor']},
  92.     {NAMES_ENUM['re_batt'],NAMES_ENUM['copper_cable'],NAMES_ENUM['iron_casing']}}}
  93. RECIPES[NAMES_ENUM['chainsaw']] = { tool='craft', recipe={
  94.     {1,NAMES_ENUM['iron_plate'],NAMES_ENUM['iron_plate']},
  95.     {NAMES_ENUM['iron_plate'],NAMES_ENUM['iron_plate'],NAMES_ENUM['iron_plate']},
  96.     {NAMES_ENUM['power_unit'],NAMES_ENUM['iron_plate'],1}}}
  97. RECIPES[NAMES_ENUM['drill']] = { tool='craft', recipe={
  98.     {1,NAMES_ENUM['iron_plate'],1},
  99.     {NAMES_ENUM['iron_plate'],NAMES_ENUM['iron_plate'],NAMES_ENUM['iron_plate']},
  100.     {NAMES_ENUM['iron_plate'],NAMES_ENUM['power_unit'],NAMES_ENUM['iron_plate']}}}
  101. RECIPES[NAMES_ENUM['tin']] = { tool='raw' }
  102. RECIPES[NAMES_ENUM['iron']] = { tool='raw' }
  103. RECIPES[NAMES_ENUM['rubber']] = { tool='raw' }
  104. RECIPES[NAMES_ENUM['copper']] = { tool='raw' }
  105. RECIPES[NAMES_ENUM['redstone']] = { tool='raw' }
  106.  
  107. --=================== END CONSTANTS ========================--
  108.  
  109. turtlePos = -1
  110.  
  111. function goToPos(pos)
  112.     while(pos > turtlePos) do
  113.         turtle.forward()
  114.         turtlePos = turtlePos + 1
  115.     end
  116.     while(pos < turtlePos) do
  117.         turtle.back()
  118.         turtlePos = turtlePos - 1
  119.     end
  120. end
  121.  
  122. function getFromBlock(recipeId, number)
  123.     while true do
  124.         inv = peripheral.wrap('bottom')
  125.         inv.condenseItems()
  126.         nbSlots = inv.getInventorySize()
  127.         for slot=1,nbSlots do
  128.             obj = inv.getStackInSlot(slot)
  129.             if(obj ~= nil and obj.raw_name == CC_NAMES[recipeId]) then
  130.                 --Since we've condensed and we are assured that number < stackSize
  131.                 --we can safely take only from the first slot we find
  132.                 inv.pushItemIntoSlot(PROD_LINE_ORIENTATION,slot,number,1)
  133.                 return
  134.             end
  135.         end
  136.         -- We've tried the whole inventory! The item is not present
  137.         print('Missing '..RECIPES_NAMES[recipeId].." x"..number)
  138.         print('Press enter to try again...')
  139.         read()
  140.     end
  141. end
  142.  
  143. function pushInTemp(fromSlot)
  144.     goToPos(TEMP_CHEST_POS)
  145.     local inv = peripheral.wrap('bottom')
  146.     inv.pullItemIntoSlot(PROD_LINE_ORIENTATION,fromSlot)
  147.     inv.condenseItems()
  148. end
  149.  
  150. function pushToOutput(number)
  151.     -- Pushes <number> items from #1 and puts it into output chest
  152.     goToPos(OUTPUT_CHEST_POS)
  153.    
  154.     ch = peripheral.wrap('bottom')
  155.     ch.pullItem(PROD_LINE_ORIENTATION, 1, number)
  156. end
  157.  
  158. function processInMF()
  159.     -- Assumes the turtle to be above the right MF, puts everything from #1
  160.     -- into MF and waits to take it back.
  161.  
  162.     -- MF input slot: 7 ; output slot: 2
  163.     mf = peripheral.wrap('bottom')
  164.     mf.pullItem(PROD_LINE_ORIENTATION, 1, nil, 7)
  165.     while mf.getStackInSlot(7) ~= nil or mf.getProgress() < 100 do
  166.         os.sleep(1)
  167.     end -- We're now done
  168.     mf.pushItem(PROD_LINE_ORIENTATION, 2, nil, 1)
  169. end
  170.  
  171. function getRequirements(recipeId, number, requirements,leftovers)
  172.     local isRootCall = false
  173.  
  174.     -- init
  175.     if(requirements == nil) then
  176.         isRootCall = true
  177.         requirements = {}
  178.         leftovers = {}
  179.         for k,_ in pairs(RECIPES_NAMES) do
  180.             requirements[k]=0
  181.             leftovers[k]=0
  182.         end
  183.  
  184.         goToPos(TEMP_CHEST_POS)
  185.         local ch = peripheral.wrap('bottom')
  186.         local nbSlots = ch.getInventorySize()
  187.  
  188.         for slot=1,nbSlots do
  189.             contents = ch.getStackInSlot(slot)
  190.             if(contents ~= nil) then
  191.                 slotRecipe = REVERSE_CC_NAMES[contents.raw_name]
  192.                 leftovers[slotRecipe] = leftovers[slotRecipe] + contents.qty
  193.             end
  194.         end
  195.     end
  196.  
  197.     local tool = RECIPES[recipeId].tool
  198.     local nNumber = math.max(0,number-leftovers[recipeId])
  199.     leftovers[recipeId] = math.max(0,leftovers[recipeId] - number)
  200.     number = nNumber
  201.     local nbCrafts = math.ceil(number/CRAFT_RATIO[recipeId])
  202.     leftovers[recipeId] = leftovers[recipeId] +
  203.         (CRAFT_RATIO[recipeId] - number) % CRAFT_RATIO[recipeId]
  204.  
  205.     requirements[recipeId] = requirements[recipeId] + nbCrafts
  206.  
  207.     if(tool == 'raw') then -- ___RAW___
  208.         requirements[recipeId] = requirements[recipeId]+nbCrafts
  209.     elseif(tool == 'craft') then -- ___CRAFT___
  210.         local recipe = RECIPES[recipeId].recipe
  211.         for i=1,3 do for j=1,3 do
  212.             requirements=getRequirements(recipe[i][j], nbCrafts,
  213.                 requirements,leftovers)
  214.         end end
  215.     elseif(tool == 'mf_roll' or tool == 'mf_extrude') then --___MF___
  216.         requirements = getRequirements(RECIPES[recipeId].material, nbCrafts,
  217.                 requirements,leftovers)
  218.     end
  219.    
  220.     return requirements
  221. end
  222.  
  223. function craftRecipe(recipeId,number)
  224.     -- Crafts [number] items, then put them in the temp chest
  225.     -- Assumes number <= stackSize
  226.  
  227.     local tool = RECIPES[recipeId].tool
  228.     if(tool == 'raw') then
  229.         if(recipeId == 1) then -- air, ie nothing
  230.             return -- We're done ;)
  231.         end
  232.  
  233.         goToPos(INPUT_CHEST_POS)
  234.         getFromBlock(recipeId,number)
  235.         pushInTemp(1)
  236.     elseif(tool == 'craft') then
  237.         local recipe = RECIPES[recipeId].recipe
  238.         local maxProcessPack = 0
  239.         for i=1,3 do for j=1,3 do
  240.             maxProcessPack = math.min(STACK_SIZES[recipe[i][j]], maxProcessPack)
  241.         end end
  242.         number = math.ceil(number / CRAFT_RATIO[recipeId])
  243.  
  244.         while number > 0 do
  245.             goToPos(TEMP_CHEST_POS)
  246.             for i=1,3 do
  247.                 for j=1,3 do
  248.                     if(recipe[i][j] ~= 1) then -- not air
  249.                         getFromBlock(recipe[i][j], number)
  250.                         turtle.transferTo(i*4+j+1)
  251.                     end
  252.                 end
  253.             end
  254.             turtle.craft(maxProcessPack)
  255.            
  256.             pushInTemp(1)
  257.            
  258.             number = number - maxProcessPack -- Might be below the real number
  259.             -- but it is okay
  260.         end
  261.     elseif(tool == 'mf_roll' or tool == 'mf_extrude') then
  262.         -- Now we have all we want in first slot (maybe more?)
  263.         local toolPos = -1
  264.         if(tool == 'mf_roll') then
  265.             toolPos = MF_ROLL_POS
  266.         elseif(tool == 'mf_extrude') then
  267.             toolPos = MF_EXTRUDE_POS
  268.         else
  269.             error("Dafuq, invalid tool")
  270.         end
  271.  
  272.         goToPos(TEMP_CHEST_POS)
  273.         local reqNum = math.ceil(number / CRAFT_RATIO[recipeId])
  274.         getFromBlock(RECIPES[recipeId].material, reqNum)
  275.  
  276.         goToPos(toolPos)
  277.         processInMF()
  278.         pushInTemp(1)
  279.     end
  280. end
  281.  
  282. function doCraft(recipeId, number)
  283.     local requirements = getRequirements(recipeId,number)
  284.  
  285.     for _,step in pairs(CRAFT_ORDER) do
  286.         if(requirements[step] > 0) then
  287.             craftRecipe(step,requirements[step])
  288.         end
  289.     end
  290.  
  291.     goToPos(TEMP_CHEST_POS)
  292.     getFromBlock(recipeId, number)
  293.     goToPos(OUTPUT_CHEST_POS)
  294.     local ch=peripheral.wrap('bottom')
  295.     ch.pullItem(PROD_LINE_ORIENTATION,1)
  296.     goToPos(-1)
  297. end
  298.  
  299. function craftName(name, number)
  300.     if(NAMES_ENUM[name] == nil) then
  301.         print("Invalid name")
  302.     else
  303.         doCraft(NAMES_ENUM[name],number)
  304.     end
  305. end
  306.  
  307. function dispRequirements(name, number)
  308.     local req = getRequirements(NAMES_ENUM[name], number)
  309.     goToPos(-1)
  310.     str = ''
  311.     parity = 0
  312.     for k,v in pairs(req) do
  313.         if(parity % 2 == 0 and parity ~= 0) then
  314.             print(str)
  315.             str=''
  316.         elseif(parity % 2 == 1) then
  317.             str = str .. ' || '
  318.         end
  319.         str = str .. RECIPES_NAMES[k]..' '..v
  320.         parity = parity + 1
  321.     end
  322.     print(str)
  323. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement