Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- ********************************************************************************** --
- -- ** ** --
- -- ** Minecraft Mining Turtle Ore Quarry v1.00 by AustinKK ** --
- -- ** ---------------------------------------------------- ** --
- -- ** ** --
- -- ** Rewritten by KeldonSlayer ** --
- -- ********************************************************************************** --
- -- ********************************************************************************** --
- -- Note: If you are in a world with flat bedrock, change the value below from -60 to -64.
- -- You don't need to change this, but the turtle is slightly faster if you do.
- -- ********************************************************************************** --
- local bottomLayer = -60 -- The y co-ords of the layer immediately above bedrock
- -- Enumeration to store the the different types of message that can be written
- messageLevel = { DEBUG=0, INFO=1, WARNING=2, ERROR=3, FATAL=4 }
- -- Enumeration to store names for the 6 directions
- direction = { FORWARD=0, RIGHT=1, BACK=2, LEFT=3, UP=4, DOWN=5 }
- -- Enumeration of mining states
- miningState = { START=0, LAYER=1, EMPTYCHESTDOWN=2, EMPTYINVENTORY=3 }
- local messageOutputLevel = messageLevel.INFO
- local messageOutputFileName
- local fuelLevelToRefuelAt = 5
- local refuelItemsToUseWhenRefuelling = 63
- local emergencyFuelToRetain = 0
- local maximumGravelStackSupported = 25 -- The number of stacked gravel or sand blocks supported
- local noiseBlocksCount
- local returningToStart = false
- local lookForChests = false -- Determines if chests should be located as part of the quarrying
- local miningOffset -- The offset to the mining layer. This is set depending on whether chests are being looked for or not
- 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)
- local turtleId
- local isWirelessTurtle
- local currentlySelectedSlot = 0 -- The slot that the last noise block was found in
- local lastMoveNeededDig = true -- Determines whether the last move needed a dig first
- local haveBeenAtZeroZeroOnLayer -- Determines whether the turtle has been at (0, 0) in this mining layer
- local orientationAtZeroZero -- The turtle's orientation when it was at (0, 0)
- local levelToReturnTo -- The level that the turtle should return to in order to head back to the start to unload
- -- Variables used to support a resume
- local startupParamsFile = "OreQuarryParams.txt"
- local oreQuarryLocation = "OreQuarryLocation.txt"
- local returnToStartFile = "OreQuarryReturn.txt"
- local startupBackup = "startup_bak"
- local supportResume = true -- Determines whether the turtle is being run in the mode that supports resume
- local resuming = false -- Determines whether the turtle is currently in the process of resuming
- local resumeX
- local resumeY
- local resumeZ
- local resumeOrient
- local resumeMiningState
- -- Variables to store the current location and orientation of the turtle. x is right, left, y is up, down and
- -- z is forward, back with relation to the starting orientation. Y is the actual turtle level, x and z are
- -- in relation to the starting point (i.e. the starting point is (0, 0))
- local currX
- local currY
- local currZ
- local currOrient
- local currMiningState = miningState.START
- local lastNoiseSlot = 1
- -- Customizable List of Noise Items
- -- These will be discarded from turtle inventory
- -- The turtle will also avoid mining if possible
- local noise = {
- ["minecraft:stone"] = true,
- ["minecraft:grass"] = true,
- ["minecraft:dirt"] = true,
- ["minecraft:sand"] = true,
- ["minecraft:sandstone"] = true,
- ["minecraft:gravel"] = true,
- ["minecraft:cobblestone"] = true,
- ["minecraft:diorite"] = true,
- ["minecraft:andesite"] = true,
- ["minecraft:granite"] = true,
- ["minecraft:deepslate"] = true,
- ["minecraft:cobbled_deepslate"] = true,
- ["minecraft:mossy_cobblestone"] = true
- }
- -- Command line parameters
- local startHeight -- Represents the height (y co-ord) that the turtle started at
- local quarryWidth -- Represents the length of the mines that the turtle will dig
- -- ********************************************************************************** --
- -- Writes an output message
- -- ********************************************************************************** --
- function writeMessage(message, msgLevel)
- if (msgLevel >= messageOutputLevel) then
- print(message)
- -- If this turtle has a modem, then write the message to red net
- if (isWirelessTurtle == true) then
- if (turtleId == nil) then
- rednet.broadcast(message)
- else
- -- Broadcast the message (prefixed with the turtle's id)
- rednet.broadcast("[".. turtleId.."] "..message)
- end
- end
- if (messageOutputFileName ~= nil) then
- -- Open file, write message and close file (flush doesn't seem to work!)
- local outputFile
- if (fs.exists(messageOutputFileName) == true) then
- outputFile = io.open(messageOutputFileName, "a")
- else
- outputFile = io.open(messageOutputFileName, "w")
- end
- outputFile:write(message)
- outputFile:write("\n")
- outputFile:close()
- end
- end
- end
- -- ********************************************************************************** --
- -- Ensures that the turtle has fuel
- -- ********************************************************************************** --
- function ensureFuel()
- -- Determine whether a refuel is required
- local fuelLevel = turtle.getFuelLevel()
- if (fuelLevel ~= "unlimited") then
- if (fuelLevel < fuelLevelToRefuelAt) then
- -- Need to refuel
- turtle.select(16)
- currentlySelectedSlot = 16
- local fuelItems = turtle.getItemCount(16)
- -- Do we need to impact the emergency fuel to continue? (always
- -- keep one fuel item in slot 16)
- if (fuelItems == 0) then
- writeMessage("Completely out of fuel!", messageLevel.FATAL)
- elseif (fuelItems == 1) then
- writeMessage("Out of Fuel!", messageLevel.ERROR)
- turtle.refuel()
- elseif (fuelItems <= (emergencyFuelToRetain + 1)) then
- writeMessage("Consuming emergency fuel supply. "..(fuelItems - 2).." emergency fuel items remain", messageLevel.WARNING)
- turtle.refuel(1)
- else
- -- Refuel the lesser of the refuelItemsToUseWhenRefuelling and the number of items more than
- -- the emergency fuel level
- if (fuelItems - (emergencyFuelToRetain + 1) < refuelItemsToUseWhenRefuelling) then
- turtle.refuel(fuelItems - (emergencyFuelToRetain + 1))
- else
- turtle.refuel(refuelItemsToUseWhenRefuelling)
- end
- end
- end
- end
- end
- -- ********************************************************************************** --
- -- Checks that the turtle has inventory space by checking for spare slots and returning
- -- to the starting point to empty out if it doesn't.
- --
- -- Takes the position required to move to in order to empty the turtle's inventory
- -- should it be full as arguments
- -- ********************************************************************************** --
- function ensureInventorySpace()
- -- If already returning to start, then don't need to do anything
- if (returningToStart == false) then
- clearNoiseItems()
- -- If the last inventory slot is full, then need to return to the start and empty
- if (turtle.getItemCount(lastEmptySlot) > 0) then
- -- Return to the starting point and empty the inventory, then go back to mining
- returnToStartAndUnload(true)
- end
- end
- end
- -- ********************************************************************************** --
- -- Checks items in slots to find trash, and disposes of them to preserve inventory
- -- ********************************************************************************** --
- function clearNoiseItems()
- local lastSlt = turtle.getSelectedSlot()
- for slot = lastNoiseSlot, 16 do
- turtle.select(slot)
- local idetail = turtle.getItemDetail()
- if (idetail == nil) then
- lastNoiseSlot = slot
- turtle.select(lastSlt)
- return
- end
- for k, v in pairs(noise) do
- if idetail.name == k then
- turtle.drop()
- lastNoiseSlot = slot
- turtle.select(lastSlt)
- return
- end
- end
- end
- turtle.select(lastSlt)
- end
- -- ********************************************************************************** --
- -- Function to move to the starting point, call a function that is passed in
- -- and return to the same location (if required)
- -- ********************************************************************************** --
- function returnToStartAndUnload(returnBackToMiningPoint)
- writeMessage("returnToStartAndUnload called", messageLevel.DEBUG)
- returningToStart = true
- local storedX, storedY, storedZ, storedOrient
- local prevMiningState = currMiningState
- if (resuming == true) then
- -- Get the stored parameters from the necessary file
- local resumeFile = fs.open(returnToStartFile, "r")
- if (resumeFile ~= nil) then
- -- Restore the parameters from the file
- local beenAtZero = resumeFile.readLine()
- if (beenAtZero == "y") then
- haveBeenAtZeroZeroOnLayer = true
- else
- haveBeenAtZeroZeroOnLayer = false
- end
- local miningPointFlag = resumeFile.readLine()
- if (miningPointFlag == "y") then
- returnBackToMiningPoint = true
- else
- returnBackToMiningPoint = false
- end
- currX = readNumber(resumeFile)
- currY = readNumber(resumeFile)
- currZ = readNumber(resumeFile)
- currOrient = readNumber(resumeFile)
- levelToReturnTo = readNumber(resumeFile)
- prevMiningState = readNumber(resumeFile)
- orientationAtZeroZero = readNumber(resumeFile)
- resumeFile.close()
- else
- writeMessage("Failed to read return to start file", messageLevel.ERROR)
- end
- elseif (supportResume == true) then
- local outputFile = io.open(returnToStartFile, "w")
- if (haveBeenAtZeroZeroOnLayer == true) then
- outputFile:write("y\n")
- else
- outputFile:write("n\n")
- end
- if (returnBackToMiningPoint == true) then
- outputFile:write("y\n")
- else
- outputFile:write("n\n")
- end
- outputFile:write(currX)
- outputFile:write("\n")
- outputFile:write(currY)
- outputFile:write("\n")
- outputFile:write(currZ)
- outputFile:write("\n")
- outputFile:write(currOrient)
- outputFile:write("\n")
- outputFile:write(levelToReturnTo)
- outputFile:write("\n")
- outputFile:write(prevMiningState)
- outputFile:write("\n")
- outputFile:write(orientationAtZeroZero)
- outputFile:write("\n")
- outputFile:close()
- end
- storedX = currX
- storedY = currY
- storedZ = currZ
- storedOrient = currOrient
- -- Store the current location and orientation so that it can be returned to
- currMiningState = miningState.EMPTYINVENTORY
- writeMessage("last item count = "..turtle.getItemCount(lastEmptySlot), messageLevel.DEBUG)
- if ((turtle.getItemCount(lastEmptySlot) > 0) or (returnBackToMiningPoint == false)) then
- writeMessage("Heading back to surface", messageLevel.DEBUG)
- -- Move down to the correct layer to return via
- if (currY > levelToReturnTo) then
- while (currY > levelToReturnTo) do
- turtleDown()
- end
- elseif (currY < levelToReturnTo) then
- while (currY < levelToReturnTo) do
- turtleUp()
- end
- end
- if ((haveBeenAtZeroZeroOnLayer == false) or (orientationAtZeroZero == direction.FORWARD)) then
- -- Move back to the correct X position first
- if (currX > 0) then
- turtleSetOrientation(direction.LEFT)
- while (currX > 0) do
- turtleForward()
- end
- elseif (currX < 0) then
- -- This should never happen
- writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
- end
- -- Then move back to the correct Z position
- if (currZ > 0) then
- turtleSetOrientation(direction.BACK)
- while (currZ > 0) do
- turtleForward()
- end
- elseif (currZ < 0) then
- -- This should never happen
- writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
- end
- else
- -- Move back to the correct Z position first
- if (currZ > 0) then
- turtleSetOrientation(direction.BACK)
- while (currZ > 0) do
- turtleForward()
- end
- elseif (currZ < 0) then
- -- This should never happen
- writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
- end
- -- Then move back to the correct X position
- if (currX > 0) then
- turtleSetOrientation(direction.LEFT)
- while (currX > 0) do
- turtleForward()
- end
- elseif (currX < 0) then
- -- This should never happen
- writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
- end
- end
- -- Return to the starting layer
- if (currY < startHeight) then
- while (currY < startHeight) do
- turtleUp()
- end
- elseif (currY > startHeight) then
- -- This should never happen
- writeMessage("Current height is greater than start height in returnToStartAndUnload", messageLevel.ERROR)
- end
- -- Empty the inventory
- local slotLoop = 1
- -- Face the chest
- turtleSetOrientation(direction.BACK)
- -- Loop over each of the slots (except the 16th one which stores fuel)
- while (slotLoop < 16) do
- turtle.select(slotLoop) -- Don't bother updating selected slot variable as it will set later in this function
- -- Drop all of the items in this slot
- writeMessage("Dropping (all) from slot "..slotLoop.." ["..turtle.getItemCount(slotLoop).."]", messageLevel.DEBUG)
- if (turtle.getItemCount(slotLoop) > 0) then
- turtle.drop()
- end
- slotLoop = slotLoop + 1
- end
- lastNoiseSlot = 1
- -- While we are here, refill the fuel items if there is capacity
- if (turtle.getItemCount(16) < 64) then
- turtleSetOrientation(direction.LEFT)
- turtle.select(16) -- Don't bother updating selected slot variable as it will set later in this function
- local currFuelItems = turtle.getItemCount(16)
- turtle.suck()
- while ((currFuelItems ~= turtle.getItemCount(16)) and (turtle.getItemCount(16) < 64)) do
- currFuelItems = turtle.getItemCount(16)
- turtle.suck()
- end
- slotLoop = noiseBlocksCount + 1
- -- Have now picked up all the items that we can. If we have also picked up some
- -- additional fuel in some of the other slots, then drop it again
- while (slotLoop <= lastEmptySlot) do
- -- Drop any items found in this slot
- if (turtle.getItemCount(slotLoop) > 0) then
- turtle.select(slotLoop) -- Don't bother updating selected slot variable as it will set later in this function
- turtle.drop()
- end
- slotLoop = slotLoop + 1
- end
- end
- -- Select the 1st slot because sometimes when leaving the 15th or 16th slots selected it can result
- -- in that slot being immediately filled (resulting in the turtle returning to base again too soon)
- turtle.select(1)
- currentlySelectedSlot = 1
- end
- -- If required, move back to the point that we were mining at before returning to the start
- if (returnBackToMiningPoint == true) then
- -- If resuming, refresh the starting point to be the top of the return shaft
- if (resuming == true) then
- currX = 0
- currY = startHeight
- currZ = 0
- currOrient = resumeOrient
- end
- -- Return back to the required layer
- while (currY > levelToReturnTo) do
- turtleDown()
- end
- if ((haveBeenAtZeroZeroOnLayer == false) or (orientationAtZeroZero == direction.FORWARD)) then
- -- Move back to the correct Z position first
- writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
- if (storedZ > currZ) then
- writeMessage("Orienting forward", messageLevel.DEBUG)
- writeMessage("Moving in z direction", messageLevel.DEBUG)
- turtleSetOrientation(direction.FORWARD)
- while (storedZ > currZ) do
- turtleForward()
- end
- elseif (storedZ < currZ) then
- -- This should never happen
- writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
- end
- -- Then move back to the correct X position
- if (storedX > currX) then
- writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
- writeMessage("Orienting right", messageLevel.DEBUG)
- writeMessage("Moving in x direction", messageLevel.DEBUG)
- turtleSetOrientation(direction.RIGHT)
- while (storedX > currX) do
- turtleForward()
- end
- elseif (storedX < currX) then
- -- This should never happen
- writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
- end
- else
- -- Move back to the correct X position first
- if (storedX > currX) then
- writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
- writeMessage("Orienting right", messageLevel.DEBUG)
- writeMessage("Moving in x direction", messageLevel.DEBUG)
- turtleSetOrientation(direction.RIGHT)
- while (storedX > currX) do
- turtleForward()
- end
- elseif (storedX < currX) then
- -- This should never happen
- writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
- end
- -- Then move back to the correct Z position
- writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
- if (storedZ > currZ) then
- writeMessage("Orienting forward", messageLevel.DEBUG)
- writeMessage("Moving in z direction", messageLevel.DEBUG)
- turtleSetOrientation(direction.FORWARD)
- while (storedZ > currZ) do
- turtleForward()
- end
- elseif (storedZ < currZ) then
- -- This should never happen
- writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
- end
- end
- -- Move back to the correct layer
- if (storedY < currY) then
- while (storedY < currY) do
- turtleDown()
- end
- elseif (storedY > currY) then
- while (storedY > currY) do
- turtleUp()
- end
- end
- -- Finally, set the correct orientation
- turtleSetOrientation(storedOrient)
- writeMessage("Have returned to the mining point", messageLevel.DEBUG)
- end
- -- Store the current location and orientation so that it can be returned to
- currMiningState = prevMiningState
- returningToStart = false
- end
- -- ********************************************************************************** --
- -- Empties a chest's contents
- -- ********************************************************************************** --
- function emptyChest(suckFn)
- local prevInventoryCount = {}
- local inventoryLoop
- local chestEmptied = false
- -- Record the number of items in each of the inventory slots
- for inventoryLoop = 1, 16 do
- prevInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
- end
- while (chestEmptied == false) do
- -- Pick up the next item
- suckFn()
- -- Determine the number of items in each of the inventory slots now
- local newInventoryCount = {}
- for inventoryLoop = 1, 16 do
- newInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
- end
- -- Now, determine whether there have been any items taken from the chest
- local foundDifferentItemCount = false
- inventoryLoop = 1
- while ((foundDifferentItemCount == false) and (inventoryLoop <= 16)) do
- if (prevInventoryCount[inventoryLoop] ~= newInventoryCount[inventoryLoop]) then
- foundDifferentItemCount = true
- else
- inventoryLoop = inventoryLoop + 1
- end
- end
- -- If no items have been found with a different item count, then the chest has been emptied
- chestEmptied = not foundDifferentItemCount
- if (chestEmptied == false) then
- prevInventoryCount = newInventoryCount
- -- Check that there is sufficient inventory space as may have picked up a block
- ensureInventorySpace()
- end
- end
- writeMessage("Finished emptying chest", messageLevel.DEBUG)
- end
- -- ********************************************************************************** --
- -- Write the current location to a file
- -- ********************************************************************************** --
- function saveLocation()
- -- Write the x, y, z and orientation to the file
- if ((supportResume == true) and (resuming == false)) then
- local outputFile = io.open(oreQuarryLocation, "w")
- outputFile:write(currMiningState)
- outputFile:write("\n")
- outputFile:write(currX)
- outputFile:write("\n")
- outputFile:write(currY)
- outputFile:write("\n")
- outputFile:write(currZ)
- outputFile:write("\n")
- outputFile:write(currOrient)
- outputFile:write("\n")
- outputFile:close()
- end
- end
- -- ********************************************************************************** --
- -- If the turtle is resuming and the current co-ordinates, orientation and
- -- mining state have been matched, then no longer resuming
- -- ********************************************************************************** --
- function updateResumingFlag()
- if (resuming == true) then
- if ((resumeMiningState == currMiningState) and (resumeX == currX) and (resumeY == currY) and (resumeZ == currZ) and (resumeOrient == currOrient)) then
- resuming = false
- end
- end
- end
- -- ********************************************************************************** --
- -- Generic function to move the Turtle (pushing through any gravel or other
- -- things such as mobs that might get in the way).
- --
- -- The only thing that should stop the turtle moving is bedrock. Where this is
- -- found, the function will return after 15 seconds returning false
- -- ********************************************************************************** --
- function moveTurtle(moveFn, detectFn, digFn, attackFn, compareFn, suckFn, maxDigCount, newX, newY, newZ)
- local moveSuccess = false
- -- If we are resuming, then don't do anything in this function other than updating the
- -- co-ordinates as if the turtle had moved
- if (resuming == true) then
- -- Set the move success to true (but don't move) - unless this is below bedrock level
- -- in which case return false
- if (currY <= 0) then
- moveSuccess = false
- else
- moveSuccess = true
- end
- -- Update the co-ordinates to reflect the movement
- currX = newX
- currY = newY
- currZ = newZ
- else
- local prevX, prevY, prevZ
- prevX = currX
- prevY = currY
- prevZ = currZ
- ensureFuel()
- -- Flag to determine whether digging has been tried yet. If it has
- -- then pause briefly before digging again to allow sand or gravel to
- -- drop
- local digCount = 0
- if (lastMoveNeededDig == false) then
- -- Didn't need to dig last time the turtle moved, so try moving first
- currX = newX
- currY = newY
- currZ = newZ
- saveLocation()
- moveSuccess = moveFn()
- -- If move failed, update the co-ords back to the previous co-ords
- if (moveSuccess == false) then
- currX = prevX
- currY = prevY
- currZ = prevZ
- saveLocation()
- end
- -- Don't need to set the last move needed dig. It is already false, if
- -- move success is now true, then it won't be changed
- else
- -- If we are looking for chests, then check that this isn't a chest before trying to dig it
- if (lookForChests == true) then
- if (isNoiseBlock(compareFn) == false) then
- if (detectFn() == true) then
- -- Determine if it is a chest before digging it
- if (isChestBlock(compareFn) == true) then
- -- Have found a chest, empty it before continuing
- emptyChest (suckFn)
- end
- end
- end
- end
- -- Try to dig (without doing a detect as it is quicker)
- local digSuccess = digFn()
- if (digSuccess == true) then
- digCount = 1
- end
- currX = newX
- currY = newY
- currZ = newZ
- saveLocation()
- moveSuccess = moveFn()
- if (moveSuccess == true) then
- lastMoveNeededDig = digSuccess
- else
- currX = prevX
- currY = prevY
- currZ = prevZ
- saveLocation()
- end
- end
- -- Loop until we've successfully moved
- if (moveSuccess == false) then
- while ((moveSuccess == false) and (digCount < maxDigCount)) do
- -- If there is a block in front, dig it
- if (detectFn() == true) then
- -- If we've already tried digging, then pause before digging again to let
- -- any sand or gravel drop, otherwise check for a chest before digging
- if(digCount == 0) then
- -- Am about to dig a block - check that it is not a chest if necessary
- -- If we are looking for chests, then check that this isn't a chest before moving
- if (lookForChests == true) then
- if (isNoiseBlock(compareFn) == false) then
- if (detectFn() == true) then
- -- Determine if it is a chest before digging it
- if (isChestBlock(compareFn) == true) then
- -- Have found a chest, empty it before continuing
- emptyChest (suckFn)
- end
- end
- end
- end
- else
- sleep(0.1)
- end
- digFn()
- digCount = digCount + 1
- else
- -- Am being stopped from moving by a mob, attack it
- attackFn()
- end
- currX = newX
- currY = newY
- currZ = newZ
- saveLocation()
- -- Try the move again
- moveSuccess = moveFn()
- if (moveSuccess == false) then
- currX = prevX
- currY = prevY
- currZ = prevZ
- saveLocation()
- end
- end
- if (digCount == 0) then
- lastMoveNeededDig = false
- else
- lastMoveNeededDig = true
- end
- end
- end
- -- If we are resuming and the current co-ordinates and orientation are the resume point
- -- then are no longer resuming
- if (moveSuccess == true) then
- updateResumingFlag()
- end
- -- Return the move success
- return moveSuccess
- end
- -- ********************************************************************************** --
- -- Move the turtle forward one block (updating the turtle's position)
- -- ********************************************************************************** --
- function turtleForward()
- -- Determine the new co-ordinate that the turtle will be moving to
- local newX, newZ
- -- Update the current co-ordinates
- if (currOrient == direction.FORWARD) then
- newZ = currZ + 1
- newX = currX
- elseif (currOrient == direction.LEFT) then
- newX = currX - 1
- newZ = currZ
- elseif (currOrient == direction.BACK) then
- newZ = currZ - 1
- newX = currX
- elseif (currOrient == direction.RIGHT) then
- newX = currX + 1
- newZ = currZ
- else
- writeMessage ("Invalid currOrient in turtleForward function", messageLevel.ERROR)
- end
- local returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.inspect, turtle.suck, maximumGravelStackSupported, newX, currY, newZ)
- if (returnVal == true) then
- -- Check that there is sufficient inventory space as may have picked up a block
- ensureInventorySpace()
- end
- return returnVal
- end
- -- ********************************************************************************** --
- -- Move the turtle up one block (updating the turtle's position)
- -- ********************************************************************************** --
- function turtleUp()
- local returnVal = moveTurtle(turtle.up, turtle.detectUp, turtle.digUp, turtle.attackUp, turtle.inspectUp, turtle.suckUp, maximumGravelStackSupported, currX, currY + 1, currZ)
- if (returnVal == true) then
- -- Check that there is sufficient inventory space as may have picked up a block
- ensureInventorySpace()
- end
- return returnVal
- end
- -- ********************************************************************************** --
- -- Move the turtle down one block (updating the turtle's position)
- -- ********************************************************************************** --
- function turtleDown()
- local returnVal = moveTurtle(turtle.down, turtle.detectDown, turtle.digDown, turtle.attackDown, turtle.inspectDown, turtle.suckDown, 1, currX, currY - 1, currZ)
- if (returnVal == true) then
- -- Check that there is sufficient inventory space as may have picked up a block
- ensureInventorySpace()
- end
- return returnVal
- end
- -- ********************************************************************************** --
- -- Move the turtle back one block (updating the turtle's position)
- -- ********************************************************************************** --
- function turtleBack()
- -- Assume that the turtle will move, and switch the co-ords back if it doesn't
- -- (do this so that we can write the co-ords to a file before moving)
- local newX, newZ
- local prevX, prevZ
- prevX = currX
- prevZ = currZ
- -- Update the current co-ordinates
- if (currOrient == direction.FORWARD) then
- newZ = currZ - 1
- newX = currX
- elseif (currOrient == direction.LEFT) then
- newX = currX + 1
- newZ = currZ
- elseif (currOrient == direction.BACK) then
- newZ = currZ + 1
- newX = currX
- elseif (currOrient == direction.RIGHT) then
- newX = currX - 1
- newZ = currZ
- else
- writeMessage ("Invalid currOrient in turtleBack function", messageLevel.ERROR)
- end
- -- First try to move back using the standard function
- currX = newX
- currZ = newZ
- saveLocation()
- local returnVal = turtle.back()
- if (returnVal == false) then
- -- Didn't move. Reset the co-ordinates to the previous value
- currX = prevX
- currZ = prevZ
- -- Reset the location back to the previous location (because the turn takes 0.8 of a second
- -- so could be stopped before getting to the forward function)
- saveLocation()
- turtle.turnRight()
- turtle.turnRight()
- -- Try to move by using the forward function (note, the orientation will be set as
- -- the same way as this function started because if the function stops, that is the
- -- direction that we want to consider the turtle to be pointing)
- returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.inspect, turtle.suck, maximumGravelStackSupported, newX, currY, newZ)
- turtle.turnRight()
- turtle.turnRight()
- end
- if (returnVal == true) then
- -- Check that there is sufficient inventory space as may have picked up a block
- ensureInventorySpace()
- end
- return returnVal
- end
- -- ********************************************************************************** --
- -- Turns the turtle (updating the current orientation at the same time)
- -- ********************************************************************************** --
- function turtleTurn(turnDir)
- if (turnDir == direction.LEFT) then
- if (currOrient == direction.FORWARD) then
- currOrient = direction.LEFT
- elseif (currOrient == direction.LEFT) then
- currOrient = direction.BACK
- elseif (currOrient == direction.BACK) then
- currOrient = direction.RIGHT
- elseif (currOrient == direction.RIGHT) then
- currOrient = direction.FORWARD
- else
- writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
- end
- -- If we are resuming, just check to see whether have reached the resume point, otherwise
- -- turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnLeft()
- end
- elseif (turnDir == direction.RIGHT) then
- if (currOrient == direction.FORWARD) then
- currOrient = direction.RIGHT
- elseif (currOrient == direction.LEFT) then
- currOrient = direction.FORWARD
- elseif (currOrient == direction.BACK) then
- currOrient = direction.LEFT
- elseif (currOrient == direction.RIGHT) then
- currOrient = direction.BACK
- else
- writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
- end
- -- If we are resuming, just check to see whether have reached the resume point, otherwise
- -- turn
- if (resuming == true) then
- updateResumingFlag()
- writeMessage("["..currMiningState..", "..currX..", "..currY..", "..currZ..", "..currOrient.."]", messageLevel.DEBUG)
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnRight()
- end
- else
- writeMessage ("Invalid turnDir in turtleTurn function", messageLevel.ERROR)
- end
- end
- -- ********************************************************************************** --
- -- Sets the turtle to a specific orientation, irrespective of its current orientation
- -- ********************************************************************************** --
- function turtleSetOrientation(newOrient)
- if (currOrient ~= newOrient) then
- if (currOrient == direction.FORWARD) then
- if (newOrient == direction.RIGHT) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnRight()
- end
- elseif (newOrient == direction.BACK) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnRight()
- turtle.turnRight()
- end
- elseif (newOrient == direction.LEFT) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnLeft()
- end
- else
- writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
- end
- elseif (currOrient == direction.RIGHT) then
- if (newOrient == direction.BACK) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnRight()
- end
- elseif (newOrient == direction.LEFT) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnRight()
- turtle.turnRight()
- end
- elseif (newOrient == direction.FORWARD) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnLeft()
- end
- else
- writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
- end
- elseif (currOrient == direction.BACK) then
- if (newOrient == direction.LEFT) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnRight()
- end
- elseif (newOrient == direction.FORWARD) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnRight()
- turtle.turnRight()
- end
- elseif (newOrient == direction.RIGHT) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnLeft()
- end
- else
- writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
- end
- elseif (currOrient == direction.LEFT) then
- if (newOrient == direction.FORWARD) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnRight()
- end
- elseif (newOrient == direction.RIGHT) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnRight()
- turtle.turnRight()
- end
- elseif (newOrient == direction.BACK) then
- currOrient = newOrient
- -- If resuming, check whether the resume point has been reached, otherwise turn
- if (resuming == true) then
- updateResumingFlag()
- else
- -- Write the new orientation and turn
- saveLocation()
- turtle.turnLeft()
- end
- else
- writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
- end
- else
- writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
- end
- end
- end
- -- ********************************************************************************** --
- -- Determines if a particular block is considered a noise block or not. A noise
- -- block is one that is a standard block in the game (stone, dirt, gravel etc.) and
- -- is one to ignore as not being an ore. Function works by comparing the block
- -- in question against a set of blocks in the turtle's inventory which are known not to
- -- be noise blocks. Param is the function to use to compare the block for a noise block
- -- ********************************************************************************** --
- function isNoiseBlock(inspectCommand)
- -- Consider air to be a noise block
- local returnVal = false
- local success, data = inspectCommand()
- if success == false then
- return true
- end
- if (resuming == true) then
- returnVal = true
- else
- for k, v in pairs(noise) do
- if data.name == k then
- returnVal = true
- end
- end
- end
- -- Return the calculated value
- return returnVal
- end
- -- ********************************************************************************** --
- -- Determines if a particular block is a chest. Returns false if it is not a chest
- -- or chests are not being detected
- -- ********************************************************************************** --
- function isChestBlock(compareFn)
- -- Check the block in the appropriate direction to see whether it is a chest. Only
- -- do this if we are looking for chests
- local returnVal = false
- local a,b = compareFn()
- if (a == true) then
- if (lookForChests == true) then
- if (b.name == "minecraft:chest") then
- returnVal = true
- end
- end
- end
- -- Return the calculated value
- return returnVal
- end
- -- ********************************************************************************** --
- -- Function to calculate the number of non seam blocks in the turtle's inventory. This
- -- is all of the blocks at the start of the inventory (before the first empty slot is
- -- found
- -- ********************************************************************************** --
- function determineNoiseBlocksCountCount()
- noiseBlocksCount = 0
- -- Determine whether a chest was provided, and hence whether we should support
- -- looking for chests
- if (turtle.getItemCount(15) > 0) then
- lookForChests = true
- lastEmptySlot = 14
- miningOffset = 0
- writeMessage("Looking for chests...", messageLevel.DEBUG)
- else
- lastEmptySlot = 15
- miningOffset = 1
- writeMessage("Ignoring chests...", messageLevel.DEBUG)
- end
- end
- -- ********************************************************************************** --
- -- Creates a quarry mining out only ores and leaving behind any noise blocks
- -- ********************************************************************************** --
- function createQuarry()
- -- Determine the top mining layer layer. The turtle mines in layers of 3, and the bottom layer
- -- is the layer directly above bedrock.
- --
- -- The actual layer that the turtle operates in is the middle of these three layers,
- -- so determine the top layer
- local topMiningLayer = startHeight + ((bottomLayer - startHeight - 2) % 3) - 1 + miningOffset
- -- If the top layer is up, then ignore it and move to the next layer
- if (topMiningLayer > currY) then
- topMiningLayer = topMiningLayer - 3
- end
- local startedLayerToRight = true -- Only used where the quarry is of an odd width
- -- Loop over each mining row
- local miningLevel
- for miningLevel = (bottomLayer + miningOffset), topMiningLayer, 3 do
- writeMessage("Mining Layer: "..miningLevel, messageLevel.INFO)
- haveBeenAtZeroZeroOnLayer = false
- -- While the initial shaft is being dug out, set the level to return to in order to unload
- -- to the just take the turtle straight back up
- if (miningLevel == (bottomLayer + miningOffset)) then
- levelToReturnTo = startHeight
- end
- -- Move to the correct level to start mining
- if (currY > miningLevel) then
- while (currY > miningLevel) do
- turtleDown()
- end
- elseif (currY < miningLevel) then
- while (currY < miningLevel) do
- turtleUp()
- end
- end
- -- Am now mining the levels (update the mining state to reflect that fact)
- currMiningState = miningState.LAYER
- -- Set the layer to return via when returning to the surface as the one below the currently
- -- mined one
- if (miningLevel == (bottomLayer + miningOffset)) then
- levelToReturnTo = (bottomLayer + miningOffset)
- else
- levelToReturnTo = miningLevel - 3
- end
- -- Move turtle into the correct orientation to start mining (if this is the
- -- first row to be mined, then don't need to turn, otherwise turn towards the next
- -- mining section)
- writeMessage("Mining Level: "..miningLevel..", Bottom Layer: "..bottomLayer..", Mining Offset: "..miningOffset, messageLevel.DEBUG)
- if (miningLevel > (bottomLayer + miningOffset)) then
- -- Turn towards the next mining layer
- if (quarryWidth % 2 == 0) then
- -- An even width quarry, always turn right
- turtleTurn(direction.RIGHT)
- else
- -- Turn the opposite direction to that which we turned before
- if (startedLayerToRight == true) then
- turtleTurn(direction.LEFT)
- startedLayerToRight = false
- else
- turtleTurn(direction.RIGHT)
- startedLayerToRight = true
- end
- end
- end
- local mineRows
- local onNearSideOfQuarry = true
- local diggingAway = true
- for mineRows = 1, quarryWidth do
- -- If this is not the first row, then get into position to mine the next row
- if ((mineRows == 1) and (lookForChests == false)) then
- -- Not looking for chests, check the block below for being an ore. Only do this
- -- if we're not looking for chests since the program doesn't support chests in
- -- bedrock
- if (isNoiseBlock(turtle.inspectDown) == false) then
- turtle.digDown()
- ensureInventorySpace()
- end
- elseif (mineRows > 1) then
- -- Move into position for mining the next row
- if (onNearSideOfQuarry == diggingAway) then
- if (startedLayerToRight == true) then
- turtleTurn(direction.LEFT)
- else
- turtleTurn(direction.RIGHT)
- end
- else
- if (startedLayerToRight == true) then
- turtleTurn(direction.RIGHT)
- else
- turtleTurn(direction.LEFT)
- end
- end
- turtleForward()
- -- Before making the final turn, check the block below. Do this
- -- now because if it is a chest, then we want to back up and
- -- approach it from the side (so that we don't lose items if we
- -- have to return to the start through it).
- --
- -- This is the point at which it is safe to back up without moving
- -- out of the quarry area (unless at bedrock in which case don't bother
- -- as we'll be digging down anyway)
- if (miningLevel ~= bottomLayer) then
- if (isNoiseBlock(turtle.inspectDown) == false) then
- -- If we are not looking for chests, then just dig it (it takes
- -- less time to try to dig and fail as it does to do detect and
- -- only dig if there is a block there)
- if (lookForChests == false) then
- turtle.digDown()
- ensureInventorySpace()
- elseif (turtle.detectDown() == true) then
- if (isChestBlock(turtle.inspectDown) == true) then
- -- There is a chest block below. Move back and approach
- -- from the side to ensure that we don't need to return to
- -- start through the chest itself (potentially losing items)
- turtleBack()
- turtleDown()
- currMiningState = miningState.EMPTYCHESTDOWN
- emptyChest(turtle.suck)
- currMiningState = miningState.LAYER
- turtleUp()
- turtleForward()
- turtle.digDown()
- ensureInventorySpace()
- else
- turtle.digDown()
- ensureInventorySpace()
- end
- end
- end
- end
- -- Move into final position for mining the next row
- if (onNearSideOfQuarry == diggingAway) then
- if (startedLayerToRight == true) then
- turtleTurn(direction.LEFT)
- else
- turtleTurn(direction.RIGHT)
- end
- else
- if (startedLayerToRight == true) then
- turtleTurn(direction.RIGHT)
- else
- turtleTurn(direction.LEFT)
- end
- end
- end
- -- Dig to the other side of the quarry
- local blocksMined
- for blocksMined = 0, (quarryWidth - 1) do
- if (blocksMined > 0) then
- -- Only move forward if this is not the first space
- turtleForward()
- end
- -- If the current block is (0,0), then record the fact that the
- -- turtle has been through this block and what it's orientation was and update the layer
- -- that it should return via to get back to the surface (it no longer needs to go down
- -- a level to prevent losing ores).
- if ((currX == 0) and (currZ == 0)) then
- -- Am at (0, 0). Remember this, and what direction I was facing so that the quickest route
- -- to the surface can be taken
- levelToReturnTo = miningLevel
- haveBeenAtZeroZeroOnLayer = true
- orientationAtZeroZero = currOrient
- end
- -- If currently at bedrock, just move down until the turtle can't go any
- -- further. This allows the blocks within the bedrock to be mined
- if (miningLevel == bottomLayer) then
- -- Temporarily turn off looking for chests to increase bedrock mining speed (this
- -- means that the program doesn't support chests below level 5 - but I think
- -- they they don't exist anyway)
- local lookForChestsPrev = lookForChests
- lookForChests = false
- -- Manually set the flag to determine whether the turtle should try to move first or
- -- dig first. At bedrock, is very rarely any space
- -- Just above bedrock layer, dig down until can't dig any lower, and then
- -- come back up. This replicates how the quarry functions
- lastMoveNeededDig = true
- local moveDownSuccess = turtleDown()
- while (moveDownSuccess == true) do
- moveDownSuccess = turtleDown()
- end
- -- Know that we are moving back up through air, therefore set the flag to force the
- -- turtle to try moving first
- lastMoveNeededDig = false
- -- Have now hit bedrock, move back to the mining layer
- while (currY < bottomLayer) do
- turtleUp()
- end
- -- Now back at the level above bedrock, again reset the flag to tell the turtle to
- -- try digging again (because it is rare to find air at bedrock level)
- lastMoveNeededDig = false
- -- Reset the look for chests value
- lookForChests = lookForChestsPrev
- elseif ((blocksMined > 0) and ((currX ~= 0) or (currZ ~= 0))) then
- -- This isn't the first block of the row, nor are we at (0, 0) so we need to check the
- -- block below
- -- Check the block down for being a noise block (don't need to check the first
- -- block as it has already been checked in the outer loop)
- if (isNoiseBlock(turtle.inspectDown) == false) then
- -- If we are not looking for chests, then just dig it (it takes
- -- less time to try to dig and fail as it does to do detect and
- -- only dig if there is a block there)
- if (lookForChests == false) then
- turtle.digDown()
- ensureInventorySpace()
- elseif (turtle.detectDown() == true) then
- if (isChestBlock(turtle.inspectDown) == true) then
- -- There is a chest block below. Move back and approach
- -- from the side to ensure that we don't need to return to
- -- start through the chest itself (potentially losing items)
- turtleBack()
- currMiningState = miningState.EMPTYCHESTDOWN
- turtleDown()
- emptyChest(turtle.suck)
- currMiningState = miningState.LAYER
- turtleUp()
- turtleForward()
- turtle.digDown()
- ensureInventorySpace()
- else
- turtle.digDown()
- ensureInventorySpace()
- end
- end
- end
- end
- -- Check the block above for ores (if we're not a (0, 0) in which case
- -- we know it's air)
- if ((currX ~= 0) or (currZ ~= 0)) then
- if (isNoiseBlock(turtle.inspectUp) == false) then
- -- If we are not looking for chests, then just dig it (it takes
- -- less time to try to dig and fail as it does to do detect and
- -- only dig if there is a block there)
- if (lookForChests == false) then
- turtle.digUp()
- ensureInventorySpace()
- elseif (turtle.detectUp() == true) then
- -- Determine if it is a chest before digging it
- if (isChestBlock(turtle.inspectUp) == true) then
- -- There is a chest block above. Empty it before digging it
- emptyChest(turtle.suckUp)
- turtle.digUp()
- ensureInventorySpace()
- else
- turtle.digUp()
- ensureInventorySpace()
- end
- end
- end
- end
- end
- -- Am now at the other side of the quarry
- onNearSideOfQuarry = not onNearSideOfQuarry
- end
- -- If we were digging away from the starting point, will be digging
- -- back towards it on the next layer
- diggingAway = not diggingAway
- end
- -- Return to the start
- returnToStartAndUnload(false)
- -- Face forward
- turtleSetOrientation(direction.FORWARD)
- end
- -- ********************************************************************************** --
- -- Reads the next number from a given file
- -- ********************************************************************************** --
- function readNumber(inputFile)
- local returnVal
- local nextLine = inputFile.readLine()
- if (nextLine ~= nil) then
- returnVal = tonumber(nextLine)
- end
- return returnVal
- end
- -- ********************************************************************************** --
- -- Startup function to support resuming mining turtle
- -- ********************************************************************************** --
- function isResume()
- local returnVal = false
- -- Try to open the resume file
- local resumeFile = fs.open(startupParamsFile, "r")
- if (resumeFile == nil) then
- -- No resume file (presume that we are not supporting it)
- supportResume = false
- else
- writeMessage("Found startup params file", messageLevel.DEBUG)
- -- Read in the startup params
- quarryWidth = readNumber(resumeFile)
- startHeight = readNumber(resumeFile)
- noiseBlocksCount = readNumber(resumeFile)
- lastEmptySlot = readNumber(resumeFile)
- resumeFile.close()
- -- If the parameters were successfully read, then set the resuming flag to true
- if ((quarryWidth ~= nil) and (startHeight ~= nil) and (noiseBlocksCount ~= nil) and (lastEmptySlot ~= nil)) then
- resuming = true
- writeMessage("Read params", messageLevel.DEBUG)
- -- Determine the look for chest and mining offset
- if (lastEmptySlot == 14) then
- lookForChests = true
- miningOffset = 0
- else
- lookForChests = false
- miningOffset = 1
- end
- -- Get the turtle resume location
- resumeFile = fs.open(oreQuarryLocation, "r")
- if (resumeFile ~= nil) then
- resumeMiningState = readNumber(resumeFile)
- resumeX = readNumber(resumeFile)
- resumeY = readNumber(resumeFile)
- resumeZ = readNumber(resumeFile)
- resumeOrient = readNumber(resumeFile)
- resumeFile.close()
- -- Ensure that the resume location has been found
- if ((resumeMiningState ~= nil) and (resumeX ~= nil) and (resumeY ~= nil) and (resumeZ ~= nil) and (resumeOrient ~= nil)) then
- returnVal = true
- local emptiedInventory = false
- -- Perform any mining state specific startup
- if (resumeMiningState == miningState.EMPTYINVENTORY) then
- -- Am mid way through an empty inventory cycle. Complete it before
- -- starting the main Quarry function
- returnToStartAndUnload(true)
- resuming = true
- -- Continue from the current position
- resumeX = currX
- resumeY = currY
- levelToReturnTo = resumeY
- resumeZ = currZ
- resumeOrient = currOrient
- writeMessage("Resuming with state of "..currMiningState, messageLevel.DEBUG)
- resumeMiningState = currMiningState
- emptiedInventory = true
- end
- -- If was emptying a chest when the program stopped, then move back
- -- to a point which the Quarry
- if (resumeMiningState == miningState.EMPTYCHESTDOWN) then
- -- Set the current X, Y, Z and orientation to the true position that
- -- the turtle is at
- if (emptiedInventory == false) then
- currX = resumeX
- currY = resumeY
- currZ = resumeZ
- currOrient = resumeOrient
- end
- -- Set the mining state as layer, assume haven't been through zero
- -- zero and set the level to return to as the one below the current one
- currMiningState = miningState.LAYER
- levelToReturnTo = currY - 2
- haveBeenAtZeroZeroOnLayer = false
- -- Temporarily disable resuming (so that the new location is written to the file
- -- in case the program stops again)
- resuming = false
- turtleUp()
- resuming = true
- resumeY = currY
- resumeMiningState = miningState.LAYER
- end
- end
- end
- end
- if (returnVal == false) then
- writeMessage("Failed to resume", messageLevel.ERROR)
- end
- end
- return returnVal
- end
- -- ********************************************************************************** --
- -- Main Function
- -- ********************************************************************************** --
- -- Process the input arguments - storing them to global variables
- local args = { ... }
- local paramsOK = true
- -- Detect whether this is a wireless turtle, and if so, open the modem
- local peripheralConnected = peripheral.getType("right")
- if (peripheralConnected == "modem") then
- isWirelessTurtle = true
- end
- -- If a wireless turtle, open the modem
- if (isWirelessTurtle == true) then
- turtleId = os.getComputerLabel()
- rednet.open("right")
- end
- if (#args == 0) then
- -- Is this a resume?
- if (isResume() == false) then
- paramsOK = false
- end
- elseif (#args == 1) then
- quarryWidth = tonumber(args[1])
- local x, y, z = gps.locate(5)
- startHeight = y
- if (startHeight == nil) then
- writeMessage("Can't locate GPS", messageLevel.FATAL)
- paramsOK = false
- end
- elseif (#args == 2) then
- if (args[2] == "/r") then
- quarryWidth = tonumber(args[1])
- supportResume = false
- else
- quarryWidth = tonumber(args[1])
- startHeight = tonumber(args[2])
- end
- elseif (#args == 3) then
- quarryWidth = tonumber(args[1])
- startHeight = tonumber(args[2])
- if (args[3] == "/r") then
- supportResume = false
- else
- paramsOK = false
- end
- end
- if ((paramsOK == false) and (resuming == false)) then
- writeMessage("Usage: "..shell.getRunningProgram().." <diameter> [turtleY] [/r]", messageLevel.FATAL)
- paramsOK = false
- end
- if (paramsOK == true) then
- if ((startHeight < -60) or (startHeight > 320)) then
- writeMessage("turtleY must be between -60 and 320", messageLevel.FATAL)
- paramsOK = false
- end
- if ((quarryWidth < 2) or (quarryWidth > 64)) then
- writeMessage("diameter must be between 2 and 64", messageLevel.FATAL)
- paramsOK = false
- end
- end
- if (paramsOK == true) then
- if (resuming == true) then
- writeMessage("Resuming Ore Quarry...", messageLevel.INFO)
- else
- writeMessage("-------------------------------------", messageLevel.INFO)
- writeMessage("** Ore Quarry v1.0 by KeldonSlayer **", messageLevel.INFO)
- writeMessage("-------------------------------------", messageLevel.INFO)
- end
- -- Set the turtle's starting position
- currX = 0
- currY = startHeight
- currZ = 0
- currOrient = direction.FORWARD
- -- Calculate which blocks in the inventory signify noise blocks
- if (resuming == false) then
- determineNoiseBlocksCountCount()
- end
- if (noiseBlocksCount == 0) then
- -- If we are supporting resume (and are not currently in the process of resuming)
- -- then store startup parameters in appropriate files
- if ((supportResume == true) and (resuming == false)) then
- -- Write the startup parameters to file
- local outputFile = io.open(startupParamsFile, "w")
- outputFile:write(quarryWidth)
- outputFile:write("\n")
- outputFile:write(startHeight)
- outputFile:write("\n")
- outputFile:write(noiseBlocksCount)
- outputFile:write("\n")
- outputFile:write(lastEmptySlot)
- outputFile:write("\n")
- outputFile:close()
- -- Setup the startup file
- -- Take a backup of the current startup file
- if (fs.exists("startup") == true) then
- fs.copy("startup", startupBackup)
- outputFile = io.open("startup", "a")
- else
- outputFile = io.open("startup", "w")
- end
- -- Write an info message so that people know how to get out of auto-resume
- outputFile:write("\nprint(\"Running auto-restart...\")\n")
- outputFile:write("print(\"If you want to stop auto-resume and restore original state:\")\n")
- outputFile:write("print(\"1) Hold Ctrl-T until the program terminates\")\n")
- outputFile:write("print(\"2) Type \\\"rm startup\\\" (without quotes) and hit Enter\")\n")
- outputFile:write("print(\"\")\n\n")
- -- Write the code required to restart the turtle
- outputFile:write("shell.run(\"")
- outputFile:write(shell.getRunningProgram())
- outputFile:write("\")\n")
- outputFile:close()
- end
- -- Create a Quarry
- turtle.select(1)
- currentlySelectedSlot = 1
- createQuarry()
- -- Restore the file system to its original configuration
- if (supportResume == true) then
- fs.delete("startup")
- if (fs.exists(startupBackup) == true) then
- fs.move(startupBackup, "startup")
- end
- if (fs.exists(startupParamsFile) == true) then
- fs.delete(startupParamsFile)
- end
- if (fs.exists(oreQuarryLocation) == true) then
- fs.delete(oreQuarryLocation)
- end
- if (fs.exists(returnToStartFile) == true) then
- fs.delete(returnToStartFile)
- end
- end
- end
- end
Add Comment
Please, Sign In to add comment