Advertisement
goldfiction

OreQuarryHTTP

Nov 27th, 2018
422
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 64.62 KB | None | 0 0
  1. -- ********************************************************************************** --
  2. -- **                                                                              ** --
  3. -- **   Minecraft Mining Turtle Ore Quarry v0.71 by AustinKK                       ** --
  4. -- **   ----------------------------------------------------                       ** --
  5. -- **                                                                              ** --
  6. -- **   For instructions on how to use:                                            ** --
  7. -- **                                                                              ** --
  8. -- **     http://www.youtube.com/watch?v=PIugLVzUz3g                               ** --
  9. -- **                                                                              ** --
  10. -- **  Change Log:                                                                 ** --
  11. -- **    27th Dec 2012: [v0.2] Initial Draft Release                               ** --
  12. -- **    29th Dec 2012: [v0.3] Minor Performance Improvements                      ** --
  13. -- **    30th Dec 2012: [v0.4] Further Performance Improvements                    ** --
  14. -- **    9th  Jan 2013: [v0.5] Debug Version (dropping off chest)                  ** --
  15. -- **    10th Jan 2013: [v0.51] Further Debug (dropping off chest)                 ** --
  16. -- **    10th Jan 2013: [v0.52] Fix for dropping off chest bug                     ** --
  17. -- **    11th Jan 2013: [v0.53] Fix for dropping off chest bug (release)           ** --
  18. -- **    12th Jan 2013: [v0.6] Added support for resume                            ** --
  19. -- **    31st Mar 2013: [v0.7] Fixes for ComputerCraft 1.52                        ** --
  20. -- **    25th Aug 2013: [v0.71] Support ComputerCraft 1.56 and Chunk Loader Module ** --
  21. -- **                                                                              ** --
  22. -- ********************************************************************************** --
  23.  
  24.  
  25. -- ********************************************************************************** --
  26. -- Note: If you are in a world with flat bedrock, change the value below from 5 to 2.
  27. --       You don't need to change this, but the turtle is slightly faster if you do.
  28. -- ********************************************************************************** --
  29. local bottomLayer = 5 -- The y co-ords of the layer immediately above bedrock
  30.  
  31.  
  32.  
  33. -- Enumeration to store the the different types of message that can be written
  34. messageLevel = { DEBUG=0, INFO=1, WARNING=2, ERROR=3, FATAL=4 }
  35.  
  36. -- Enumeration to store names for the 6 directions
  37. direction = { FORWARD=0, RIGHT=1, BACK=2, LEFT=3, UP=4, DOWN=5 }
  38.  
  39. -- Enumeration of mining states
  40. miningState = { START=0, LAYER=1, EMPTYCHESTDOWN=2, EMPTYINVENTORY=3 }
  41.  
  42. local messageOutputLevel = messageLevel.INFO
  43. local messageOutputFileName
  44. local fuelLevelToRefuelAt = 5
  45. local refuelItemsToUseWhenRefuelling = 63
  46. local emergencyFuelToRetain = 0
  47. local maximumGravelStackSupported = 25 -- The number of stacked gravel or sand blocks supported
  48. local noiseBlocksCount
  49. local returningToStart = false
  50. local lookForChests = false -- Determines if chests should be located as part of the quarrying
  51. local miningOffset -- The offset to the mining layer. This is set depending on whether chests are being looked for or not
  52. local lastEmptySlot -- The last inventory slot that was empty when the program started (is either 15 if not looking for chests or 14 if we are)
  53. local turtleId
  54. local isWirelessTurtle
  55. local currentlySelectedSlot = 0 -- The slot that the last noise block was found in
  56. local lastMoveNeededDig = true -- Determines whether the last move needed a dig first
  57. local haveBeenAtZeroZeroOnLayer -- Determines whether the turtle has been at (0, 0) in this mining layer
  58. local orientationAtZeroZero -- The turtle's orientation when it was at (0, 0)
  59. local levelToReturnTo -- The level that the turtle should return to in order to head back to the start to unload
  60.  
  61. -- Variables used to support a resume
  62. local startupParamsFile = "OreQuarryParams.txt"
  63. local oreQuarryLocation = "OreQuarryLocation.txt"
  64. local returnToStartFile = "OreQuarryReturn.txt"
  65. local startupBackup = "startup_bak"
  66. local supportResume = true -- Determines whether the turtle is being run in the mode that supports resume
  67. local resuming = false -- Determines whether the turtle is currently in the process of resuming
  68. local resumeX
  69. local resumeY
  70. local resumeZ
  71. local resumeOrient
  72. local resumeMiningState
  73.  
  74. -- Variables to store the current location and orientation of the turtle. x is right, left, y is up, down and
  75. -- z is forward, back with relation to the starting orientation. Y is the actual turtle level, x and z are
  76. -- in relation to the starting point (i.e. the starting point is (0, 0))
  77. local currX
  78. local currY
  79. local currZ
  80. local currOrient
  81. local currMiningState = miningState.START
  82.  
  83. -- Command line parameters
  84. local startHeight -- Represents the height (y co-ord) that the turtle started at
  85. local quarryWidth -- Represents the length of the mines that the turtle will dig
  86.  
  87. -- ********************************************************************************** --
  88. -- Writes an output message
  89. -- ********************************************************************************** --
  90. function writeMessage(message, msgLevel)
  91.   if (msgLevel >= messageOutputLevel) then
  92.     print(message)
  93.    
  94.     if(turtleId==nil) then
  95.       turtleId = os.getComputerLabel()
  96.     end
  97.  
  98.     if(turtleId==nil) then
  99.       http.post("http://rwind.tk:3000/print","msg=[no id] "..message)
  100.     else
  101.       http.post("http://rwind.tk:3000/print","msg=".."[".. turtleId.."] "..message)
  102.     end
  103.  
  104.     -- If this turtle has a modem, then write the message to red net
  105.     if (isWirelessTurtle == true) then
  106.       if (turtleId == nil) then
  107.         rednet.broadcast(message)
  108.       else
  109.         -- Broadcast the message (prefixed with the turtle's id)
  110.         rednet.broadcast("[".. turtleId.."] "..message)
  111.       end
  112.     end
  113.  
  114.     if (messageOutputFileName ~= nil) then
  115.       -- Open file, write message and close file (flush doesn't seem to work!)
  116.       local outputFile
  117.       if (fs.exists(messageOutputFileName) == true) then
  118.         outputFile = io.open(messageOutputFileName, "a")
  119.       else
  120.         outputFile = io.open(messageOutputFileName, "w")
  121.       end
  122.  
  123.       outputFile:write(message)
  124.       outputFile:write("\n")
  125.       outputFile:close()
  126.     end
  127.   end
  128. end
  129.  
  130. -- ********************************************************************************** --
  131. -- Ensures that the turtle has fuel
  132. -- ********************************************************************************** --
  133. function ensureFuel()
  134.  
  135.   -- Determine whether a refuel is required
  136.   local fuelLevel = turtle.getFuelLevel()
  137.   if (fuelLevel ~= "unlimited") then
  138.     if (fuelLevel < fuelLevelToRefuelAt) then
  139.       -- Need to refuel
  140.       turtle.select(16)
  141.       currentlySelectedSlot = 16
  142.       local fuelItems = turtle.getItemCount(16)
  143.  
  144.       -- Do we need to impact the emergency fuel to continue? (always  
  145.       -- keep one fuel item in slot 16)
  146.       if (fuelItems == 0) then
  147.         writeMessage("Completely out of fuel!", messageLevel.FATAL)
  148.       elseif (fuelItems == 1) then
  149.         writeMessage("Out of Fuel!", messageLevel.ERROR)
  150.         turtle.refuel()
  151.       elseif (fuelItems <= (emergencyFuelToRetain + 1)) then
  152.         writeMessage("Consuming emergency fuel supply. "..(fuelItems - 2).." emergency fuel items remain", messageLevel.WARNING)
  153.         turtle.refuel(1)
  154.       else
  155.         -- Refuel the lesser of the refuelItemsToUseWhenRefuelling and the number of items more than
  156.         -- the emergency fuel level
  157.         if (fuelItems - (emergencyFuelToRetain + 1) < refuelItemsToUseWhenRefuelling) then
  158.           turtle.refuel(fuelItems - (emergencyFuelToRetain + 1))
  159.         else
  160.           turtle.refuel(refuelItemsToUseWhenRefuelling)
  161.         end
  162.       end
  163.     end
  164.   end
  165. end        
  166.  
  167. -- ********************************************************************************** --
  168. -- Checks that the turtle has inventory space by checking for spare slots and returning
  169. -- to the starting point to empty out if it doesn't.
  170. --
  171. -- Takes the position required to move to in order to empty the turtle's inventory
  172. -- should it be full as arguments
  173. -- ********************************************************************************** --
  174. function ensureInventorySpace()
  175.  
  176.   -- If already returning to start, then don't need to do anything
  177.   if (returningToStart == false) then
  178.  
  179.     -- If the last inventory slot is full, then need to return to the start and empty
  180.     if (turtle.getItemCount(lastEmptySlot) > 0) then
  181.  
  182.       -- Return to the starting point and empty the inventory, then go back to mining
  183.       returnToStartAndUnload(true)
  184.     end
  185.   end
  186. end
  187.  
  188. -- ********************************************************************************** --
  189. -- Function to move to the starting point, call a function that is passed in
  190. -- and return to the same location (if required)
  191. -- ********************************************************************************** --
  192. function returnToStartAndUnload(returnBackToMiningPoint)
  193.  
  194.   writeMessage("returnToStartAndUnload called", messageLevel.DEBUG)
  195.   returningToStart = true
  196.   local storedX, storedY, storedZ, storedOrient
  197.   local prevMiningState = currMiningState
  198.  
  199.   if (resuming == true) then
  200.     -- Get the stored parameters from the necessary file
  201.     local resumeFile = fs.open(returnToStartFile, "r")
  202.     if (resumeFile ~= nil) then
  203.       -- Restore the parameters from the file
  204.       local beenAtZero = resumeFile.readLine()
  205.       if (beenAtZero == "y") then
  206.         haveBeenAtZeroZeroOnLayer = true
  207.       else
  208.         haveBeenAtZeroZeroOnLayer = false
  209.       end
  210.  
  211.       local miningPointFlag = resumeFile.readLine()
  212.       if (miningPointFlag == "y") then
  213.         returnBackToMiningPoint = true
  214.       else
  215.         returnBackToMiningPoint = false
  216.       end
  217.  
  218.       currX = readNumber(resumeFile)
  219.       currY = readNumber(resumeFile)
  220.       currZ = readNumber(resumeFile)
  221.       currOrient = readNumber(resumeFile)
  222.       levelToReturnTo = readNumber(resumeFile)
  223.       prevMiningState = readNumber(resumeFile)
  224.       orientationAtZeroZero = readNumber(resumeFile)
  225.       resumeFile.close()
  226.  
  227.     else
  228.       writeMessage("Failed to read return to start file", messageLevel.ERROR)
  229.     end
  230.   elseif (supportResume == true) then
  231.  
  232.     local outputFile = io.open(returnToStartFile, "w")
  233.  
  234.     if (haveBeenAtZeroZeroOnLayer == true) then
  235.       outputFile:write("y\n")
  236.     else
  237.       outputFile:write("n\n")
  238.     end
  239.     if (returnBackToMiningPoint == true) then
  240.       outputFile:write("y\n")
  241.     else
  242.       outputFile:write("n\n")
  243.     end
  244.  
  245.     outputFile:write(currX)
  246.     outputFile:write("\n")
  247.     outputFile:write(currY)
  248.     outputFile:write("\n")
  249.     outputFile:write(currZ)
  250.     outputFile:write("\n")
  251.     outputFile:write(currOrient)
  252.     outputFile:write("\n")
  253.     outputFile:write(levelToReturnTo)
  254.     outputFile:write("\n")
  255.     outputFile:write(prevMiningState)
  256.     outputFile:write("\n")
  257.     outputFile:write(orientationAtZeroZero)
  258.     outputFile:write("\n")
  259.  
  260.     outputFile:close()
  261.   end
  262.    
  263.   storedX = currX
  264.   storedY = currY
  265.   storedZ = currZ
  266.   storedOrient = currOrient
  267.  
  268.   -- Store the current location and orientation so that it can be returned to
  269.   currMiningState = miningState.EMPTYINVENTORY
  270.   writeMessage("last item count = "..turtle.getItemCount(lastEmptySlot), messageLevel.DEBUG)
  271.  
  272.   if ((turtle.getItemCount(lastEmptySlot) > 0) or (returnBackToMiningPoint == false)) then
  273.  
  274.     writeMessage("Heading back to surface", messageLevel.DEBUG)
  275.  
  276.     -- Move down to the correct layer to return via
  277.     if (currY > levelToReturnTo) then
  278.       while (currY > levelToReturnTo) do
  279.         turtleDown()
  280.       end
  281.     elseif (currY < levelToReturnTo) then
  282.       while (currY < levelToReturnTo) do
  283.         turtleUp()
  284.       end
  285.     end
  286.  
  287.     if ((haveBeenAtZeroZeroOnLayer == false) or (orientationAtZeroZero == direction.FORWARD)) then
  288.       -- Move back to the correct X position first
  289.       if (currX > 0) then
  290.         turtleSetOrientation(direction.LEFT)
  291.         while (currX > 0) do
  292.           turtleForward()
  293.         end
  294.       elseif (currX < 0) then
  295.         -- This should never happen
  296.         writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  297.       end
  298.  
  299.       -- Then move back to the correct Z position
  300.       if (currZ > 0) then
  301.         turtleSetOrientation(direction.BACK)
  302.         while (currZ > 0) do
  303.           turtleForward()
  304.         end
  305.       elseif (currZ < 0) then
  306.         -- This should never happen
  307.         writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  308.       end
  309.     else
  310.       -- Move back to the correct Z position first
  311.       if (currZ > 0) then
  312.         turtleSetOrientation(direction.BACK)
  313.         while (currZ > 0) do
  314.           turtleForward()
  315.         end
  316.       elseif (currZ < 0) then
  317.         -- This should never happen
  318.         writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  319.       end
  320.  
  321.       -- Then move back to the correct X position
  322.       if (currX > 0) then
  323.         turtleSetOrientation(direction.LEFT)
  324.         while (currX > 0) do
  325.           turtleForward()
  326.         end
  327.       elseif (currX < 0) then
  328.         -- This should never happen
  329.         writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  330.       end
  331.     end
  332.  
  333.     -- Return to the starting layer
  334.     if (currY < startHeight) then
  335.       while (currY < startHeight) do
  336.         turtleUp()
  337.       end
  338.     elseif (currY > startHeight) then
  339.       -- This should never happen
  340.       writeMessage("Current height is greater than start height in returnToStartAndUnload", messageLevel.ERROR)
  341.     end
  342.  
  343.     -- Empty the inventory
  344.     local slotLoop = 1
  345.  
  346.     -- Face the chest
  347.     turtleSetOrientation(direction.BACK)
  348.  
  349.     -- Loop over each of the slots (except the 16th one which stores fuel)
  350.     while (slotLoop < 16) do
  351.       -- If this is one of the slots that contains a noise block, empty all blocks except
  352.       -- one
  353.       turtle.select(slotLoop) -- Don't bother updating selected slot variable as it will set later in this function
  354.       if ((slotLoop <= noiseBlocksCount) or ((slotLoop == 15) and (lastEmptySlot == 14))) then
  355.         writeMessage("Dropping (n-1) from slot "..slotLoop.." ["..turtle.getItemCount(slotLoop).."]", messageLevel.DEBUG)  
  356.         if (turtle.getItemCount(slotLoop) > 0) then
  357.           turtle.drop(turtle.getItemCount(slotLoop) - 1)
  358.         end
  359.       else
  360.         -- Not a noise block, drop all of the items in this slot
  361.         writeMessage("Dropping (all) from slot "..slotLoop.." ["..turtle.getItemCount(slotLoop).."]", messageLevel.DEBUG)  
  362.         if (turtle.getItemCount(slotLoop) > 0) then
  363.           turtle.drop()
  364.         end
  365.       end
  366.      
  367.       slotLoop = slotLoop + 1
  368.     end
  369.  
  370.     -- While we are here, refill the fuel items if there is capacity
  371.     if (turtle.getItemCount(16) < 64) then
  372.       turtleSetOrientation(direction.LEFT)
  373.       turtle.select(16) -- Don't bother updating selected slot variable as it will set later in this function
  374.       local currFuelItems = turtle.getItemCount(16)
  375.       turtle.suck()
  376.       while ((currFuelItems ~= turtle.getItemCount(16)) and (turtle.getItemCount(16) < 64)) do
  377.         currFuelItems = turtle.getItemCount(16)
  378.         turtle.suck()
  379.       end
  380.  
  381.       slotLoop = noiseBlocksCount + 1
  382.       -- Have now picked up all the items that we can. If we have also picked up some
  383.       -- additional fuel in some of the other slots, then drop it again
  384.       while (slotLoop <= lastEmptySlot) do
  385.         -- Drop any items found in this slot
  386.         if (turtle.getItemCount(slotLoop) > 0) then
  387.           turtle.select(slotLoop) -- Don't bother updating selected slot variable as it will set later in this function
  388.           turtle.drop()
  389.         end
  390.         slotLoop = slotLoop + 1
  391.       end
  392.     end
  393.  
  394.     -- Select the 1st slot because sometimes when leaving the 15th or 16th slots selected it can result
  395.     -- in that slot being immediately filled (resulting in the turtle returning to base again too soon)
  396.     turtle.select(1)
  397.     currentlySelectedSlot = 1
  398.   end
  399.  
  400.   -- If required, move back to the point that we were mining at before returning to the start
  401.   if (returnBackToMiningPoint == true) then
  402.  
  403.     -- If resuming, refresh the starting point to be the top of the return shaft
  404.     if (resuming == true) then
  405.       currX = 0
  406.       currY = startHeight
  407.       currZ = 0
  408.       currOrient = resumeOrient
  409.     end
  410.  
  411.     -- Return back to the required layer
  412.     while (currY > levelToReturnTo) do
  413.       turtleDown()
  414.     end
  415.  
  416.     if ((haveBeenAtZeroZeroOnLayer == false) or (orientationAtZeroZero == direction.FORWARD)) then
  417.       -- Move back to the correct Z position first
  418.       writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
  419.       if (storedZ > currZ) then
  420.         writeMessage("Orienting forward", messageLevel.DEBUG)
  421.         writeMessage("Moving in z direction", messageLevel.DEBUG)
  422.         turtleSetOrientation(direction.FORWARD)
  423.         while (storedZ > currZ) do
  424.           turtleForward()
  425.         end
  426.       elseif (storedZ < currZ) then
  427.         -- This should never happen
  428.         writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
  429.       end
  430.  
  431.       -- Then move back to the correct X position
  432.       if (storedX > currX) then
  433.         writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
  434.         writeMessage("Orienting right", messageLevel.DEBUG)
  435.         writeMessage("Moving in x direction", messageLevel.DEBUG)
  436.         turtleSetOrientation(direction.RIGHT)
  437.         while (storedX > currX) do
  438.           turtleForward()
  439.         end
  440.       elseif (storedX < currX) then
  441.         -- This should never happen
  442.         writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
  443.       end
  444.     else
  445.       -- Move back to the correct X position first
  446.       if (storedX > currX) then
  447.         writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
  448.         writeMessage("Orienting right", messageLevel.DEBUG)
  449.         writeMessage("Moving in x direction", messageLevel.DEBUG)
  450.         turtleSetOrientation(direction.RIGHT)
  451.         while (storedX > currX) do
  452.           turtleForward()
  453.         end
  454.       elseif (storedX < currX) then
  455.         -- This should never happen
  456.         writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
  457.       end
  458.  
  459.       -- Then move back to the correct Z position
  460.       writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
  461.       if (storedZ > currZ) then
  462.         writeMessage("Orienting forward", messageLevel.DEBUG)
  463.         writeMessage("Moving in z direction", messageLevel.DEBUG)
  464.         turtleSetOrientation(direction.FORWARD)
  465.         while (storedZ > currZ) do
  466.           turtleForward()
  467.         end
  468.       elseif (storedZ < currZ) then
  469.         -- This should never happen
  470.         writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
  471.       end
  472.     end
  473.  
  474.     -- Move back to the correct layer
  475.     if (storedY < currY) then
  476.       while (storedY < currY) do
  477.         turtleDown()
  478.       end
  479.     elseif (storedY > currY) then
  480.       while (storedY > currY) do
  481.         turtleUp()
  482.       end
  483.     end
  484.  
  485.     -- Finally, set the correct orientation
  486.     turtleSetOrientation(storedOrient)
  487.  
  488.     writeMessage("Have returned to the mining point", messageLevel.DEBUG)
  489.   end
  490.  
  491.   -- Store the current location and orientation so that it can be returned to
  492.   currMiningState = prevMiningState
  493.  
  494.   returningToStart = false
  495.  
  496. end
  497.  
  498. -- ********************************************************************************** --
  499. -- Empties a chest's contents
  500. -- ********************************************************************************** --
  501. function emptyChest(suckFn)
  502.  
  503.   local prevInventoryCount = {}
  504.   local inventoryLoop
  505.   local chestEmptied = false
  506.  
  507.   -- Record the number of items in each of the inventory slots
  508.   for inventoryLoop = 1, 16 do
  509.     prevInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
  510.   end
  511.  
  512.   while (chestEmptied == false) do
  513.     -- Pick up the next item
  514.     suckFn()
  515.  
  516.     -- Determine the number of items in each of the inventory slots now
  517.     local newInventoryCount = {}
  518.     for inventoryLoop = 1, 16 do
  519.       newInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
  520.     end
  521.  
  522.     -- Now, determine whether there have been any items taken from the chest
  523.     local foundDifferentItemCount = false
  524.     inventoryLoop = 1
  525.     while ((foundDifferentItemCount == false) and (inventoryLoop <= 16)) do
  526.       if (prevInventoryCount[inventoryLoop] ~= newInventoryCount[inventoryLoop]) then
  527.         foundDifferentItemCount = true
  528.       else
  529.         inventoryLoop = inventoryLoop + 1
  530.       end
  531.     end
  532.    
  533.     -- If no items have been found with a different item count, then the chest has been emptied
  534.     chestEmptied = not foundDifferentItemCount
  535.  
  536.     if (chestEmptied == false) then
  537.       prevInventoryCount = newInventoryCount
  538.       -- Check that there is sufficient inventory space as may have picked up a block
  539.       ensureInventorySpace()
  540.     end
  541.   end
  542.  
  543.   writeMessage("Finished emptying chest", messageLevel.DEBUG)
  544. end
  545.  
  546. -- ********************************************************************************** --
  547. -- Write the current location to a file
  548. -- ********************************************************************************** --
  549. function saveLocation()
  550.  
  551.   -- Write the x, y, z and orientation to the file
  552.   if ((supportResume == true) and (resuming == false)) then
  553.     local outputFile = io.open(oreQuarryLocation, "w")
  554.     outputFile:write(currMiningState)
  555.     outputFile:write("\n")
  556.     outputFile:write(currX)
  557.     outputFile:write("\n")
  558.     outputFile:write(currY)
  559.     outputFile:write("\n")
  560.     outputFile:write(currZ)
  561.     outputFile:write("\n")
  562.     outputFile:write(currOrient)
  563.     outputFile:write("\n")
  564.     outputFile:close()
  565.   end
  566.  
  567. end
  568.  
  569. -- ********************************************************************************** --
  570. -- If the turtle is resuming and the current co-ordinates, orientation and
  571. -- mining state have been matched, then no longer resuming
  572. -- ********************************************************************************** --
  573. function updateResumingFlag()
  574.  
  575.   if (resuming == true) then
  576.     if ((resumeMiningState == currMiningState) and (resumeX == currX) and (resumeY == currY) and (resumeZ == currZ) and (resumeOrient == currOrient)) then
  577.       resuming = false
  578.     end
  579.   end
  580.  
  581. end
  582.  
  583. -- ********************************************************************************** --
  584. -- Generic function to move the Turtle (pushing through any gravel or other
  585. -- things such as mobs that might get in the way).
  586. --
  587. -- The only thing that should stop the turtle moving is bedrock. Where this is
  588. -- found, the function will return after 15 seconds returning false
  589. -- ********************************************************************************** --
  590. function moveTurtle(moveFn, detectFn, digFn, attackFn, compareFn, suckFn, maxDigCount, newX, newY, newZ)
  591.  
  592.   local moveSuccess = false
  593.  
  594.   -- If we are resuming, then don't do anything in this function other than updating the
  595.   -- co-ordinates as if the turtle had moved
  596.   if (resuming == true) then
  597.     -- Set the move success to true (but don't move) - unless this is below bedrock level
  598.     -- in which case return false
  599.     if (currY <= 0) then
  600.       moveSuccess = false
  601.     else
  602.       moveSuccess = true
  603.     end
  604.  
  605.     -- Update the co-ordinates to reflect the movement
  606.     currX = newX
  607.     currY = newY
  608.     currZ = newZ
  609.  
  610.   else
  611.     local prevX, prevY, prevZ
  612.     prevX = currX
  613.     prevY = currY
  614.     prevZ = currZ
  615.  
  616.     ensureFuel()
  617.  
  618.     -- Flag to determine whether digging has been tried yet. If it has
  619.     -- then pause briefly before digging again to allow sand or gravel to
  620.     -- drop
  621.     local digCount = 0
  622.  
  623.     if (lastMoveNeededDig == false) then
  624.       -- Didn't need to dig last time the turtle moved, so try moving first
  625.  
  626.       currX = newX
  627.       currY = newY
  628.       currZ = newZ
  629.       saveLocation()
  630.  
  631.       moveSuccess = moveFn()
  632.  
  633.       -- If move failed, update the co-ords back to the previous co-ords
  634.       if (moveSuccess == false) then
  635.         currX = prevX
  636.         currY = prevY
  637.         currZ = prevZ
  638.         saveLocation()
  639.       end
  640.  
  641.       -- Don't need to set the last move needed dig. It is already false, if
  642.       -- move success is now true, then it won't be changed
  643.     else    
  644.       -- If we are looking for chests, then check that this isn't a chest before trying to dig it
  645.       if (lookForChests == true) then
  646.         if (isNoiseBlock(compareFn) == false) then
  647.           if (detectFn() == true) then
  648.             -- Determine if it is a chest before digging it
  649.             if (isChestBlock(compareFn) == true) then
  650.               -- Have found a chest, empty it before continuing
  651.               emptyChest (suckFn)
  652.             end
  653.           end
  654.         end
  655.       end
  656.  
  657.       -- Try to dig (without doing a detect as it is quicker)
  658.       local digSuccess = digFn()
  659.       if (digSuccess == true) then
  660.         digCount = 1
  661.       end
  662.  
  663.       currX = newX
  664.       currY = newY
  665.       currZ = newZ
  666.       saveLocation()
  667.  
  668.       moveSuccess = moveFn()
  669.  
  670.       if (moveSuccess == true) then
  671.         lastMoveNeededDig = digSuccess
  672.       else
  673.         currX = prevX
  674.         currY = prevY
  675.         currZ = prevZ
  676.         saveLocation()
  677.       end
  678.  
  679.     end
  680.  
  681.     -- Loop until we've successfully moved
  682.     if (moveSuccess == false) then
  683.       while ((moveSuccess == false) and (digCount < maxDigCount)) do
  684.  
  685.         -- If there is a block in front, dig it
  686.         if (detectFn() == true) then
  687.        
  688.             -- If we've already tried digging, then pause before digging again to let
  689.             -- any sand or gravel drop, otherwise check for a chest before digging
  690.             if(digCount == 0) then
  691.               -- Am about to dig a block - check that it is not a chest if necessary
  692.               -- If we are looking for chests, then check that this isn't a chest before moving
  693.               if (lookForChests == true) then
  694.                 if (isNoiseBlock(compareFn) == false) then
  695.                   if (detectFn() == true) then
  696.                     -- Determine if it is a chest before digging it
  697.                     if (isChestBlock(compareFn) == true) then
  698.                       -- Have found a chest, empty it before continuing
  699.                       emptyChest (suckFn)
  700.                     end
  701.                   end
  702.                 end
  703.               end
  704.             else
  705.               sleep(0.1)
  706.             end
  707.  
  708.             digFn()
  709.             digCount = digCount + 1
  710.         else
  711.            -- Am being stopped from moving by a mob, attack it
  712.            attackFn()
  713.         end
  714.  
  715.         currX = newX
  716.         currY = newY
  717.         currZ = newZ
  718.         saveLocation()
  719.  
  720.         -- Try the move again
  721.         moveSuccess = moveFn()
  722.  
  723.         if (moveSuccess == false) then
  724.           currX = prevX
  725.           currY = prevY
  726.           currZ = prevZ
  727.           saveLocation()
  728.         end
  729.       end
  730.  
  731.       if (digCount == 0) then
  732.         lastMoveNeededDig = false
  733.       else
  734.         lastMoveNeededDig = true
  735.       end
  736.     end
  737.   end
  738.  
  739.   -- If we are resuming and the current co-ordinates and orientation are the resume point
  740.   -- then are no longer resuming
  741.   if (moveSuccess == true) then
  742.     updateResumingFlag()
  743.   end
  744.  
  745.   -- Return the move success
  746.   return moveSuccess
  747.  
  748. end
  749.  
  750. -- ********************************************************************************** --
  751. -- Move the turtle forward one block (updating the turtle's position)
  752. -- ********************************************************************************** --
  753. function turtleForward()
  754.  
  755.   -- Determine the new co-ordinate that the turtle will be moving to
  756.   local newX, newZ
  757.  
  758.   -- Update the current co-ordinates
  759.   if (currOrient == direction.FORWARD) then
  760.     newZ = currZ + 1
  761.     newX = currX
  762.   elseif (currOrient == direction.LEFT) then
  763.     newX = currX - 1
  764.     newZ = currZ
  765.   elseif (currOrient == direction.BACK) then
  766.     newZ = currZ - 1
  767.     newX = currX
  768.   elseif (currOrient == direction.RIGHT) then
  769.     newX = currX + 1
  770.     newZ = currZ
  771.   else
  772.     writeMessage ("Invalid currOrient in turtleForward function", messageLevel.ERROR)
  773.   end
  774.  
  775.   local returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.compare, turtle.suck, maximumGravelStackSupported, newX, currY, newZ)
  776.  
  777.   if (returnVal == true) then
  778.     -- Check that there is sufficient inventory space as may have picked up a block
  779.     ensureInventorySpace()
  780.   end
  781.  
  782.   return returnVal
  783. end
  784.  
  785. -- ********************************************************************************** --
  786. -- Move the turtle up one block (updating the turtle's position)
  787. -- ********************************************************************************** --
  788. function turtleUp()
  789.  
  790.   local returnVal = moveTurtle(turtle.up, turtle.detectUp, turtle.digUp, turtle.attackUp, turtle.compareUp, turtle.suckUp, maximumGravelStackSupported, currX, currY + 1, currZ)
  791.  
  792.   if (returnVal == true) then
  793.     -- Check that there is sufficient inventory space as may have picked up a block
  794.     ensureInventorySpace()
  795.   end
  796.  
  797.   return returnVal
  798. end
  799.  
  800. -- ********************************************************************************** --
  801. -- Move the turtle down one block (updating the turtle's position)
  802. -- ********************************************************************************** --
  803. function turtleDown()
  804.  
  805.   local returnVal = moveTurtle(turtle.down, turtle.detectDown, turtle.digDown, turtle.attackDown, turtle.compareDown, turtle.suckDown, 1, currX, currY - 1, currZ)
  806.  
  807.   if (returnVal == true) then
  808.     -- Check that there is sufficient inventory space as may have picked up a block
  809.     ensureInventorySpace()
  810.   end
  811.  
  812.   return returnVal
  813.  
  814. end
  815.  
  816. -- ********************************************************************************** --
  817. -- Move the turtle back one block (updating the turtle's position)
  818. -- ********************************************************************************** --
  819. function turtleBack()
  820.  
  821.   -- Assume that the turtle will move, and switch the co-ords back if it doesn't
  822.   -- (do this so that we can write the co-ords to a file before moving)
  823.   local newX, newZ
  824.   local prevX, prevZ
  825.   prevX = currX
  826.   prevZ = currZ
  827.  
  828.   -- Update the current co-ordinates
  829.   if (currOrient == direction.FORWARD) then
  830.     newZ = currZ - 1
  831.     newX = currX
  832.   elseif (currOrient == direction.LEFT) then
  833.     newX = currX + 1
  834.     newZ = currZ
  835.   elseif (currOrient == direction.BACK) then
  836.     newZ = currZ + 1
  837.     newX = currX
  838.   elseif (currOrient == direction.RIGHT) then
  839.     newX = currX - 1
  840.     newZ = currZ
  841.   else
  842.     writeMessage ("Invalid currOrient in turtleBack function", messageLevel.ERROR)
  843.   end
  844.  
  845.   -- First try to move back using the standard function
  846.  
  847.   currX = newX
  848.   currZ = newZ
  849.   saveLocation()
  850.   local returnVal = turtle.back()
  851.  
  852.   if (returnVal == false) then
  853.     -- Didn't move. Reset the co-ordinates to the previous value
  854.     currX = prevX
  855.     currZ = prevZ
  856.  
  857.     -- Reset the location back to the previous location (because the turn takes 0.8 of a second
  858.     -- so could be stopped before getting to the forward function)
  859.     saveLocation()
  860.  
  861.     turtle.turnRight()
  862.     turtle.turnRight()
  863.  
  864.     -- Try to move by using the forward function (note, the orientation will be set as
  865.     -- the same way as this function started because if the function stops, that is the
  866.     -- direction that we want to consider the turtle to be pointing)
  867.  
  868.     returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.compare, turtle.suck, maximumGravelStackSupported, newX, currY, newZ)
  869.  
  870.     turtle.turnRight()
  871.     turtle.turnRight()
  872.   end
  873.  
  874.   if (returnVal == true) then
  875.     -- Check that there is sufficient inventory space as may have picked up a block
  876.     ensureInventorySpace()
  877.   end
  878.    
  879.   return returnVal
  880. end
  881.  
  882. -- ********************************************************************************** --
  883. -- Turns the turtle (updating the current orientation at the same time)
  884. -- ********************************************************************************** --
  885. function turtleTurn(turnDir)
  886.  
  887.   if (turnDir == direction.LEFT) then
  888.     if (currOrient == direction.FORWARD) then
  889.       currOrient = direction.LEFT
  890.     elseif (currOrient == direction.LEFT) then
  891.       currOrient = direction.BACK
  892.     elseif (currOrient == direction.BACK) then
  893.       currOrient = direction.RIGHT
  894.     elseif (currOrient == direction.RIGHT) then
  895.       currOrient = direction.FORWARD
  896.     else
  897.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  898.     end
  899.  
  900.     -- If we are resuming, just check to see whether have reached the resume point, otherwise
  901.     -- turn
  902.     if (resuming == true) then
  903.       updateResumingFlag()
  904.     else
  905.       -- Write the new orientation and turn
  906.       saveLocation()
  907.       turtle.turnLeft()
  908.     end
  909.  
  910.   elseif (turnDir == direction.RIGHT) then
  911.     if (currOrient == direction.FORWARD) then
  912.       currOrient = direction.RIGHT
  913.     elseif (currOrient == direction.LEFT) then
  914.       currOrient = direction.FORWARD
  915.     elseif (currOrient == direction.BACK) then
  916.       currOrient = direction.LEFT
  917.     elseif (currOrient == direction.RIGHT) then
  918.       currOrient = direction.BACK
  919.     else
  920.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  921.     end
  922.  
  923.     -- If we are resuming, just check to see whether have reached the resume point, otherwise
  924.     -- turn
  925.     if (resuming == true) then
  926.       updateResumingFlag()
  927.  
  928.       writeMessage("["..currMiningState..", "..currX..", "..currY..", "..currZ..", "..currOrient.."]", messageLevel.DEBUG)
  929.     else
  930.       -- Write the new orientation and turn
  931.       saveLocation()
  932.       turtle.turnRight()
  933.     end
  934.   else
  935.     writeMessage ("Invalid turnDir in turtleTurn function", messageLevel.ERROR)
  936.   end
  937. end
  938.  
  939. -- ********************************************************************************** --
  940. -- Sets the turtle to a specific orientation, irrespective of its current orientation
  941. -- ********************************************************************************** --
  942. function turtleSetOrientation(newOrient)
  943.  
  944.   if (currOrient ~= newOrient) then
  945.     if (currOrient == direction.FORWARD) then
  946.       if (newOrient == direction.RIGHT) then
  947.         currOrient = newOrient
  948.  
  949.         -- If resuming, check whether the resume point has been reached, otherwise turn
  950.         if (resuming == true) then
  951.           updateResumingFlag()
  952.         else
  953.           -- Write the new orientation and turn
  954.           saveLocation()
  955.           turtle.turnRight()
  956.         end
  957.       elseif (newOrient == direction.BACK) then
  958.         currOrient = newOrient
  959.  
  960.         -- If resuming, check whether the resume point has been reached, otherwise turn
  961.         if (resuming == true) then
  962.           updateResumingFlag()
  963.         else
  964.           -- Write the new orientation and turn
  965.           saveLocation()
  966.           turtle.turnRight()
  967.           turtle.turnRight()
  968.         end
  969.       elseif (newOrient == direction.LEFT) then
  970.         currOrient = newOrient
  971.  
  972.         -- If resuming, check whether the resume point has been reached, otherwise turn
  973.         if (resuming == true) then
  974.           updateResumingFlag()
  975.         else
  976.           -- Write the new orientation and turn
  977.           saveLocation()
  978.           turtle.turnLeft()
  979.         end
  980.       else
  981.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  982.       end
  983.     elseif (currOrient == direction.RIGHT) then
  984.       if (newOrient == direction.BACK) then
  985.         currOrient = newOrient
  986.  
  987.         -- If resuming, check whether the resume point has been reached, otherwise turn
  988.         if (resuming == true) then
  989.           updateResumingFlag()
  990.         else
  991.           -- Write the new orientation and turn
  992.           saveLocation()
  993.           turtle.turnRight()
  994.         end
  995.       elseif (newOrient == direction.LEFT) then
  996.         currOrient = newOrient
  997.  
  998.         -- If resuming, check whether the resume point has been reached, otherwise turn
  999.         if (resuming == true) then
  1000.           updateResumingFlag()
  1001.         else
  1002.           -- Write the new orientation and turn
  1003.           saveLocation()
  1004.           turtle.turnRight()
  1005.           turtle.turnRight()
  1006.         end
  1007.       elseif (newOrient == direction.FORWARD) then
  1008.         currOrient = newOrient
  1009.  
  1010.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1011.         if (resuming == true) then
  1012.           updateResumingFlag()
  1013.         else
  1014.           -- Write the new orientation and turn
  1015.           saveLocation()
  1016.           turtle.turnLeft()
  1017.         end
  1018.       else
  1019.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  1020.       end
  1021.     elseif (currOrient == direction.BACK) then
  1022.       if (newOrient == direction.LEFT) then
  1023.         currOrient = newOrient
  1024.  
  1025.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1026.         if (resuming == true) then
  1027.           updateResumingFlag()
  1028.         else
  1029.           -- Write the new orientation and turn
  1030.           saveLocation()
  1031.           turtle.turnRight()
  1032.         end
  1033.       elseif (newOrient == direction.FORWARD) then
  1034.         currOrient = newOrient
  1035.  
  1036.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1037.         if (resuming == true) then
  1038.           updateResumingFlag()
  1039.         else
  1040.           -- Write the new orientation and turn
  1041.           saveLocation()
  1042.           turtle.turnRight()
  1043.           turtle.turnRight()
  1044.         end
  1045.       elseif (newOrient == direction.RIGHT) then
  1046.         currOrient = newOrient
  1047.  
  1048.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1049.         if (resuming == true) then
  1050.           updateResumingFlag()
  1051.         else
  1052.           -- Write the new orientation and turn
  1053.           saveLocation()
  1054.           turtle.turnLeft()
  1055.         end
  1056.       else
  1057.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  1058.       end
  1059.     elseif (currOrient == direction.LEFT) then
  1060.       if (newOrient == direction.FORWARD) then
  1061.         currOrient = newOrient
  1062.  
  1063.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1064.         if (resuming == true) then
  1065.           updateResumingFlag()
  1066.         else
  1067.           -- Write the new orientation and turn
  1068.           saveLocation()
  1069.           turtle.turnRight()
  1070.         end
  1071.       elseif (newOrient == direction.RIGHT) then
  1072.         currOrient = newOrient
  1073.  
  1074.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1075.         if (resuming == true) then
  1076.           updateResumingFlag()
  1077.         else
  1078.           -- Write the new orientation and turn
  1079.           saveLocation()
  1080.           turtle.turnRight()
  1081.           turtle.turnRight()
  1082.         end
  1083.       elseif (newOrient == direction.BACK) then
  1084.         currOrient = newOrient
  1085.  
  1086.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1087.         if (resuming == true) then
  1088.           updateResumingFlag()
  1089.         else
  1090.           -- Write the new orientation and turn
  1091.           saveLocation()
  1092.           turtle.turnLeft()
  1093.         end
  1094.       else
  1095.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  1096.       end
  1097.     else
  1098.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  1099.     end
  1100.   end
  1101. end
  1102.  
  1103. -- ********************************************************************************** --
  1104. -- Determines if a particular block is considered a noise block or not. A noise
  1105. -- block is one that is a standard block in the game (stone, dirt, gravel etc.) and
  1106. -- is one to ignore as not being an ore. Function works by comparing the block
  1107. -- in question against a set of blocks in the turtle's inventory which are known not to
  1108. -- be noise blocks. Param is the function to use to compare the block for a noise block
  1109. -- ********************************************************************************** --
  1110. function isNoiseBlock(compareFn)
  1111.  
  1112.   -- Consider air to be a noise block
  1113.   local returnVal = false
  1114.  
  1115.   if (resuming == true) then
  1116.     returnVal = true
  1117.   else
  1118.     local seamLoop = 1
  1119.     local prevSelectedSlot  
  1120.  
  1121.     -- If the currently selected slot is a noise block, then compare against this first
  1122.     -- so that the slot doesn't need to be selected again (there is a 0.05s cost to do
  1123.     -- this even if it is the currently selected slot)
  1124.     if (currentlySelectedSlot <= noiseBlocksCount) then
  1125.       returnVal = compareFn()
  1126.     end
  1127.  
  1128.     if (returnVal == false) then
  1129.       prevSelectedSlot = currentlySelectedSlot
  1130.       while((returnVal == false) and (seamLoop <= noiseBlocksCount)) do
  1131.         if (seamLoop ~= prevSelectedSlot) then
  1132.           turtle.select(seamLoop)
  1133.           currentlySelectedSlot = seamLoop
  1134.           returnVal = compareFn()
  1135.         end
  1136.         seamLoop = seamLoop + 1
  1137.       end
  1138.     end
  1139.   end
  1140.  
  1141.   -- Return the calculated value
  1142.   return returnVal
  1143.  
  1144. end
  1145.  
  1146. -- ********************************************************************************** --
  1147. -- Determines if a particular block is a chest. Returns false if it is not a chest
  1148. -- or chests are not being detected
  1149. -- ********************************************************************************** --
  1150. function isChestBlock(compareFn)
  1151.  
  1152.   -- Check the block in the appropriate direction to see whether it is a chest. Only
  1153.   -- do this if we are looking for chests
  1154.   local returnVal = false
  1155.   if (lookForChests == true) then
  1156.     turtle.select(15)
  1157.     currentlySelectedSlot = 15
  1158.     returnVal = compareFn()
  1159.   end
  1160.  
  1161.   -- Return the calculated value
  1162.   return returnVal
  1163.  
  1164. end
  1165.  
  1166. -- ********************************************************************************** --
  1167. -- Function to calculate the number of non seam blocks in the turtle's inventory. This
  1168. -- is all of the blocks at the start of the inventory (before the first empty slot is
  1169. -- found
  1170. -- ********************************************************************************** --
  1171. function determineNoiseBlocksCountCount()
  1172.   -- Determine the location of the first empty inventory slot. All items before this represent
  1173.   -- noise items.
  1174.   local foundFirstBlankInventorySlot = false
  1175.   noiseBlocksCount = 1
  1176.   while ((noiseBlocksCount < 16) and (foundFirstBlankInventorySlot == false)) do
  1177.     if (turtle.getItemCount(noiseBlocksCount) > 0) then
  1178.       noiseBlocksCount = noiseBlocksCount + 1
  1179.     else
  1180.       foundFirstBlankInventorySlot = true
  1181.     end
  1182.   end
  1183.   noiseBlocksCount = noiseBlocksCount - 1
  1184.  
  1185.   -- Determine whether a chest was provided, and hence whether we should support
  1186.   -- looking for chests
  1187.   if (turtle.getItemCount(15) > 0) then
  1188.     lookForChests = true
  1189.     lastEmptySlot = 14
  1190.     miningOffset = 0
  1191.     writeMessage("Looking for chests...", messageLevel.DEBUG)
  1192.   else
  1193.     lastEmptySlot = 15
  1194.     miningOffset = 1
  1195.     writeMessage("Ignoring chests...", messageLevel.DEBUG)
  1196.   end
  1197. end
  1198.  
  1199. -- ********************************************************************************** --
  1200. -- Creates a quarry mining out only ores and leaving behind any noise blocks
  1201. -- ********************************************************************************** --
  1202. function createQuarry()
  1203.  
  1204.   -- Determine the top mining layer layer. The turtle mines in layers of 3, and the bottom layer
  1205.   -- is the layer directly above bedrock.
  1206.   --
  1207.   -- The actual layer that the turtle operates in is the middle of these three layers,
  1208.   -- so determine the top layer
  1209.   local topMiningLayer = startHeight + ((bottomLayer - startHeight - 2) % 3) - 1 + miningOffset
  1210.  
  1211.   -- If the top layer is up, then ignore it and move to the next layer
  1212.   if (topMiningLayer > currY) then
  1213.     topMiningLayer = topMiningLayer - 3
  1214.   end
  1215.  
  1216.   local startedLayerToRight = true -- Only used where the quarry is of an odd width
  1217.  
  1218.   -- Loop over each mining row
  1219.   local miningLevel
  1220.   for miningLevel = (bottomLayer + miningOffset), topMiningLayer, 3 do
  1221.     writeMessage("Mining Layer: "..miningLevel, messageLevel.INFO)
  1222.     haveBeenAtZeroZeroOnLayer = false
  1223.  
  1224.     -- While the initial shaft is being dug out, set the level to return to in order to unload
  1225.     -- to the just take the turtle straight back up
  1226.     if (miningLevel == (bottomLayer + miningOffset)) then
  1227.       levelToReturnTo = startHeight
  1228.     end
  1229.  
  1230.     -- Move to the correct level to start mining
  1231.     if (currY > miningLevel) then
  1232.       while (currY > miningLevel) do
  1233.         turtleDown()
  1234.       end
  1235.     elseif (currY < miningLevel) then
  1236.       while (currY < miningLevel) do
  1237.         turtleUp()
  1238.       end
  1239.     end
  1240.  
  1241.     -- Am now mining the levels (update the mining state to reflect that fact)
  1242.     currMiningState = miningState.LAYER
  1243.  
  1244.     -- Set the layer to return via when returning to the surface as the one below the currently
  1245.     -- mined one
  1246.     if (miningLevel == (bottomLayer + miningOffset)) then
  1247.       levelToReturnTo = (bottomLayer + miningOffset)
  1248.     else
  1249.       levelToReturnTo = miningLevel - 3
  1250.     end
  1251.  
  1252.     -- Move turtle into the correct orientation to start mining (if this is the
  1253.     -- first row to be mined, then don't need to turn, otherwise turn towards the next
  1254.     -- mining section)
  1255.  
  1256.     writeMessage("Mining Level: "..miningLevel..", Bottom Layer: "..bottomLayer..", Mining Offset: "..miningOffset, messageLevel.DEBUG)
  1257.  
  1258.     if (miningLevel > (bottomLayer + miningOffset)) then
  1259.       -- Turn towards the next mining layer
  1260.       if (quarryWidth % 2 == 0) then
  1261.         -- An even width quarry, always turn right
  1262.         turtleTurn(direction.RIGHT)
  1263.       else
  1264.         -- Turn the opposite direction to that which we turned before
  1265.         if (startedLayerToRight == true) then
  1266.           turtleTurn(direction.LEFT)
  1267.           startedLayerToRight = false
  1268.         else
  1269.           turtleTurn(direction.RIGHT)
  1270.           startedLayerToRight = true
  1271.         end
  1272.       end
  1273.     end
  1274.  
  1275.     local mineRows
  1276.     local onNearSideOfQuarry = true
  1277.     local diggingAway = true
  1278.     for mineRows = 1, quarryWidth do
  1279.  
  1280.       -- If this is not the first row, then get into position to mine the next row
  1281.       if ((mineRows == 1) and (lookForChests == false)) then
  1282.         -- Not looking for chests, check the block below for being an ore. Only do this
  1283.         -- if we're not looking for chests since the program doesn't support chests in
  1284.         -- bedrock
  1285.         if (isNoiseBlock(turtle.compareDown) == false) then
  1286.           turtle.digDown()
  1287.           ensureInventorySpace()
  1288.         end
  1289.       elseif (mineRows > 1) then
  1290.         -- Move into position for mining the next row
  1291.         if (onNearSideOfQuarry == diggingAway) then
  1292.           if (startedLayerToRight == true) then
  1293.             turtleTurn(direction.LEFT)
  1294.           else
  1295.             turtleTurn(direction.RIGHT)
  1296.           end
  1297.         else
  1298.           if (startedLayerToRight == true) then
  1299.             turtleTurn(direction.RIGHT)
  1300.           else
  1301.             turtleTurn(direction.LEFT)
  1302.           end
  1303.         end
  1304.  
  1305.         turtleForward()
  1306.  
  1307.         -- Before making the final turn, check the block below. Do this
  1308.         -- now because if it is a chest, then we want to back up and
  1309.         -- approach it from the side (so that we don't lose items if we
  1310.         -- have to return to the start through it).
  1311.         --
  1312.         -- This is the point at which it is safe to back up without moving
  1313.         -- out of the quarry area (unless at bedrock in which case don't bother
  1314.         -- as we'll be digging down anyway)
  1315.         if (miningLevel ~= bottomLayer) then
  1316.           if (isNoiseBlock(turtle.compareDown) == false) then
  1317.             -- If we are not looking for chests, then just dig it (it takes
  1318.             -- less time to try to dig and fail as it does to do detect and
  1319.             -- only dig if there is a block there)
  1320.             if (lookForChests == false) then
  1321.               turtle.digDown()
  1322.               ensureInventorySpace()
  1323.             elseif (turtle.detectDown() == true) then
  1324.               if (isChestBlock(turtle.compareDown) == true) then
  1325.                 -- There is a chest block below. Move back and approach
  1326.                 -- from the side to ensure that we don't need to return to
  1327.                 -- start through the chest itself (potentially losing items)
  1328.                 turtleBack()
  1329.                 turtleDown()
  1330.                 currMiningState = miningState.EMPTYCHESTDOWN
  1331.                 emptyChest(turtle.suck)
  1332.                 currMiningState = miningState.LAYER
  1333.                 turtleUp()
  1334.                 turtleForward()
  1335.                 turtle.digDown()
  1336.                 ensureInventorySpace()
  1337.               else
  1338.                 turtle.digDown()
  1339.                 ensureInventorySpace()
  1340.               end
  1341.             end
  1342.           end
  1343.         end
  1344.  
  1345.         -- Move into final position for mining the next row
  1346.         if (onNearSideOfQuarry == diggingAway) then
  1347.           if (startedLayerToRight == true) then
  1348.             turtleTurn(direction.LEFT)
  1349.           else
  1350.             turtleTurn(direction.RIGHT)
  1351.           end
  1352.         else
  1353.           if (startedLayerToRight == true) then
  1354.             turtleTurn(direction.RIGHT)
  1355.           else
  1356.             turtleTurn(direction.LEFT)
  1357.           end
  1358.         end
  1359.       end
  1360.  
  1361.       -- Dig to the other side of the quarry
  1362.       local blocksMined
  1363.       for blocksMined = 0, (quarryWidth - 1) do
  1364.         if (blocksMined > 0) then
  1365.           -- Only move forward if this is not the first space
  1366.           turtleForward()
  1367.         end
  1368.  
  1369.         -- If the current block is (0,0), then record the fact that the
  1370.         -- turtle has been through this block and what it's orientation was and update the layer
  1371.         -- that it should return via to get back to the surface (it no longer needs to go down
  1372.         -- a level to prevent losing ores).
  1373.         if ((currX == 0) and (currZ == 0)) then
  1374.           -- Am at (0, 0). Remember this, and what direction I was facing so that the quickest route
  1375.           -- to the surface can be taken
  1376.           levelToReturnTo = miningLevel
  1377.           haveBeenAtZeroZeroOnLayer = true
  1378.           orientationAtZeroZero = currOrient
  1379.         end
  1380.  
  1381.         -- If currently at bedrock, just move down until the turtle can't go any
  1382.         -- further. This allows the blocks within the bedrock to be mined
  1383.         if (miningLevel == bottomLayer) then
  1384.           -- Temporarily turn off looking for chests to increase bedrock mining speed (this
  1385.           -- means that the program doesn't support chests below level 5 - but I think
  1386.           -- they they don't exist anyway)
  1387.           local lookForChestsPrev = lookForChests
  1388.           lookForChests = false
  1389.  
  1390.           -- Manually set the flag to determine whether the turtle should try to move first or
  1391.           -- dig first. At bedrock, is very rarely any space
  1392.  
  1393.           -- Just above bedrock layer, dig down until can't dig any lower, and then
  1394.           -- come back up. This replicates how the quarry functions
  1395.           lastMoveNeededDig = true
  1396.           local moveDownSuccess = turtleDown()
  1397.           while (moveDownSuccess == true) do
  1398.             moveDownSuccess = turtleDown()
  1399.           end
  1400.  
  1401.           -- Know that we are moving back up through air, therefore set the flag to force the
  1402.           -- turtle to try moving first
  1403.           lastMoveNeededDig = false
  1404.  
  1405.           -- Have now hit bedrock, move back to the mining layer
  1406.           while (currY < bottomLayer) do
  1407.             turtleUp()
  1408.           end
  1409.  
  1410.           -- Now back at the level above bedrock, again reset the flag to tell the turtle to
  1411.           -- try digging again (because it is rare to find air at bedrock level)
  1412.           lastMoveNeededDig = false
  1413.  
  1414.           -- Reset the look for chests value
  1415.           lookForChests = lookForChestsPrev
  1416.         elseif ((blocksMined > 0) and ((currX ~= 0) or (currZ ~= 0))) then
  1417.           -- This isn't the first block of the row, nor are we at (0, 0) so we need to check the
  1418.           -- block below
  1419.  
  1420.           -- Check the block down for being a noise block (don't need to check the first
  1421.           -- block as it has already been checked in the outer loop)
  1422.           if (isNoiseBlock(turtle.compareDown) == false) then
  1423.             -- If we are not looking for chests, then just dig it (it takes
  1424.             -- less time to try to dig and fail as it does to do detect and
  1425.             -- only dig if there is a block there)
  1426.             if (lookForChests == false) then
  1427.               turtle.digDown()
  1428.               ensureInventorySpace()
  1429.             elseif (turtle.detectDown() == true) then
  1430.               if (isChestBlock(turtle.compareDown) == true) then
  1431.                 -- There is a chest block below. Move back and approach
  1432.                 -- from the side to ensure that we don't need to return to
  1433.                 -- start through the chest itself (potentially losing items)
  1434.                 turtleBack()
  1435.                 currMiningState = miningState.EMPTYCHESTDOWN
  1436.                 turtleDown()
  1437.                 emptyChest(turtle.suck)
  1438.                 currMiningState = miningState.LAYER
  1439.                 turtleUp()
  1440.                 turtleForward()
  1441.                 turtle.digDown()
  1442.                 ensureInventorySpace()
  1443.               else
  1444.                 turtle.digDown()
  1445.                 ensureInventorySpace()
  1446.               end
  1447.             end
  1448.           end
  1449.         end
  1450.        
  1451.         -- Check the block above for ores (if we're not a (0, 0) in which case
  1452.         -- we know it's air)
  1453.         if ((currX ~= 0) or (currZ ~= 0)) then
  1454.           if (isNoiseBlock(turtle.compareUp) == false) then
  1455.             -- If we are not looking for chests, then just dig it (it takes
  1456.             -- less time to try to dig and fail as it does to do detect and
  1457.             -- only dig if there is a block there)
  1458.             if (lookForChests == false) then
  1459.               turtle.digUp()
  1460.               ensureInventorySpace()
  1461.             elseif (turtle.detectUp() == true) then
  1462.               -- Determine if it is a chest before digging it
  1463.               if (isChestBlock(turtle.compareUp) == true) then
  1464.                 -- There is a chest block above. Empty it before digging it
  1465.                 emptyChest(turtle.suckUp)
  1466.                 turtle.digUp()
  1467.                 ensureInventorySpace()
  1468.               else
  1469.                 turtle.digUp()
  1470.                 ensureInventorySpace()
  1471.               end
  1472.             end
  1473.           end
  1474.         end
  1475.       end
  1476.  
  1477.       -- Am now at the other side of the quarry
  1478.       onNearSideOfQuarry = not onNearSideOfQuarry
  1479.     end
  1480.  
  1481.     -- If we were digging away from the starting point, will be digging
  1482.     -- back towards it on the next layer
  1483.     diggingAway = not diggingAway
  1484.   end
  1485.  
  1486.   -- Return to the start
  1487.   returnToStartAndUnload(false)
  1488.  
  1489.   -- Face forward
  1490.   turtleSetOrientation(direction.FORWARD)
  1491.  
  1492.   -- Write all done
  1493.   writeMessage("All Done!", messageLevel.INFO)
  1494. end
  1495.  
  1496. -- ********************************************************************************** --
  1497. -- Reads the next number from a given file
  1498. -- ********************************************************************************** --
  1499. function readNumber(inputFile)
  1500.  
  1501.   local returnVal
  1502.   local nextLine = inputFile.readLine()
  1503.   if (nextLine ~= nil) then
  1504.     returnVal = tonumber(nextLine)
  1505.   end
  1506.  
  1507.   return returnVal
  1508. end
  1509.  
  1510. -- ********************************************************************************** --
  1511. -- Startup function to support resuming mining turtle
  1512. -- ********************************************************************************** --
  1513. function isResume()
  1514.  
  1515.   local returnVal = false
  1516.  
  1517.   -- Try to open the resume file
  1518.   local resumeFile = fs.open(startupParamsFile, "r")
  1519.   if (resumeFile == nil) then
  1520.     -- No resume file (presume that we are not supporting it)
  1521.     supportResume = false
  1522.   else
  1523.     writeMessage("Found startup params file", messageLevel.DEBUG)
  1524.  
  1525.     -- Read in the startup params
  1526.     quarryWidth = readNumber(resumeFile)
  1527.     startHeight = readNumber(resumeFile)
  1528.     noiseBlocksCount = readNumber(resumeFile)
  1529.     lastEmptySlot = readNumber(resumeFile)
  1530.     resumeFile.close()
  1531.  
  1532.     -- If the parameters were successfully read, then set the resuming flag to true
  1533.     if ((quarryWidth ~= nil) and (startHeight ~= nil) and (noiseBlocksCount ~= nil) and (lastEmptySlot ~= nil)) then
  1534.  
  1535.       resuming = true
  1536.       writeMessage("Read params", messageLevel.DEBUG)
  1537.  
  1538.       -- Determine the look for chest and mining offset
  1539.       if (lastEmptySlot == 14) then
  1540.         lookForChests = true
  1541.         miningOffset = 0
  1542.       else
  1543.         lookForChests = false
  1544.         miningOffset = 1
  1545.       end
  1546.  
  1547.       -- Get the turtle resume location
  1548.       resumeFile = fs.open(oreQuarryLocation, "r")
  1549.       if (resumeFile ~= nil) then
  1550.  
  1551.         resumeMiningState = readNumber(resumeFile)
  1552.         resumeX = readNumber(resumeFile)
  1553.         resumeY = readNumber(resumeFile)
  1554.         resumeZ = readNumber(resumeFile)
  1555.         resumeOrient = readNumber(resumeFile)
  1556.         resumeFile.close()
  1557.  
  1558.         -- Ensure that the resume location has been found
  1559.         if ((resumeMiningState ~= nil) and (resumeX ~= nil) and (resumeY ~= nil) and (resumeZ ~= nil) and (resumeOrient ~= nil)) then
  1560.           returnVal = true
  1561.           local emptiedInventory = false
  1562.  
  1563.           -- Perform any mining state specific startup
  1564.           if (resumeMiningState == miningState.EMPTYINVENTORY) then
  1565.             -- Am mid way through an empty inventory cycle. Complete it before
  1566.             -- starting the main Quarry function
  1567.             returnToStartAndUnload(true)
  1568.             resuming = true
  1569.  
  1570.             -- Continue from the current position
  1571.             resumeX = currX
  1572.             resumeY = currY
  1573.             levelToReturnTo = resumeY
  1574.             resumeZ = currZ
  1575.             resumeOrient = currOrient
  1576.  
  1577.             writeMessage("Resuming with state of "..currMiningState, messageLevel.DEBUG)
  1578.             resumeMiningState = currMiningState
  1579.             emptiedInventory = true
  1580.           end
  1581.  
  1582.           -- If was emptying a chest when the program stopped, then move back
  1583.           -- to a point which the Quarry
  1584.           if (resumeMiningState == miningState.EMPTYCHESTDOWN) then
  1585.  
  1586.             -- Set the current X, Y, Z and orientation to the true position that
  1587.             -- the turtle is at
  1588.             if (emptiedInventory == false) then
  1589.               currX = resumeX
  1590.               currY = resumeY
  1591.               currZ = resumeZ
  1592.               currOrient = resumeOrient
  1593.             end
  1594.  
  1595.             -- Set the mining state as layer, assume haven't been through zero
  1596.             -- zero and set the level to return to as the one below the current one
  1597.             currMiningState = miningState.LAYER
  1598.             levelToReturnTo = currY - 2
  1599.             haveBeenAtZeroZeroOnLayer = false
  1600.  
  1601.             -- Temporarily disable resuming (so that the new location is written to the file
  1602.             -- in case the program stops again)
  1603.             resuming = false
  1604.             turtleUp()
  1605.             resuming = true
  1606.  
  1607.             resumeY = currY
  1608.             resumeMiningState = miningState.LAYER
  1609.           end
  1610.         end
  1611.       end
  1612.     end
  1613.  
  1614.     if (returnVal == false) then
  1615.       writeMessage("Failed to resume", messageLevel.ERROR)
  1616.     end
  1617.   end
  1618.  
  1619.   return returnVal
  1620. end
  1621.  
  1622. -- ********************************************************************************** --
  1623. -- Main Function                                          
  1624. -- ********************************************************************************** --
  1625. -- Process the input arguments - storing them to global variables
  1626. local args = { ... }
  1627. local paramsOK = true
  1628.  
  1629. -- Detect whether this is a wireless turtle, and if so, open the modem
  1630. local peripheralConnected = peripheral.getType("right")
  1631. if (peripheralConnected == "modem") then
  1632.   isWirelessTurtle = true
  1633. end
  1634.  
  1635. -- If a wireless turtle, open the modem
  1636. if (isWirelessTurtle == true) then
  1637.   turtleId = os.getComputerLabel()
  1638.   rednet.open("right")
  1639. end
  1640.  
  1641. if (#args == 0) then
  1642.   -- Is this a resume?
  1643.   if (isResume() == false) then
  1644.     paramsOK = false
  1645.   end
  1646. elseif (#args == 1) then
  1647.   quarryWidth = tonumber(args[1])
  1648.   local x, y, z = gps.locate(5)
  1649.   startHeight = y
  1650.   if (startHeight == nil) then
  1651.     writeMessage("Can't locate GPS", messageLevel.FATAL)
  1652.     paramsOK = false
  1653.   end
  1654. elseif (#args == 2) then
  1655.   if (args[2] == "/r") then
  1656.     quarryWidth = tonumber(args[1])
  1657.     supportResume = false
  1658.   else
  1659.     quarryWidth = tonumber(args[1])
  1660.     startHeight = tonumber(args[2])
  1661.   end
  1662. elseif (#args == 3) then
  1663.   quarryWidth = tonumber(args[1])
  1664.   startHeight = tonumber(args[2])
  1665.   if (args[3] == "/r") then
  1666.     supportResume = false
  1667.   else
  1668.     paramsOK = false
  1669.   end
  1670. end
  1671.  
  1672. if ((paramsOK == false) and (resuming == false)) then
  1673.   writeMessage("Usage: "..shell.getRunningProgram().." <diameter> [turtleY] [/r]", messageLevel.FATAL)
  1674.   paramsOK = false
  1675. end
  1676.  
  1677. if (paramsOK == true) then
  1678.   if ((startHeight < 6) or (startHeight > 128)) then
  1679.     writeMessage("turtleY must be between 6 and 128", messageLevel.FATAL)
  1680.     paramsOK = false
  1681.   end
  1682.  
  1683.   if ((quarryWidth < 2) or (quarryWidth > 64)) then
  1684.     writeMessage("diameter must be between 2 and 64", messageLevel.FATAL)
  1685.     paramsOK = false
  1686.   end
  1687. end
  1688.  
  1689. if (paramsOK == true) then
  1690.   if (resuming == true) then
  1691.     writeMessage("Resuming Ore Quarry...", messageLevel.INFO)
  1692.   else
  1693.     writeMessage("----------------------------------", messageLevel.INFO)
  1694.     writeMessage("** Ore Quarry v0.71 by AustinKK **", messageLevel.INFO)
  1695.     writeMessage("----------------------------------", messageLevel.INFO)
  1696.   end
  1697.  
  1698.   -- Set the turtle's starting position
  1699.   currX = 0
  1700.   currY = startHeight
  1701.   currZ = 0
  1702.   currOrient = direction.FORWARD
  1703.  
  1704.   -- Calculate which blocks in the inventory signify noise blocks
  1705.   if (resuming == false) then
  1706.     determineNoiseBlocksCountCount()
  1707.   end
  1708.  
  1709.   if ((noiseBlocksCount == 0) or (noiseBlocksCount > 13)) then
  1710.     writeMessage("No noise blocks have been been added. Please place blocks that the turtle should not mine (e.g. Stone, Dirt, Gravel etc.) in the first few slots of the turtle\'s inventory. The first empty slot signifies the end of the noise blocks.", messageLevel.FATAL)
  1711.   else
  1712.     -- If we are supporting resume (and are not currently in the process of resuming)
  1713.     -- then store startup parameters in appropriate files
  1714.     if ((supportResume == true) and (resuming == false)) then
  1715.       -- Write the startup parameters to  file
  1716.       local outputFile = io.open(startupParamsFile, "w")
  1717.       outputFile:write(quarryWidth)
  1718.       outputFile:write("\n")
  1719.       outputFile:write(startHeight)
  1720.       outputFile:write("\n")
  1721.       outputFile:write(noiseBlocksCount)
  1722.       outputFile:write("\n")
  1723.       outputFile:write(lastEmptySlot)
  1724.       outputFile:write("\n")
  1725.       outputFile:close()
  1726.  
  1727.       -- Setup the startup file
  1728.  
  1729.       -- Take a backup of the current startup file
  1730.       if (fs.exists("startup") == true) then
  1731.         fs.copy("startup", startupBackup)
  1732.         outputFile = io.open("startup", "a")
  1733.       else
  1734.         outputFile = io.open("startup", "w")
  1735.       end
  1736.      
  1737.       -- Write an info message so that people know how to get out of auto-resume
  1738.       outputFile:write("\nprint(\"Running auto-restart...\")\n")
  1739.       outputFile:write("print(\"If you want to stop auto-resume and restore original state:\")\n")
  1740.       outputFile:write("print(\"1) Hold Ctrl-T until the program terminates\")\n")
  1741.       outputFile:write("print(\"2) Type \\\"rm startup\\\" (without quotes) and hit Enter\")\n")
  1742.       outputFile:write("print(\"\")\n\n")
  1743.  
  1744.       -- Write the code required to restart the turtle
  1745.       outputFile:write("shell.run(\"")
  1746.       outputFile:write(shell.getRunningProgram())
  1747.       outputFile:write("\")\n")
  1748.       outputFile:close()
  1749.  
  1750.     end
  1751.  
  1752.     -- Create a Quarry
  1753.     turtle.select(1)
  1754.     currentlySelectedSlot = 1
  1755.     createQuarry()
  1756.  
  1757.     -- Restore the file system to its original configuration
  1758.     if (supportResume == true) then
  1759.       fs.delete("startup")
  1760.       if (fs.exists(startupBackup) == true) then
  1761.         fs.move(startupBackup, "startup")
  1762.       end
  1763.  
  1764.       if (fs.exists(startupParamsFile) == true) then
  1765.         fs.delete(startupParamsFile)
  1766.       end
  1767.  
  1768.       if (fs.exists(oreQuarryLocation) == true) then
  1769.         fs.delete(oreQuarryLocation)
  1770.       end
  1771.  
  1772.       if (fs.exists(returnToStartFile) == true) then
  1773.         fs.delete(returnToStartFile)
  1774.       end
  1775.     end
  1776.   end
  1777. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement