Advertisement
Guest User

Untitled

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