Advertisement
Guest User

Untitled

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