Advertisement
sviridovt

Untitled

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