Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- if not turtle then
- printError("Requires a Turtle")
- return
- end
- if 0 ~= tonumber(settings.get("miner.done",0)) then
- printError("Current area marked as done! Change settings or run 'miner/sethome.lua' to allow another excavation.")
- error()
- end
- -- Mine in a quarry pattern until we hit something we can't dig
- local size = tonumber(settings.get("miner.exc_rad",20))
- if size < 1 then
- printError("Excavate diameter must be positive")
- error()
- end
- -- Some forward-declarations
- local goTo, refuel
- local _await, _awaitRefuel
- local xPos, zPos, depth, lowDepth
- local xDir, zDir
- local tohomeFuel
- -- gps.locate() that does not return until it succeeds
- local function locate()
- local printed = false
- local x,y,z
- repeat
- x,y,z = gps.locate()
- if x == nil then
- if not printed then
- print("GPS Error! Please fix!")
- rednet.broadcast({"gpserr"},"excgps")
- printed = true
- end
- _await(5, true)
- end
- until x ~= nil
- return x,y,z
- end
- -- Save settings to disk
- local function save()
- settings.save(".settings")
- end
- -- Setup network
- local sides = {"up","down","left","right","forward","back"}
- local function openNet()
- if rednet.isOpen() then
- return true
- else
- for i = 1,#sides do
- if peripheral.getType(sides[i]) == "modem" then
- if rednet.open(sides[i]) then
- return true
- end
- end
- end
- end
- return false
- end
- local function sendPos()
- if not rednet.isOpen() then return end
- local x,y,z = locate()
- rednet.broadcast({"coord",x,y,z},"excgps")
- end
- if not openNet() then
- printError("Failed to open rednet connection; modem required")
- error()
- end
- -- Mine straight down this far first
- local startDepth = tonumber(settings.get("miner.sdepth",10))
- -- Max distance to mine down before stopping, even if no bedrock reached
- local maxDepth = tonumber(settings.get("miner.mdepth",999))
- -- Extra distance to travel forwards before starting mining
- local wanderDist = tonumber(settings.get("miner.wander",0))
- --The home location to return supplies to, absolute coordinates
- local homex = tonumber(settings.get("miner.homex",nil))
- local homey = tonumber(settings.get("miner.homey",nil))
- local homez = tonumber(settings.get("miner.homez",nil))
- local hxDir = tonumber(settings.get("miner.homexd",nil))
- local hzDir = tonumber(settings.get("miner.homezd",nil))
- local function refuel(ammount)
- local fuelLevel = turtle.getFuelLevel()
- if fuelLevel == "unlimited" then
- return true
- end
- local needed = ammount or xPos + zPos + depth + tohomeFuel + 64
- if turtle.getFuelLevel() < needed then
- for n = 1, 16 do
- if turtle.getItemCount(n) > 0 then
- turtle.select(n)
- if turtle.refuel(1) then
- while turtle.getItemCount(n) > 0 and turtle.getFuelLevel() < needed do
- turtle.refuel(1)
- end
- if turtle.getFuelLevel() >= needed then
- turtle.select(1)
- return true
- end
- end
- end
- end
- turtle.select(1)
- return false
- end
- return true
- end
- local function fuelCheck()
- refuel(16)
- _await(0)
- end
- function _await(s, nopos)
- if not nopos then sendPos() end
- sleep(s or 0.05)
- end
- function _awaitRefuel(fuelNeeded)
- repeat
- turtle.suckUp(64)
- until refuel(fuelNeeded)
- end
- -- Use two separate locates to determine facing direction
- local function getDirs(bMine)
- local invert = false
- local x1,_1,z1 = locate()
- fuelCheck()
- if not turtle.forward() then
- if turtle.back() then
- invert = true
- end
- if not invert then
- while not turtle.forward() do
- if bMine then turtle.dig() end
- fuelCheck()
- _await()
- end
- end
- end
- local x2,_2,z2 = locate()
- local xd,zd = x2-x1,z2-z1
- if invert then
- xd,zd = -xd,-zd
- while not turtle.forward() do
- fuelCheck()
- _await()
- end
- else
- while not turtle.back() do
- fuelCheck()
- _await()
- end
- end
- if xd > 1 then xd = 1 end
- if xd < -1 then xd = -1 end
- if zd > 1 then zd = 1 end
- if zd < -1 then zd = -1 end
- return xd,zd
- end
- -- Save current position as the home position if none saved
- if homex == nil or homey == nil or homez == nil then
- homex, homey, homez = locate()
- settings.set("miner.homex",homex)
- settings.set("miner.homey",homey)
- settings.set("miner.homez",homez)
- save()
- end
- xDir, zDir = getDirs(hxDir ~= nil and hzDir ~= nil)
- if hxDir == nil or hzDir == nil then
- hxDir,hzDir = xDir,zDir
- settings.set("miner.homexd",hxDir)
- settings.set("miner.homezd",hzDir)
- save()
- end
- local function turnLeft()
- turtle.turnLeft()
- xDir, zDir = zDir, -xDir
- end
- local function turnRight()
- turtle.turnRight()
- xDir, zDir = -zDir, xDir
- end
- -- The position to start this tunnel from
- local tx,ty,tz = homex + hxDir*wanderDist, homey-startDepth, homez + hzDir*wanderDist
- -- The home position, relative to the tunnel start, y is inverted
- local hx,hy,hz = homex-tx,ty-homey,homez-tz
- -- The launch position
- local sx,sy,sz = locate()
- local athome = sx==homex and sy==homey and sz==homez
- local exc = tonumber(settings.get("miner.is_exc",0))
- local resume = 0 ~= exc
- local resume_deposit = 2 == exc
- -- Relative coordinates to the tunnel start position
- depth = ty-sy --inverted!
- xPos, zPos = sx-tx, sz-tz
- -- The fuel required from tx,ty,tz to homex,homey,homez and a little extra
- tohomeFuel = math.abs(tx-homex) + math.abs(ty-homey) + math.abs(tz-homez) + 16
- local function unload(bKeepFuel)
- print("Unloading items...")
- --Never hold fuel stack if fuel is infinite
- if turtle.getFuelLevel() == "unlimited" then
- bKeepFuel = false
- end
- for n = 1, 16 do
- local nCount = turtle.getItemCount(n)
- if nCount > 0 then
- turtle.select(n)
- local bDrop = true
- if bKeepFuel and turtle.refuel(0) then
- bDrop = false
- bKeepFuel = false
- end
- if bDrop then
- --First drop into any container above
- if turtle.detectUp() then
- turtle.dropUp()
- end
- if turtle.getItemCount(n) > 0 then
- --Then to each side, if there's any left
- for _ = 1,4 do
- if turtle.detect() and turtle.getItemCount(n) > 0 then
- turtle.drop()
- end
- turnLeft()
- end
- end
- --finally, if anything remains, just drop it on the ground
- if turtle.getItemCount(n) > 0 then
- turtle.drop()
- end
- end
- end
- end
- turtle.select(1)
- end
- local function returnSupplies()
- local x, y, z, xd, zd = xPos, depth, zPos, xDir, zDir
- print("Returning to surface...")
- goTo(0, 0, 0) --returns to the relative start
- goTo(hx, hy, hz, hxDir, -hzDir) --returns to home
- local fuelNeeded = 3 * (x + y + z) + 128 + tohomeFuel
- if not refuel(fuelNeeded) then
- unload(true)
- print("Waiting for fuel")
- --redstone.setOutput("top", true)
- _awaitRefuel(fuelNeeded)
- --redstone.setOutput("top", false)
- unload(true) --prevent >1 stack of fuel from being stored
- else
- unload(true)
- end
- print("Resuming mining...")
- goTo(0, 0, 0)
- goTo(x, y, z, xd, zd)
- end
- local function collect()
- local bFull = true
- local nTotalItems = 0
- for n = 1, 16 do
- local nCount = turtle.getItemCount(n)
- if nCount == 0 then
- bFull = false
- end
- nTotalItems = nTotalItems + nCount
- end
- if bFull then
- print("No empty slots left.")
- return false
- end
- return true
- end
- local function countSlots()
- local slotcount = 0
- for n = 1, 16 do
- if turtle.getItemCount(n) == 0 then
- slotcount = slotcount + 1
- end
- end
- return slotcount
- end
- local function tryForwards()
- if not refuel() then
- print("Not enough Fuel")
- returnSupplies()
- end
- while not turtle.forward() do
- if turtle.detect() then
- if turtle.dig() then
- if not collect() then
- returnSupplies()
- end
- else
- return false
- end
- elseif turtle.attack() then
- if not collect() then
- returnSupplies()
- end
- else
- _await()
- end
- fuelCheck()
- end
- xPos = xPos + xDir
- zPos = zPos + zDir
- return true
- end
- local function tryDown()
- if not refuel() then
- print("Not enough Fuel")
- returnSupplies()
- end
- if depth + 1 > maxDepth then
- return false
- end
- while not turtle.down() do
- if turtle.detectDown() then
- if turtle.digDown() then
- if not collect() then
- returnSupplies()
- end
- else
- return false
- end
- elseif turtle.attackDown() then
- if not collect() then
- returnSupplies()
- end
- else
- _await()
- end
- fuelCheck()
- end
- depth = depth + 1
- if math.fmod(depth, 10) == 0 then
- print("Descended " .. depth .. " metres.")
- end
- if lowDepth < depth then
- lowDepth = depth
- settings.set("miner.lastDepth",lowDepth)
- save()
- end
- return true
- end
- local function goY(y)
- if y == nil then return end
- while depth > y do
- if turtle.up() then
- depth = depth - 1
- elseif turtle.digUp() or turtle.attackUp() then
- collect()
- else
- _await()
- end
- fuelCheck()
- end
- while depth < y do
- if turtle.down() then
- depth = depth + 1
- elseif turtle.digDown() or turtle.attackDown() then
- collect()
- else
- _await()
- end
- fuelCheck()
- end
- end
- local function goX(x)
- if x == nil then return end
- if xPos > x then
- while xDir ~= -1 do
- turnLeft()
- end
- while xPos > x do
- if turtle.forward() then
- xPos = xPos - 1
- elseif turtle.dig() or turtle.attack() then
- collect()
- else
- _await()
- end
- fuelCheck()
- end
- elseif xPos < x then
- while xDir ~= 1 do
- turnLeft()
- end
- while xPos < x do
- if turtle.forward() then
- xPos = xPos + 1
- elseif turtle.dig() or turtle.attack() then
- collect()
- else
- _await()
- end
- fuelCheck()
- end
- end
- end
- local function goZ(z)
- if z == nil then return end
- if zPos > z then
- while zDir ~= -1 do
- turnLeft()
- end
- while zPos > z do
- if turtle.forward() then
- zPos = zPos - 1
- elseif turtle.dig() or turtle.attack() then
- collect()
- else
- _await()
- end
- fuelCheck()
- end
- elseif zPos < z then
- while zDir ~= 1 do
- turnLeft()
- end
- while zPos < z do
- if turtle.forward() then
- zPos = zPos + 1
- elseif turtle.dig() or turtle.attack() then
- collect()
- else
- _await()
- end
- fuelCheck()
- end
- end
- end
- local function goXZ(x,z)
- if hzDir ~= 0 then
- goZ(z)
- goX(x)
- else
- goX(x)
- goZ(z)
- end
- end
- function goTo(x, y, z, xd, zd)
- if depth < 0 and ((x ~= nil and x ~= xPos) or (z ~= nil and z ~= zPos)) then
- goY(0)
- end
- goXZ(x,z)
- goY(y)
- while (zd ~= nil and zDir ~= zd) or (xd ~= nil and xDir ~= xd) do
- turnLeft()
- end
- end
- if athome then
- if not refuel(256) then
- print("Waiting for fuel...")
- --redstone.setOutput("top", true)
- _awaitRefuel(256)
- --redstone.setOutput("top", false)
- end
- if countSlots() < 15 then
- print("Depositing down to 1 stack of fuel...")
- unload(true)
- end
- if not resume_deposit then
- print("Excavating...")
- goTo(0,0,0,hxDir,hzDir)
- end
- end
- if resume then
- if (depth < 0 and (sy > homey or sx ~= homex or sz ~= homez)) or math.abs(xPos) > size or math.abs(zPos) > size then
- printError("Cannot resume from current position; might mine through important things.")
- printError("Please reposition me back to my home, or underground near where I was mining!")
- error()
- end
- print("Resuming...")
- end
- turtle.select(1)
- local alternate = 0
- local done = false
- --Store some values which will be used to resume from a terminated state
- local rxp,rzp = xPos,zPos
- lowDepth = tonumber(settings.get("miner.lastDepth",0))
- if resume and not resume_deposit then
- goTo(0,lowDepth,0,hxDir,hzDir)
- end
- --
- if not resume_deposit then
- exc = 1
- settings.set("miner.is_exc",exc)
- save()
- while not done do
- for n = 1, size do
- for _ = 1, size - 1 do
- if not tryForwards() then
- done = true
- break
- end
- end
- if done then
- break
- end
- if n < size then
- if math.fmod(n + alternate, 2) == 0 then
- turnLeft()
- if not tryForwards() then
- done = true
- break
- end
- turnLeft()
- else
- turnRight()
- if not tryForwards() then
- done = true
- break
- end
- turnRight()
- end
- end
- end
- if done then
- break
- end
- if size > 1 then
- if math.fmod(size, 2) == 0 then
- turnRight()
- else
- if alternate == 0 then
- turnLeft()
- else
- turnRight()
- end
- alternate = 1 - alternate
- end
- end
- if not tryDown() then
- done = true
- break
- end
- end
- exc = 2
- settings.set("miner.is_exc",exc)
- settings.set("miner.lastDepth",0)
- save()
- end
- print("Returning to surface...")
- goY(0) --return to relative start y, important to avoid bedrock
- goTo(0, 0, 0) --returns to the relative start
- goTo(hx, hy, hz, hxDir, -hzDir) --returns to home
- unload(false)
- goTo(nil,nil,nil,hxDir,hzDir)
- print("Excavate complete.")
- settings.set("miner.is_exc",0)
- if 0 ~= tonumber(settings.get("miner.autoinc",1)) then
- settings.set("miner.wander",wanderDist+size)
- save()
- print("Ready to excavate again!")
- else
- settings.set("miner.done",1)
- save()
- end
Add Comment
Please, Sign In to add comment