willisshek

[Minecraft] Ore Quarry

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