Shaco74

Sebosom

Oct 9th, 2019
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 36.18 KB | None | 0 0
  1. -- ********************************************************************************** --
  2. -- ** ** --
  3. -- ** Minecraft Mining Turtle Ore Quarry v0.2 by AustinKK ** --
  4. -- ** --------------------------------------------------- ** --
  5. -- ** ** --
  6. -- ** For instructions on how to use: ** --
  7. -- ** ** --
  8. -- ** http://www.youtube.com/watch?v=DS1H4OY0yyg ** --
  9. -- ** ** --
  10. -- ********************************************************************************** --
  11. -- Enumeration to store the the different types of message that can be written
  12. messageLevel = { DEBUG=0, INFO=1, WARNING=2, ERROR=3, FATAL=4 }
  13.  
  14. -- Enumeration to store names for the 6 directions
  15. direction = { FORWARD=0, RIGHT=1, BACK=2, LEFT=3, UP=4, DOWN=5 }
  16.  
  17. local messageOutputLevel = messageLevel.INFO
  18. local fuelLevelToRefuelAt = 5
  19. local refuelItemsToUseWhenRefuelling = 1
  20. local emergencyFuelToRetain = 3
  21. local maximumGravelStackSupported = 25 -- The number of stacked gravel or sand blocks supported
  22. local nonSeamBlocks
  23. local bottomLayer = 5 -- The y co-ords of the layer immediately above bedrock
  24. local returningToStart = false
  25. local lookForChests = false -- Determines if chests should be located as part of the quarrying
  26. 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)
  27. local turtleId
  28.  
  29. -- Variables to store the current location and orientation of the turtle. x is right, left, y is up, down and
  30. -- z is forward, back with relation to the starting orientation. Y is the actual turtle level, x and z are
  31. -- in relation to the starting point (i.e. the starting point is (0, 0))
  32. local currX
  33. local currY
  34. local currZ
  35. local currOrient
  36.  
  37. -- Command line parameters
  38. local startHeight -- Represents the height (y co-ord) that the turtle started at
  39. local quarryWidth -- Represents the length of the mines that the turtle will dig
  40.  
  41. -- ********************************************************************************** --
  42. -- Writes an output message
  43. -- ********************************************************************************** --
  44. function writeMessage(message, msgLevel)
  45. if (msgLevel >= messageOutputLevel) then
  46. print(message)
  47. if (turtleId == nil) then
  48. rednet.broadcast(message)
  49. else
  50. -- Broadcast the message (prefixed with the turtle's id)
  51. rednet.broadcast("[".. turtleId.."] "..message)
  52. end
  53. end
  54. end
  55.  
  56. -- ********************************************************************************** --
  57. -- Ensures that the turtle has fuel
  58. -- ********************************************************************************** --
  59. function ensureFuel()
  60.  
  61. -- Determine whether a refuel is required
  62. local fuelLevel = turtle.getFuelLevel()
  63. if (fuelLevel ~= "unlimited") then
  64. if (fuelLevel < fuelLevelToRefuelAt) then
  65. -- Need to refuel
  66. turtle.select(16)
  67. local fuelItems = turtle.getItemCount(16)
  68.  
  69. -- Do we need to impact the emergency fuel to continue? (always
  70. -- keep one fuel item in slot 16)
  71. if (fuelItems == 0) then
  72. writeMessage("Completely out of fuel!", messageLevel.FATAL)
  73. elseif (fuelItems == 1) then
  74. writeMessage("Out of Fuel!", messageLevel.ERROR)
  75. elseif (fuelItems <= (emergencyFuelToRetain + 1)) then
  76. writeMessage("Consuming emergency fuel supply. "..(fuelItems - 2).." emergency fuel items remain", messageLevel.WARNING)
  77. turtle.refuel(1)
  78. else
  79. -- Refuel the lesser of the refuelItemsToUseWhenRefuelling and the number of items more than
  80. -- the emergency fuel level
  81. if (fuelItems - (emergencyFuelToRetain + 1) < refuelItemsToUseWhenRefuelling) then
  82. turtle.refuel(fuelItems - (emergencyFuelToRetain + 1))
  83. else
  84. turtle.refuel(refuelItemsToUseWhenRefuelling)
  85. end
  86. end
  87. end
  88. end
  89. end
  90.  
  91. -- ********************************************************************************** --
  92. -- Checks that the turtle has inventory space by checking for spare slots and returning
  93. -- to the starting point to empty out if it doesn't.
  94. --
  95. -- Takes the position required to move to in order to empty the turtle's inventory
  96. -- should it be full as arguments
  97. -- ********************************************************************************** --
  98. function ensureInventorySpace()
  99.  
  100. -- If already returning to start, then don't need to do anything
  101. if (returningToStart == false) then
  102.  
  103. -- If the last inventory slot is full, then need to return to the start and empty
  104. if (turtle.getItemCount(lastEmptySlot) > 0) then
  105.  
  106. -- Return to the starting point and empty the inventory, then go back to mining
  107. returnToStartAndUnload(true)
  108. end
  109. end
  110. end
  111.  
  112. -- ********************************************************************************** --
  113. -- Function that is called when the turtle has returned to the start in order to
  114. -- empty its inventory into the chest and also pick up any fuel that is
  115. -- available
  116. -- ********************************************************************************** --
  117. function emptyInventory()
  118.  
  119. local slotLoop = 1
  120.  
  121. -- Face the chest
  122. turtleSetOrientation(direction.BACK)
  123.  
  124. -- Loop over each of the slots (except the 16th one which stores fuel)
  125. while (slotLoop < 16) do
  126. -- If this is one of the slots that contains a noise block, empty all blocks except
  127. -- one
  128. turtle.select(slotLoop)
  129. if ((slotLoop <= nonSeamBlocks) or ((slotLoop == 15) and (lookForChests == true))) then
  130. turtle.drop(turtle.getItemCount(slotLoop) - 1)
  131. else
  132. -- Not a noise block, drop all of the items in this slot
  133. turtle.drop()
  134. end
  135.  
  136. slotLoop = slotLoop + 1
  137. end
  138.  
  139. -- While we are here, refill the fuel items
  140. turtleSetOrientation(direction.LEFT)
  141. turtle.select(16)
  142. local currFuelItems = turtle.getItemCount(16)
  143. turtle.suck()
  144. while ((currFuelItems ~= turtle.getItemCount(16)) and (turtle.getItemCount(16) < 64)) do
  145. currFuelItems = turtle.getItemCount(16)
  146. turtle.suck()
  147. end
  148.  
  149. slotLoop = nonSeamBlocks + 1
  150. -- Have now picked up all the items that we can. If we have also picked up some
  151. -- additional fuel in some of the other slots, then drop it again
  152. while (slotLoop < lastEmptySlot) do
  153. -- Drop any items found in this slot
  154. turtle.select(slotLoop)
  155. turtle.drop()
  156. slotLoop = slotLoop + 1
  157. end
  158.  
  159. -- Select the 1st slot because sometimes when leaving the 15th or 16th slots selected it can result
  160. -- in that slot being immediately filled (resulting in the turtle returning to base again too soon)
  161. turtle.select(1)
  162. end
  163.  
  164. -- ********************************************************************************** --
  165. -- Function to move to the starting point, call a function that is passed in
  166. -- and return to the same location (if required)
  167. -- ********************************************************************************** --
  168. function returnToStartAndUnload(returnBackToMiningPoint)
  169.  
  170. writeMessage("returnToStartAndUnload called", messageLevel.DEBUG)
  171. returningToStart = true
  172.  
  173. -- Store the current location and orientation so that it can be returned to
  174. local storedX = currX
  175. local storedY = currY
  176. local storedZ = currZ
  177. local storedOrient = currOrient
  178.  
  179. -- First direction to move is straight up. Do this because the inventory is full and
  180. -- therefore don't want to pass through any blocks that contain ores. Know that all
  181. -- blocks above don't contain ores, so is safe to go that way
  182. -- (Note, there is a rare edge case where the inventory becomes full after moving
  183. -- forward and before checking the block above, this is quite rare and given the
  184. -- likelihood of it not being able be added to the inventory (even though slot 15
  185. -- is full), and is deemed an acceptable risk)
  186. if (currY < startHeight) then
  187. while (currY < startHeight) do
  188. turtleUp()
  189. end
  190. elseif (currY > startHeight) then
  191. -- This should never happen
  192. writeMessage("Current height is greater than start height in returnToStartAndUnload", messageLevel.ERROR)
  193. end
  194.  
  195. -- Move back to the correct X position
  196. if (currX > 0) then
  197. turtleSetOrientation(direction.LEFT)
  198. while (currX > 0) do
  199. turtleForward()
  200. end
  201. elseif (currX < 0) then
  202. -- This should never happen
  203. writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  204. end
  205.  
  206. -- Move back to the correct Z position
  207. if (currZ > 0) then
  208. turtleSetOrientation(direction.BACK)
  209. while (currZ > 0) do
  210. turtleForward()
  211. end
  212. elseif (currZ < 0) then
  213. -- This should never happen
  214. writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  215. end
  216.  
  217. -- Empty the inventory
  218. local slotLoop = 1
  219.  
  220. -- Face the chest
  221. turtleSetOrientation(direction.BACK)
  222.  
  223. -- Loop over each of the slots (except the 16th one which stores fuel)
  224. while (slotLoop < 16) do
  225. -- If this is one of the slots that contains a noise block, empty all blocks except
  226. -- one
  227. turtle.select(slotLoop)
  228. if ((slotLoop <= nonSeamBlocks) or ((slotLoop == 15) and (lookForChests == true))) then
  229. turtle.drop(turtle.getItemCount(slotLoop) - 1)
  230. else
  231. -- Not a noise block, drop all of the items in this slot
  232. turtle.drop()
  233. end
  234.  
  235. slotLoop = slotLoop + 1
  236. end
  237.  
  238. -- While we are here, refill the fuel items
  239. turtleSetOrientation(direction.LEFT)
  240. turtle.select(16)
  241. local currFuelItems = turtle.getItemCount(16)
  242. turtle.suck()
  243. while ((currFuelItems ~= turtle.getItemCount(16)) and (turtle.getItemCount(16) < 64)) do
  244. currFuelItems = turtle.getItemCount(16)
  245. turtle.suck()
  246. end
  247.  
  248. slotLoop = nonSeamBlocks + 1
  249. -- Have now picked up all the items that we can. If we have also picked up some
  250. -- additional fuel in some of the other slots, then drop it again
  251. while (slotLoop <= lastEmptySlot) do
  252. -- Drop any items found in this slot
  253. turtle.select(slotLoop)
  254. turtle.drop()
  255. slotLoop = slotLoop + 1
  256. end
  257.  
  258. -- Select the 1st slot because sometimes when leaving the 15th or 16th slots selected it can result
  259. -- in that slot being immediately filled (resulting in the turtle returning to base again too soon)
  260. turtle.select(1)
  261.  
  262. -- If required, move back to the point that we were mining at before returning to the start
  263. if (returnBackToMiningPoint == true) then
  264. -- Return to the point that we were at so that quarrying may resume
  265. -- Move back to the correct Z position
  266. writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
  267. if (storedZ > currZ) then
  268. writeMessage("Orienting forward", messageLevel.DEBUG)
  269. writeMessage("Moving in z direction", messageLevel.DEBUG)
  270. turtleSetOrientation(direction.FORWARD)
  271. while (storedZ > currZ) do
  272. turtleForward()
  273. end
  274. elseif (storedZ < currZ) then
  275. -- This should never happen
  276. writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
  277. end
  278.  
  279. -- Move back to the correct X position
  280. if (storedX > currX) then
  281. writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
  282. writeMessage("Orienting right", messageLevel.DEBUG)
  283. writeMessage("Moving in x direction", messageLevel.DEBUG)
  284. turtleSetOrientation(direction.RIGHT)
  285. while (storedX > currX) do
  286. turtleForward()
  287. end
  288. elseif (storedX < currX) then
  289. -- This should never happen
  290. writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
  291. end
  292.  
  293. -- Move back to the correct Y position
  294. if (storedY < currY) then
  295. while (storedY < currY) do
  296. turtleDown()
  297. end
  298. elseif (storedY > currY) then
  299. -- This should never happen
  300. writeMessage("Stored y is greater than current y in returnToStartAndUnload", messageLevel.ERROR)
  301. end
  302.  
  303. -- Finally, set the correct orientation
  304. turtleSetOrientation(storedOrient)
  305.  
  306. writeMessage("Have returned to the mining point", messageLevel.DEBUG)
  307. end
  308.  
  309. returningToStart = false
  310.  
  311. end
  312.  
  313. -- ********************************************************************************** --
  314. -- Empties a chest's contents
  315. -- ********************************************************************************** --
  316. function emptyChest(suckFn)
  317.  
  318. local prevInventoryCount = {}
  319. local inventoryLoop
  320. local chestEmptied = false
  321.  
  322. -- Record the number of items in each of the inventory slots
  323. for inventoryLoop = 1, 16 do
  324. prevInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
  325. end
  326.  
  327. while (chestEmptied == false) do
  328. -- Pick up the next item
  329. suckFn()
  330.  
  331. -- Determine the number of items in each of the inventory slots now
  332. local newInventoryCount = {}
  333. for inventoryLoop = 1, 16 do
  334. newInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
  335. end
  336.  
  337. -- Now, determine whether there have been any items taken from the chest
  338. local foundDifferentItemCount = false
  339. inventoryLoop = 1
  340. while ((foundDifferentItemCount == false) and (inventoryLoop <= 16)) do
  341. if (prevInventoryCount[inventoryLoop] ~= newInventoryCount[inventoryLoop]) then
  342. foundDifferentItemCount = true
  343. else
  344. inventoryLoop = inventoryLoop + 1
  345. end
  346. end
  347.  
  348. -- If no items have been found with a different item count, then the chest has been emptied
  349. chestEmptied = not foundDifferentItemCount
  350.  
  351. if (chestEmptied == false) then
  352. prevInventoryCount = newInventoryCount
  353. -- Check that there is sufficient inventory space as may have picked up a block
  354. ensureInventorySpace()
  355. end
  356. end
  357.  
  358. writeMessage("Finished emptying chest", messageLevel.DEBUG)
  359. end
  360.  
  361.  
  362. -- ********************************************************************************** --
  363. -- Generic function to move the Turtle (pushing through any gravel or other
  364. -- things such as mobs that might get in the way).
  365. --
  366. -- The only thing that should stop the turtle moving is bedrock. Where this is
  367. -- found, the function will return after 15 seconds returning false
  368. -- ********************************************************************************** --
  369. function moveTurtle(moveFn, detectFn, digFn, attackFn, compareFn, suckFn, maxDigCount)
  370.  
  371. ensureFuel()
  372.  
  373. -- If we are looking for chests, then check that this isn't a chest before moving
  374. if (lookForChests == true) then
  375. if (isChestBlock(compareFn) == true) then
  376. -- Have found a chest, empty it before continuing
  377. emptyChest (suckFn)
  378. end
  379. end
  380.  
  381. -- Flag to determine whether digging has been tried yet. If it has
  382. -- then pause briefly before digging again to allow sand or gravel to
  383. -- drop
  384. local digCount = 0
  385. local moveSuccess = moveFn()
  386.  
  387. while ((moveSuccess == false) and (digCount < maxDigCount)) do
  388.  
  389. -- If there is a block in front, dig it
  390. if (detectFn() == true) then
  391.  
  392. -- If we've already tried digging, then pause before digging again to let
  393. -- any sand or gravel drop
  394. if(digCount > 0) then
  395. sleep(0.4)
  396. end
  397.  
  398. digFn()
  399. digCount = digCount + 1
  400. else
  401. -- Am being stopped from moving by a mob, attack it
  402. attackFn()
  403. end
  404.  
  405. -- Try the move again
  406. moveSuccess = moveFn()
  407. end
  408.  
  409. -- Return the move success
  410. return moveSuccess
  411.  
  412. end
  413.  
  414. -- ********************************************************************************** --
  415. -- Move the turtle forward one block (updating the turtle's position)
  416. -- ********************************************************************************** --
  417. function turtleForward()
  418. local returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.compare, turtle.suck, maximumGravelStackSupported)
  419. if (returnVal == true) then
  420. -- Update the current co-ordinates
  421. if (currOrient == direction.FORWARD) then
  422. currZ = currZ + 1
  423. elseif (currOrient == direction.LEFT) then
  424. currX = currX - 1
  425. elseif (currOrient == direction.BACK) then
  426. currZ = currZ - 1
  427. elseif (currOrient == direction.RIGHT) then
  428. currX = currX + 1
  429. else
  430. writeMessage ("Invalid currOrient in turtleForward function", messageLevel.ERROR)
  431. end
  432.  
  433. -- Check that there is sufficient inventory space as may have picked up a block
  434. ensureInventorySpace()
  435. end
  436.  
  437. return returnVal
  438. end
  439.  
  440. -- ********************************************************************************** --
  441. -- Move the turtle up one block (updating the turtle's position)
  442. -- ********************************************************************************** --
  443. function turtleUp()
  444. local returnVal = moveTurtle(turtle.up, turtle.detectUp, turtle.digUp, turtle.attackUp, turtle.compareUp, turtle.suckUp, maximumGravelStackSupported)
  445. if (returnVal == true) then
  446. currY = currY + 1
  447.  
  448. -- Check that there is sufficient inventory space as may have picked up a block
  449. ensureInventorySpace()
  450. end
  451. return returnVal
  452. end
  453.  
  454. -- ********************************************************************************** --
  455. -- Move the turtle down one block (updating the turtle's position)
  456. -- ********************************************************************************** --
  457. function turtleDown()
  458. local returnVal
  459.  
  460. -- Because the turtle is digging down, can fail fast (only allow 1 dig attempt).
  461. returnVal = moveTurtle(turtle.down, turtle.detectDown, turtle.digDown, turtle.attackDown, turtle.compareDown, turtle.suckDown, 1)
  462. if (returnVal == true) then
  463. currY = currY - 1
  464.  
  465. -- Check that there is sufficient inventory space as may have picked up a block
  466. ensureInventorySpace()
  467. end
  468. return returnVal
  469. end
  470.  
  471. -- ********************************************************************************** --
  472. -- Move the turtle back one block (updating the turtle's position)
  473. -- ********************************************************************************** --
  474. function turtleBack()
  475. -- First try to move back using the standard function
  476. local returnVal = turtle.back()
  477.  
  478. -- Moving back didn't work (might be a block or a mob in the way). Turn round and move
  479. -- forward instead (whereby anything in the way can be cleared)
  480. if(returnVal == false) then
  481. turtle.turnRight()
  482. turtle.turnRight()
  483. returnVal = turtleForward()
  484. turtle.turnRight()
  485. turtle.turnRight()
  486. end
  487.  
  488. if (returnVal == true) then
  489. -- Update the current co-ordinates
  490. if (currOrient == direction.FORWARD) then
  491. currZ = currZ - 1
  492. elseif (currOrient == direction.LEFT) then
  493. currX = currX + 1
  494. elseif (currOrient == direction.BACK) then
  495. currZ = currZ + 1
  496. elseif (currOrient == direction.RIGHT) then
  497. currX = currX - 1
  498. else
  499. writeMessage ("Invalid currOrient in turtleBack function", messageLevel.ERROR)
  500. end
  501.  
  502. -- Check that there is sufficient inventory space as may have picked up a block
  503. ensureInventorySpace()
  504. end
  505.  
  506. return returnVal
  507. end
  508.  
  509. -- ********************************************************************************** --
  510. -- Turns the turtle (updating the current orientation at the same time)
  511. -- ********************************************************************************** --
  512. function turtleTurn(turnDir)
  513.  
  514. if (turnDir == direction.LEFT) then
  515. if (currOrient == direction.FORWARD) then
  516. currOrient = direction.LEFT
  517. turtle.turnLeft()
  518. elseif (currOrient == direction.LEFT) then
  519. currOrient = direction.BACK
  520. turtle.turnLeft()
  521. elseif (currOrient == direction.BACK) then
  522. currOrient = direction.RIGHT
  523. turtle.turnLeft()
  524. elseif (currOrient == direction.RIGHT) then
  525. currOrient = direction.FORWARD
  526. turtle.turnLeft()
  527. else
  528. writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  529. end
  530. elseif (turnDir == direction.RIGHT) then
  531. if (currOrient == direction.FORWARD) then
  532. currOrient = direction.RIGHT
  533. turtle.turnRight()
  534. elseif (currOrient == direction.LEFT) then
  535. currOrient = direction.FORWARD
  536. turtle.turnRight()
  537. elseif (currOrient == direction.BACK) then
  538. currOrient = direction.LEFT
  539. turtle.turnRight()
  540. elseif (currOrient == direction.RIGHT) then
  541. currOrient = direction.BACK
  542. turtle.turnRight()
  543. else
  544. writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  545. end
  546. else
  547. writeMessage ("Invalid turnDir in turtleTurn function", messageLevel.ERROR)
  548. end
  549. end
  550.  
  551. -- ********************************************************************************** --
  552. -- Sets the turtle to a specific orientation, irrespective of its current orientation
  553. -- ********************************************************************************** --
  554. function turtleSetOrientation(newOrient)
  555.  
  556. if (currOrient ~= newOrient) then
  557. if (currOrient == direction.FORWARD) then
  558. if (newOrient == direction.RIGHT) then
  559. turtle.turnRight()
  560. currOrient = newOrient
  561. elseif (newOrient == direction.BACK) then
  562. turtle.turnRight()
  563. turtle.turnRight()
  564. currOrient = newOrient
  565. elseif (newOrient == direction.LEFT) then
  566. turtle.turnLeft()
  567. currOrient = newOrient
  568. else
  569. writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  570. end
  571. elseif (currOrient == direction.RIGHT) then
  572. if (newOrient == direction.BACK) then
  573. turtle.turnRight()
  574. currOrient = newOrient
  575. elseif (newOrient == direction.LEFT) then
  576. turtle.turnRight()
  577. turtle.turnRight()
  578. currOrient = newOrient
  579. elseif (newOrient == direction.FORWARD) then
  580. turtle.turnLeft()
  581. currOrient = newOrient
  582. else
  583. writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  584. end
  585. elseif (currOrient == direction.BACK) then
  586. if (newOrient == direction.LEFT) then
  587. turtle.turnRight()
  588. currOrient = newOrient
  589. elseif (newOrient == direction.FORWARD) then
  590. turtle.turnRight()
  591. turtle.turnRight()
  592. currOrient = newOrient
  593. elseif (newOrient == direction.RIGHT) then
  594. turtle.turnLeft()
  595. currOrient = newOrient
  596. else
  597. writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  598. end
  599. elseif (currOrient == direction.LEFT) then
  600. if (newOrient == direction.FORWARD) then
  601. turtle.turnRight()
  602. currOrient = newOrient
  603. elseif (newOrient == direction.RIGHT) then
  604. turtle.turnRight()
  605. turtle.turnRight()
  606. currOrient = newOrient
  607. elseif (newOrient == direction.BACK) then
  608. turtle.turnLeft()
  609. currOrient = newOrient
  610. else
  611. writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  612. end
  613. else
  614. writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  615. end
  616. end
  617. end
  618.  
  619. -- ********************************************************************************** --
  620. -- Determines if a particular block is considered a noise block or not. A noise
  621. -- block is one that is a standard block in the game (stone, dirt, gravel etc.) and
  622. -- is one to ignore when a seam is being dug out. Function works by comparing the block
  623. -- in question against a set of blocks in the turtle's inventory which are known not to
  624. -- be noise blocks. The first parameter is the number of slots containing noise blocks
  625. -- (these must be at the start of the turtle's inventory), and the second param is the
  626. -- function to use to compare the block for a noise block
  627. -- ********************************************************************************** --
  628. function isNoiseBlock(detectFn, compareFn)
  629.  
  630. -- Consider air to be a noise block
  631. local returnVal = not detectFn()
  632. local seamLoop = 1
  633.  
  634. while((returnVal == false) and (seamLoop <= nonSeamBlocks)) do
  635. turtle.select(seamLoop)
  636. returnVal = compareFn()
  637. seamLoop = seamLoop + 1
  638. end
  639.  
  640. -- Return the calculated value
  641. return returnVal
  642.  
  643. end
  644.  
  645. -- ********************************************************************************** --
  646. -- Determines if a particular block is a chest. Returns false if it is not a chest
  647. -- or chests are not being detected
  648. -- ********************************************************************************** --
  649. function isChestBlock(compareFn)
  650.  
  651. -- Check the block in the appropriate direction to see whether it is a chest. Only
  652. -- do this if we are looking for chests
  653. local returnVal = false
  654. if (lookForChests == true) then
  655. turtle.select(15)
  656. returnVal = compareFn()
  657. end
  658.  
  659. -- Return the calculated value
  660. return returnVal
  661.  
  662. end
  663.  
  664. -- ********************************************************************************** --
  665. -- Function to calculate the number of non seam blocks in the turtle's inventory. This
  666. -- is all of the blocks at the start of the inventory (before the first empty slot is
  667. -- found
  668. -- ********************************************************************************** --
  669. function determineNonSeamBlocksCount()
  670. -- Determine the location of the first empty inventory slot. All items before this represent
  671. -- noise items.
  672. local foundFirstBlankInventorySlot = false
  673. nonSeamBlocks = 1
  674. while ((nonSeamBlocks < 16) and (foundFirstBlankInventorySlot == false)) do
  675. if (turtle.getItemCount(nonSeamBlocks) > 0) then
  676. nonSeamBlocks = nonSeamBlocks + 1
  677. else
  678. foundFirstBlankInventorySlot = true
  679. end
  680. end
  681. nonSeamBlocks = nonSeamBlocks - 1
  682.  
  683. -- Determine whether a chest was provided, and hence whether we should support
  684. -- looking for chests
  685. if (turtle.getItemCount(15) > 0) then
  686. lookForChests = true
  687. lastEmptySlot = 14
  688. writeMessage("Looking for chests...", messageLevel.DEBUG)
  689. else
  690. lastEmptySlot = 15
  691. writeMessage("Ignoring chests...", messageLevel.DEBUG)
  692. end
  693. end
  694.  
  695. -- ********************************************************************************** --
  696. -- Creates a quarry mining out only ores and leaving behind any noise blocks
  697. -- ********************************************************************************** --
  698. function createQuarry()
  699.  
  700. -- Determine the starting layer. The turtle mines in layers of 3, and the bottom layer
  701. -- is the layer directly above bedrock.
  702. --
  703. -- The actual layer that the turtle operates in is the middle of these three layers,
  704. -- so determine the top layer
  705. local firstMiningLayer = startHeight + ((bottomLayer - startHeight - 2) % 3) - 1
  706.  
  707. -- If the top layer is up, then ignore it and move to the next layer
  708. if (firstMiningLayer > currY) then
  709. firstMiningLayer = firstMiningLayer - 3
  710. end
  711.  
  712. local miningLoop
  713. local firstTimeThru = true
  714. local onNearSideOfQuarry = true
  715. local diggingAway = true
  716.  
  717. -- Loop over each mining row
  718. for miningLoop = firstMiningLayer, bottomLayer, -3 do
  719. writeMessage("Mining Layer: "..miningLoop, messageLevel.INFO)
  720.  
  721. -- Move to the correct level to start mining
  722. if (currY > miningLoop) then
  723. while (currY > miningLoop) do
  724. turtleDown()
  725. end
  726. end
  727.  
  728. -- Move turtle into the correct orientation to start mining
  729. if (firstTimeThru == true) then
  730. turtleTurn(direction.RIGHT)
  731. firstTimeThru = false
  732. else
  733. turtleTurn(direction.LEFT)
  734. turtleTurn(direction.LEFT)
  735. end
  736.  
  737. local firstRow = true
  738. local mineRows
  739. for mineRows = 1, quarryWidth do
  740. -- If this is not the first row, then get into position to mine the next row
  741. if (firstRow == true) then
  742. firstRow = false
  743. else
  744. -- Move into position for mining the next row
  745. if (onNearSideOfQuarry == diggingAway) then
  746. turtleTurn(direction.RIGHT)
  747. else
  748. turtleTurn(direction.LEFT)
  749. end
  750.  
  751. turtleForward()
  752. if (isChestBlock(turtle.compareUp) == true) then
  753. -- There is a chest block above. Move back and approach
  754. -- from the side to ensure that we don't need to return to
  755. -- start through the chest itself (potentially losing items)
  756. turtleBack()
  757. turtleUp()
  758. emptyChest(turtle.suck)
  759. turtleDown()
  760. turtleForward()
  761. end
  762.  
  763. -- Move into final position for mining the next row
  764. if (onNearSideOfQuarry == diggingAway) then
  765. turtleTurn(direction.RIGHT)
  766. else
  767. turtleTurn(direction.LEFT)
  768. end
  769. end
  770.  
  771. -- Dig to the other side of the quarry
  772. local blocksMined
  773. for blocksMined = 0, (quarryWidth - 1) do
  774. -- Move forward and check for ores
  775. if(blocksMined > 0) then
  776. -- Only move forward if this is not the first space
  777. turtleForward()
  778. end
  779.  
  780. -- Check upwards for a chest block if this is not the first block of the
  781. -- row (in which case it will have already been checked)
  782. if(blocksMined > 0) then
  783. if (isChestBlock(turtle.compareUp) == true) then
  784. -- There is a chest block above. Move back and approach
  785. -- from the side to ensure that we don't need to return to
  786. -- start through the chest itself (potentially losing items)
  787. turtleBack()
  788. turtleUp()
  789. emptyChest(turtle.suck)
  790. turtleDown()
  791. turtleForward()
  792. end
  793. end
  794.  
  795. if (isNoiseBlock(turtle.detectUp, turtle.compareUp) == false) then
  796. turtle.digUp()
  797. ensureInventorySpace()
  798. end
  799.  
  800. -- Check down, if this is the bedrock layer, use an alternate approach.
  801. -- If this is not the bedrock layer, then just check down
  802. if (miningLoop == bottomLayer) then
  803. -- Just above bedrock layer, dig down until can't dig any lower, and then
  804. -- come back up. This replicates how the quarry functions
  805. local moveDownSuccess = turtleDown()
  806. while (moveDownSuccess == true) do
  807. moveDownSuccess = turtleDown()
  808. end
  809.  
  810. -- Have now hit bedrock, move back to the mining layer
  811. writeMessage("Moving back to mining layer", messageLevel.DEBUG)
  812. writeMessage("currY: "..currY..", bottomLayer: "..bottomLayer, messageLevel.DEBUG)
  813. while (currY < bottomLayer) do
  814. turtleUp()
  815. end
  816. else
  817. -- Check the block down for being a chest
  818. if (isChestBlock(turtle.compareDown) == true) then
  819. emptyChest(turtle.suckDown)
  820. end
  821.  
  822. -- Check the block down and mine if necessary
  823. if (isNoiseBlock(turtle.detectDown, turtle.compareDown) == false) then
  824. turtle.digDown()
  825. ensureInventorySpace()
  826. end
  827. end
  828. end
  829.  
  830. -- Am now at the other side of the quarry
  831. onNearSideOfQuarry = not onNearSideOfQuarry
  832. end
  833.  
  834. -- If we were digging away from the starting point, will be digging
  835. -- back towards it on the next layer
  836. diggingAway = not diggingAway
  837. end
  838.  
  839. -- Return to the start
  840. returnToStartAndUnload(false)
  841.  
  842. -- Face forward
  843. turtleSetOrientation(direction.FORWARD)
  844. end
  845.  
  846. -- ********************************************************************************** --
  847. -- Main Function
  848. -- ********************************************************************************** --
  849. -- Process the input arguments - storing them to global variables
  850. local args = { ... }
  851. local paramsOK = true
  852. turtleId = os.getComputerLabel()
  853. rednet.open("right")
  854. if (#args == 1) then
  855. quarryWidth = tonumber(args[1])
  856. local x, y, z = gps.locate(5)
  857. startHeight = y
  858. if (startHeight == nil) then
  859. writeMessage("Can't locate GPS", messageLevel.FATAL)
  860. paramsOK = false
  861. end
  862. elseif (#args == 2) then
  863. quarryWidth = tonumber(args[1])
  864. startHeight = tonumber(args[2])
  865. else
  866. writeMessage("Usage: OreQuarry <diameter> <turtleY>", messageLevel.FATAL)
  867. paramsOK = false
  868. end
  869. if (paramsOK == true) then
  870. if ((startHeight < 6) or (startHeight > 128)) then
  871. writeMessage("turtleY must be between 6 and 128", messageLevel.FATAL)
  872. paramsOK = false
  873. end
  874.  
  875. if ((quarryWidth < 2) or (quarryWidth > 64)) then
  876. writeMessage("diameter must be between 2 and 64", messageLevel.FATAL)
  877. paramsOK = false
  878. end
  879. end
  880.  
  881. if (paramsOK == true) then
  882. writeMessage("---------------------------------", messageLevel.INFO)
  883. writeMessage("** Ore Quarry v0.2 by AustinKK **", messageLevel.INFO)
  884. writeMessage("---------------------------------", messageLevel.INFO)
  885.  
  886. -- Set the turtle's starting position
  887. currX = 0
  888. currY = startHeight
  889. currZ = 0
  890. currOrient = direction.FORWARD
  891.  
  892. -- Calculate which blocks in the inventory signify noise blocks
  893. determineNonSeamBlocksCount()
  894.  
  895. if ((nonSeamBlocks == 0) or (nonSeamBlocks == 15)) then
  896. 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)
  897. else
  898. -- Create a Quary
  899. createQuarry()
  900. end
  901. end
Add Comment
Please, Sign In to add comment