JustMark

Tree Farmer

Jul 11th, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.51 KB | None | 0 0
  1. --[[
  2.     TODO:
  3.     1. handle not having saplings in the chest
  4.     2. make persistance better
  5.     3. minimum clearing interval
  6. --]]
  7.  
  8. math.sign = math.sign or function(x)
  9.     return x < 0 and -1 or x > 0 and 1 or 0
  10. end
  11.  
  12. table.shallowCopy = function(t)
  13.   local t2 = {}
  14.   for k,v in pairs(t) do
  15.     t2[k] = v
  16.   end
  17.   return t2
  18. end
  19.  
  20. function printMessage(line)
  21.     term.clear()
  22.     print(line)
  23. end
  24.  
  25. function printSleep(line)
  26.     printMessage(line)
  27.     sleep(1)
  28.     term.clear()
  29. end
  30.  
  31. local currentPosition = {
  32.     x = -4;
  33.     y = 0;
  34.     z = 4;
  35. }
  36.  
  37. local currentDirection = 4
  38.  
  39. local persisted = false
  40.  
  41. local currentSlot = nil
  42.  
  43. local woodWhitelist = {
  44.     'minecraft:oak_log',
  45.     'minecraft:spruce_log',
  46.     'minecraft:birch_log',
  47.     'minecraft:jungle_log',
  48.     'minecraft:acacia_log',
  49.     'minecraft:dark_oak_log'
  50. }
  51.  
  52. local saplingWhitelist = {
  53.     'minecraft:oak_sapling',
  54.     'minecraft:spruce_sapling',
  55.     'minecraft:birtch_sapling',
  56.     'minecraft:jungle_sapling',
  57.     'minecraft:acacia_sapling',
  58.     'minecraft:dark_oak_sapling'
  59. }
  60.  
  61. local fuelWhitelist = {
  62.     'minecraft:coal',
  63.     'minecraft:charcoal'
  64. }
  65.  
  66. local fuelStorageDirection = 1
  67. local saplingStorageDirection = 3
  68.  
  69. local fuelSlot = 16
  70. local minFuelToStart = 16
  71. local minFuelToContinue = 2
  72.  
  73. function readData(name)
  74.     if fs.exists('/data/'..name) then
  75.         local handle = fs.open('/data/'..name, 'r')
  76.         local stuff = handle.readAll()
  77.         handle.close()
  78.         return textutils.unserialize(stuff)
  79.     end
  80.  
  81.     return
  82. end
  83.  
  84. function writeData(name, data)
  85.     if not fs.exists('/data') then
  86.         fs.makeDir('/data')
  87.     end
  88.  
  89.     local handle = fs.open('/data/'..name, 'w')
  90.     handle.write(textutils.serialize(data))
  91.     handle.close()
  92. end
  93.  
  94. function loadData()
  95.     local loadedPosition = readData('position')
  96.     local loadedDirection = readData('direction')
  97.  
  98.     if (loadedPosition ~= nil) or (loadedDirection ~= nil) then
  99.         currentPosition = loadedPosition or currentPosition
  100.         currentDirection = loadedDirection or currentDirection
  101.  
  102.         persisted = true
  103.     end
  104. end
  105.  
  106. function updatePosition(deltaX, deltaY, deltaZ)
  107.     currentPosition.x = currentPosition.x + deltaX
  108.     currentPosition.y = currentPosition.y + deltaY
  109.     currentPosition.z = currentPosition.z + deltaZ
  110.  
  111.     writeData('position', currentPosition)
  112. end
  113.  
  114. function updateDirection(deltaD)
  115.     currentDirection = (currentDirection + deltaD - 1) % 4 + 1
  116.  
  117.     writeData('direction', currentDirection)
  118. end
  119.  
  120. function directionToXZ(direction)
  121.     return {
  122.         x = (direction- 2) * (direction% 2),
  123.         z = (direction- 3) * ((direction+ 1) % 2)
  124.     }
  125. end
  126.  
  127. function moveForward(steps, force)
  128.     steps = steps or 1
  129.  
  130.     for i = 1, steps do  
  131.         handleFuel()
  132.  
  133.         if force == true then
  134.             while turtle.detect() do
  135.                 turtle.dig()
  136.             end
  137.         end
  138.    
  139.         moved = turtle.forward()
  140.  
  141.         if moved == true then
  142.             deltaXZ = directionToXZ(currentDirection)
  143.  
  144.             updatePosition(deltaXZ.x, 0, deltaXZ.z)
  145.         else
  146.             printSleep('turtle is stuck, please remove the block in front')
  147.             i = i - 1
  148.         end
  149.     end
  150. end
  151.  
  152. function moveUp(steps, force)
  153.     steps = steps or 1
  154.  
  155.     for i = 1, steps do  
  156.         handleFuel()
  157.    
  158.         if force == true then
  159.           while turtle.detectUp() do
  160.                turtle.digUp()
  161.             end
  162.         end
  163.  
  164.         moved = turtle.up()
  165.  
  166.         if moved == true then
  167.             updatePosition(0, 1, 0)
  168.         else
  169.             printSleep('turtle is stuck, please remove the block above')
  170.             i = i - 1
  171.         end
  172.     end
  173. end
  174.  
  175. function moveDown(steps, force)
  176.     steps = steps or 1
  177.  
  178.     for i = 1, steps do  
  179.         handleFuel()
  180.  
  181.         if force == true then
  182.             while turtle.detectDown() do
  183.                 turtle.digDown()
  184.             end
  185.         end
  186.  
  187.         moved = turtle.down()
  188.  
  189.         if moved == true then
  190.             updatePosition(0, -1, 0)
  191.         else
  192.             printSleep('turtle is stuck, please remove the block below')
  193.             i = i - 1
  194.         end
  195.     end
  196. end
  197.  
  198. function moveBack(steps, force, maintaintDirection)
  199.     steps = steps or 1
  200.  
  201.     for i = 1, steps do  
  202.         handleFuel()
  203.  
  204.         moved = turtle.back()
  205.  
  206.         if moved == true then
  207.             deltaXZ = directionToXZ(currentDirection)
  208.  
  209.             updatePosition(-deltaXZ.x, 0, -deltaXZ.z)
  210.         else
  211.             if force == true then
  212.                 turnAround()
  213.                 moveForward(steps - i + 1, true)
  214.  
  215.                 if maintaintDirection == true then
  216.                     turnAround()
  217.                 end
  218.  
  219.                 return
  220.             else
  221.                 printSleep('turtle is stuck, please remove the block behind')
  222.                 i = i - 1
  223.             end
  224.         end
  225.     end
  226. end
  227.  
  228. function turnLeft()
  229.     turtle.turnLeft()
  230.     updateDirection(1)
  231. end
  232.  
  233. function turnRight()
  234.     turtle.turnRight()
  235.     updateDirection(-1)
  236. end
  237.  
  238. function turnAround()
  239.     turnRight()
  240.     turnRight()
  241. end
  242.  
  243. function turnTo(direction)
  244.     if direction == nil or direction == currentDirection then
  245.         return
  246.     end
  247.  
  248.     local deltaDir = currentDirection - direction
  249.    
  250.     local temp = (currentDirection % 4) - (direction % 4)
  251.     if math.abs(temp) < math.abs(deltaDir) then
  252.         deltaDir = temp
  253.     end
  254.  
  255.     if deltaDir < 0 then
  256.         for i = 1, -deltaDir do
  257.             turnLeft()
  258.         end
  259.     elseif deltaDir > 0 then
  260.         for i = 1, deltaDir do
  261.             turnRight()
  262.         end
  263.     end
  264. end
  265.  
  266. function turnToXAxis(preferedSign)
  267.     if currentDirection == 4 then
  268.         if preferedSign == -1 then
  269.             turnLeft()
  270.         else
  271.             turnRight()
  272.         end
  273.     elseif currentDirection == 2 then
  274.         if preferedSign == -1 then
  275.             turnRight()
  276.         else
  277.             turnLeft()
  278.         end
  279.     end
  280. end
  281.  
  282. function turnToZAxis(preferedSign)
  283.     if currentDirection == 1 then
  284.         if preferedSign == -1 then
  285.             turnLeft()
  286.         else
  287.             turnRight()
  288.         end
  289.     elseif currentDirection == 3 then
  290.         if preferedSign == -1 then
  291.             turnRight()
  292.         else
  293.             turnLeft()
  294.         end
  295.     end
  296. end
  297.  
  298. function moveOnXAxis(delta, force, maintaintDirection)
  299.     if delta == 0 or delta == nil then
  300.         return
  301.     end
  302.  
  303.     local startDir = currentDirection
  304.     local distance = math.abs(delta)
  305.     local sign = math.sign(delta)
  306.  
  307.     turnToXAxis(sign)
  308.    
  309.     local currentSign = (currentDirection == 3) and 1 or -1
  310.  
  311.     if sign * currentSign == 1 then
  312.         moveForward(distance, force)
  313.     else
  314.         moveBack(distance, force, false)
  315.     end
  316.  
  317.     if maintainDirection then
  318.         turnTo(startDir)
  319.     end
  320. end
  321.  
  322. function moveOnYAxis(delta, force)
  323.     if delta == 0 or delta == nil then
  324.         return
  325.     end
  326.  
  327.     local distance = math.abs(delta)
  328.     local sign = math.sign(delta)
  329.  
  330.     if sign == 1 then
  331.         moveUp(distance, force)
  332.     else
  333.         moveDown(distance, force)
  334.     end
  335. end
  336.  
  337. function moveOnZAxis(delta, force, maintaintDirection)
  338.     if delta == 0 or delta == nil then
  339.         return
  340.     end
  341.  
  342.     local startDir = currentDirection
  343.     local distance = math.abs(delta)
  344.     local sign = math.sign(delta)
  345.  
  346.     turnToZAxis(sign)
  347.    
  348.     local currentSign = (currentDirection == 4) and 1 or -1
  349.  
  350.     if sign * currentSign == 1 then
  351.         moveForward(distance, force)
  352.     else
  353.         moveBack(distance, force, false)
  354.     end
  355.  
  356.     if maintainDirection then
  357.         turnTo(startDir)
  358.     end
  359. end
  360.  
  361. function moveToX(x, force, maintaintDirection)
  362.     if x == nil then
  363.         return
  364.     end
  365.  
  366.     local delta = x - currentPosition.x
  367.     moveOnXAxis(delta, force, maintainDirection)
  368. end
  369.  
  370. function moveToY(y, force)
  371.     if y == nil then
  372.         return
  373.     end
  374.    
  375.     local delta = y - currentPosition.y
  376.     moveOnYAxis(delta, force, maintainDirection)
  377. end
  378.  
  379. function moveToZ(z, force, maintaintDirection)
  380.     if z == nil then
  381.         return
  382.     end
  383.  
  384.     local delta = z - currentPosition.z
  385.     moveOnZAxis(delta, force, maintainDirection)
  386. end
  387.  
  388. function moveTo(x, y, z, force, maintaintDirection)
  389.     local startDir = currentDirection
  390.  
  391.     if currentPosition.y < 0 then
  392.         moveToY(y, force)
  393.  
  394.         if math.abs(currentPosition.x) > math.abs(currentPosition.z) then
  395.             moveToX(x, force, false)
  396.             moveToZ(z, force, false)
  397.         else
  398.             moveToZ(z, force, false)
  399.             moveToX(x, force, false)
  400.         end
  401.     else
  402.         if math.abs(currentPosition.x) > math.abs(currentPosition.z) then
  403.             moveToX(x, force, false)
  404.             moveToZ(z, force, false)
  405.         else
  406.             moveToZ(z, force, false)
  407.             moveToX(x, force, false)
  408.         end
  409.  
  410.         moveToY(y, force)
  411.     end
  412.  
  413.     if maintainDirection == true then
  414.         turnTo(startDir)
  415.     end
  416. end
  417.  
  418. function digForward()
  419.     turtle.dig()
  420.     moveForward(1, true)
  421. end    
  422.  
  423. function digUp()
  424.     turtle.digUp()
  425.     moveUp(1, true)
  426. end
  427.  
  428. function digDown()
  429.     turtle.digDown()
  430.     moveDown(1, true)
  431. end
  432.  
  433. function select(slot)
  434.     if slot == nil then
  435.         return
  436.     end
  437.  
  438.     turtle.select(slot)
  439.     currentSlot = slot
  440. end
  441.  
  442. function hasEmptySlots(number)
  443.     number = number or 1
  444.  
  445.     local empty = 0
  446.  
  447.     for i = 1, 16 do
  448.         if turtle.getItemDetail(i) == nil then
  449.             empty = empty + 1
  450.  
  451.             if empty >= number then
  452.                 return true
  453.             end
  454.         end
  455.     end
  456.  
  457.     return false
  458. end
  459.  
  460. function handleFuel()
  461.     local fuel = turtle.getFuelLevel()
  462.    
  463.     if fuel == 0 then
  464.         local previousSlot = currentSlot
  465.         select(fuelSlot)
  466.         while not turtle.refuel(1) do
  467.             printSleep('turtle is out of fuel, please add some fuel to slot '..fuelSlot)
  468.         end
  469.         select(previousSlot)
  470.     end
  471. end
  472.  
  473. function handleResources(returnBack)
  474.     local previousSlot = currentSlot
  475.  
  476.     if (selectSapling() == false) or
  477.        (hasEmptySlots(2) == false) or
  478.        (isFuel(getItemName(fuelSlot)) == false) or
  479.        (turtle.getItemCount(fuelSlot) < minFuelToContinue) then
  480.                
  481.         restock(returnBack)
  482.     end
  483.  
  484.     select(previousSlot)
  485. end
  486.  
  487. function isWood(name)
  488.     for i = 1, #woodWhitelist do
  489.         if (name == woodWhitelist [i]) then
  490.             return true
  491.         end
  492.     end
  493.  
  494.     return false
  495. end
  496.  
  497. function isSapling(name)
  498.     for i = 1, #saplingWhitelist do
  499.         if (name == saplingWhitelist [i]) then
  500.             return true
  501.         end
  502.     end
  503.  
  504.     return false
  505. end
  506.  
  507. function isFuel(name)
  508.     for i = 1, #fuelWhitelist do
  509.         if (name == fuelWhitelist[i]) then
  510.             return true
  511.         end
  512.     end
  513.  
  514.     return false
  515. end
  516.  
  517. function getItemName(slot)
  518.     if slot == nil then
  519.         return nil
  520.     end
  521.    
  522.     local detail = turtle.getItemDetail(slot)
  523.  
  524.     return detail and detail.name or nil
  525. end
  526.  
  527. function selectSapling()
  528.     local holdingSapling = isSapling(getItemName(currentSlot))
  529.  
  530.     if holdingSapling == false then
  531.         for i = 1, 15 do
  532.             if i ~= currentSlot then
  533.                 local foundSapling = isSapling(getItemName(i))
  534.  
  535.                 if foundSapling == true then
  536.                     select(i)
  537.                     return true
  538.                 end
  539.             end
  540.         end
  541.  
  542.         return false
  543.     end
  544.  
  545.     return true
  546. end
  547.  
  548. function selectWood()
  549.     local holdingWood = isWood(getItemName(currentSlot))
  550.  
  551.     if holdingWood == false then
  552.         for i = 1, 15 do
  553.             if i ~= currentSlot then
  554.                 local foundWood = isWood(getItemName(i))
  555.  
  556.                 if foundWood == true then
  557.                     select(i)
  558.                     return true
  559.                 end
  560.             end
  561.         end
  562.  
  563.         return false
  564.     end
  565.  
  566.     return true
  567. end
  568.  
  569. function dropUnwanted(drop)
  570.     drop = drop or turtle.dropDown
  571.  
  572.     for i = 1, 16 do
  573.         local name = getItemName(i)
  574.  
  575.         if (name ~= nil) and (isSapling(name) == false) and (isFuel(name) == false) then
  576.             select(i)
  577.             drop()
  578.         end
  579.     end
  580. end
  581.  
  582. function dropSaplings(drop)
  583.     drop = drop or turtle.drop
  584.  
  585.     for i = 1, 16 do
  586.         local name = getItemName(i)
  587.  
  588.         if isSapling(name) == true then
  589.             select(i)
  590.             drop()
  591.         end
  592.     end
  593. end
  594.  
  595. function getSaplings()
  596.     turnTo(saplingStorageDirection)
  597.     dropSaplings(turtle.drop)
  598.  
  599.     select(1)
  600.     while not turtle.suck(9 * 4) do
  601.         printSleep('missing saplings. to continue, please put saplings in the chest')
  602.     end
  603. end
  604.  
  605. function getFuel()
  606.     while true do
  607.         local name = getItemName(fuelSlot)
  608.         if (name == nil) or (isFuel(name) == true) then
  609.             break
  610.         else
  611.             printMessage('fuel slot('..fuelSlot..') is clogged, please remove all items from slot '..fuelSlot)
  612.         end
  613.     end
  614.    
  615.     hasAmount = turtle.getItemCount(fuelSlot)
  616.  
  617.     if hasAmount < 64 then
  618.         turnTo(fuelStorageDirection)
  619.         select(fuelSlot)
  620.  
  621.         while true do
  622.             turtle.suck(64 - hasAmount)
  623.             hasAmount = turtle.getItemCount(fuelSlot)
  624.  
  625.             if hasAmount >= minFuelToStart then
  626.                 break
  627.             else
  628.                 printSleep('missing '..(minFuelToStart - hasAmount)..' fuel. to continue, please put fuel in the chest')
  629.             end
  630.         end
  631.     end
  632. end
  633.  
  634. function restock(returnBack)
  635.     local previousPosition = table.shallowCopy(currentPosition)
  636.     local previousDirection = currentDirection
  637.  
  638.     moveTo(0, -4, 0, true, false)
  639.    
  640.     dropUnwanted(turtle.dropDown)
  641.     getSaplings()
  642.     getFuel()
  643.  
  644.     if returnBack == true then
  645.         moveTo(previousPosition.x, previousPosition.y, previousPosition.z)
  646.         turnTo(previousDirection)
  647.     end
  648. end
  649.  
  650. function placeSapling()
  651.     if selectSapling() == true then
  652.         turtle.place()
  653.     end
  654. end
  655.  
  656. function cutTree()
  657.     local _, data = turtle.inspect()
  658.  
  659.     if isWood(data.name) then
  660.         selectWood()
  661.         digForward(true)
  662.        
  663.         local deltaY = 0
  664.  
  665.         while true do
  666.             _, data = turtle.inspectUp()
  667.  
  668.             if isWood(data.name) then
  669.                 digUp()
  670.                 deltaY = deltaY + 1
  671.             else
  672.                 break
  673.             end
  674.         end
  675.  
  676.         for i = 1, deltaY do
  677.             moveDown(1, true)
  678.         end
  679.  
  680.         moveBack(1)
  681.     end
  682. end
  683.  
  684. function processSpace()
  685.     handleResources(true)
  686.  
  687.     turtle.suck()
  688.     cutTree()
  689.     placeSapling()
  690. end
  691.  
  692. function processRow(length)
  693.     for i = 1, length-1 do
  694.         processSpace()
  695.         turnRight()
  696.         moveForward()
  697.         turnLeft()
  698.     end
  699.  
  700.     processSpace()
  701. end
  702.  
  703. function persist()
  704.     loadData()
  705.  
  706.     if persisted == true then
  707.         printMessage('turtle successfully persisted')
  708.        
  709.         if ((math.abs(currentPosition.x) == 5) or (math.abs(currentPosition.z) == 5)) then
  710.             if turtle.detectUp() == false then
  711.                 moveUp()
  712.             end
  713.  
  714.             while true do
  715.                 local _, data = turtle.inspectUp()
  716.  
  717.                 if isWood(data.name) then
  718.                     digUp()
  719.                 else
  720.                     break
  721.                 end
  722.             end
  723.         end    
  724.  
  725.         handleResources(false)
  726.         moveTo(-4, 0, 4, true)
  727.         turnTo(4)
  728.     end
  729. end
  730.  
  731. function main()
  732.     persist()
  733.  
  734.     while true do
  735.         processRow(9)
  736.         turnRight()
  737.     end
  738. end
  739.  
  740. main()
Add Comment
Please, Sign In to add comment