Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Turtle Miner (CraftOS / CC:Tweaked)
- local DEFAULTS = {
- stateFile = "disk:miner.state",
- homeDir = 0,
- startEscapeSteps = 6,
- save = { stepInterval = 12, statusInterval = 1.0, suckCycles = 4, suckSleep = 0.03, moveSleep = 0.02 },
- fuel = { returnReserve = 120, refuelMin = 800 },
- fluids = { blockSlot = 14 },
- scanner = { enable = true, radiusDefault = 8 },
- status = { protocol = "miner" },
- stairs = { steps = 24, width = 3, headroom = 3, torches = true, torchSlot = 15, torchInterval = 6, torchRescanInterval = 12 },
- mine = { roomLen = 16, roomRows = 5, layers = 6, layerDrop = 1, torchInterval = 10, torchRescanInterval = 24 }
- }
- local function scanPeripherals(want)
- local found = {}
- for _, name in ipairs(peripheral.getNames()) do
- local pType = peripheral.getType(name)
- local p = peripheral.wrap(name)
- if (want.modem and not found.modem and pType == "modem") then found.modem = p; found.modemName = name end
- if (want.scanner and not found.scanner and type(p.scan) == "function") then found.scanner = p; found.scannerName = name; found.scannerType = pType end
- end
- return found
- end
- local function parseArgs(args)
- local mode = "both"
- local resume = false
- local goHome = false
- local radius = nil
- for i = 1, #args do
- local a = tostring(args[i] or "")
- local al = string.lower(a)
- if (al == "mine" or al == "stairs" or al == "both") then mode = al end
- if (al == "resume") then resume = true end
- if (al == "home") then goHome = true; resume = true end
- if (radius == nil) then local n = tonumber(a); if (n ~= nil) then radius = n end end
- end
- return mode, radius, resume, goHome
- end
- local args = { ... }
- local mode, radius, resume, goHome = parseArgs(args)
- local STATE_FILE = DEFAULTS.stateFile
- local HOME_DIR = DEFAULTS.homeDir
- local START_ESCAPE_STEPS = DEFAULTS.startEscapeSteps
- local SAVE_STEP_INTERVAL = DEFAULTS.save.stepInterval
- local STATUS_INTERVAL = DEFAULTS.save.statusInterval
- local SUCK_CYCLES = DEFAULTS.save.suckCycles
- local SUCK_SLEEP = DEFAULTS.save.suckSleep
- local MOVE_SLEEP = DEFAULTS.save.moveSleep
- local STAIR_ENABLE = (mode == "stairs" or mode == "both")
- local STAIR_STEPS = DEFAULTS.stairs.steps
- local STAIR_WIDTH = DEFAULTS.stairs.width
- local STAIR_HEADROOM = DEFAULTS.stairs.headroom
- local STAIR_TORCHES = DEFAULTS.stairs.torches
- local TORCH_SLOT_PREF = DEFAULTS.stairs.torchSlot
- local STAIR_TORCH_INTERVAL = DEFAULTS.stairs.torchInterval
- local STAIR_TORCH_RESCAN_INTERVAL = DEFAULTS.stairs.torchRescanInterval
- local FLUID_BLOCK_SLOT = DEFAULTS.fluids.blockSlot
- local MINE_ENABLE = (mode == "mine" or mode == "both")
- local MINE_ROOM_LEN = DEFAULTS.mine.roomLen
- local MINE_ROOM_ROWS = DEFAULTS.mine.roomRows
- local MINE_LAYERS = DEFAULTS.mine.layers
- local MINE_LAYER_DROP = DEFAULTS.mine.layerDrop
- local MINE_TORCH_INTERVAL = DEFAULTS.mine.torchInterval
- local MINE_TORCH_RESCAN_INTERVAL = DEFAULTS.mine.torchRescanInterval
- local USE_SCANNER_IF_AVAILABLE = DEFAULTS.scanner.enable
- local SCAN_RADIUS_DEFAULT = DEFAULTS.scanner.radiusDefault
- local STATUS_PROTOCOL = DEFAULTS.status.protocol
- local FUEL_RETURN_RESERVE = DEFAULTS.fuel.returnReserve
- local FUEL_REFUEL_MIN = DEFAULTS.fuel.refuelMin
- radius = tonumber(radius or SCAN_RADIUS_DEFAULT) or SCAN_RADIUS_DEFAULT
- if (radius < 1) then radius = 1 end
- if (radius > 32) then radius = 32 end
- local P = scanPeripherals({ modem = true, scanner = USE_SCANNER_IF_AVAILABLE })
- local MODEM_SIDE = P.modemName
- local scanner, scannerSide, scannerType = P.scanner, P.scannerName, P.scannerType
- local TORCH_NAME_LIST = { "minecraft:wall_torch", "minecraft:torch" }
- local function isTorchName(n)
- if (not n) then return false end
- for i = 1, #TORCH_NAME_LIST do if (TORCH_NAME_LIST[i] == n) then return true end end
- return false
- end
- local ALLOWED_PREFIX = { "xycraft_world:", "supplementaries:" }
- local function startsWith(s, p) return s and p and string.sub(s, 1, #p) == p end
- local ALLOWED_EXACT = (function()
- local t = {}
- local function add(list) for i = 1, #list do t[list[i]] = true end end
- add({
- "minecraft:cobblestone",
- "minecraft:dirt",
- "minecraft:grass_block",
- "minecraft:stone",
- "minecraft:deepslate",
- "minecraft:granite",
- "minecraft:diorite",
- "minecraft:andesite",
- "minecraft:tuff",
- "minecraft:gravel",
- "minecraft:calcite",
- "minecraft:smooth_basalt",
- "minecraft:dripstone_block",
- "minecraft:moss_block",
- "minecraft:clay",
- "minecraft:pointed_dripstone",
- "minecraft:wall_torch",
- "supplementaries:barnacles",
- "xycraft_world:kiwi"
- })
- return t
- end)()
- local home = { x = 0, y = 0, z = 0 }
- local staging = { x = 0, y = 0, z = 0 }
- local pos = { x = 0, y = 0, z = 0 }
- local dir = HOME_DIR
- local stepCount = 0
- local path = {}
- local modemReady = false
- local lastStatusClock = 0
- local dirtySteps = 0
- local torchSlot = 0
- local lastTorchScanStep = 0
- local function rednetInit()
- if (modemReady) then return true end
- if (not MODEM_SIDE) then return false end
- if (peripheral.getType(MODEM_SIDE) ~= "modem") then return false end
- if (not rednet.isOpen(MODEM_SIDE)) then rednet.open(MODEM_SIDE) end
- modemReady = true
- return true
- end
- local function invUsed()
- local c = 0
- for i = 1, 16 do if (turtle.getItemCount(i) > 0) then c = c + 1 end end
- return c
- end
- local function statusSend(task, force)
- if (not rednetInit()) then return end
- local now = os.clock()
- if (not force and STATUS_INTERVAL > 0 and (now - lastStatusClock) < STATUS_INTERVAL) then return end
- lastStatusClock = now
- rednet.broadcast({ task = task, pos = { x = pos.x, y = pos.y, z = pos.z }, fuel = turtle.getFuelLevel(), inv = invUsed() }, STATUS_PROTOCOL)
- end
- local function saveState(force)
- if (not force) then
- if (SAVE_STEP_INTERVAL <= 0) then return end
- if (dirtySteps < SAVE_STEP_INTERVAL) then return end
- end
- local h = fs.open(STATE_FILE, "w")
- h.write(textutils.serialize({
- home = home, staging = staging, pos = pos, dir = dir, stepCount = stepCount, path = path,
- torchSlot = torchSlot, lastTorchScanStep = lastTorchScanStep
- }))
- h.close()
- dirtySteps = 0
- end
- local function loadState()
- if (not fs.exists(STATE_FILE)) then return false end
- local h = fs.open(STATE_FILE, "r")
- local s = textutils.unserialize(h.readAll())
- h.close()
- if (s and s.home and s.staging and s.pos and s.dir ~= nil and type(s.path) == "table") then
- home = s.home; staging = s.staging; pos = s.pos; dir = s.dir; path = s.path
- stepCount = tonumber(s.stepCount or 0) or 0
- torchSlot = tonumber(s.torchSlot or 0) or 0
- lastTorchScanStep = tonumber(s.lastTorchScanStep or 0) or 0
- dirtySteps = 0
- return true
- end
- return false
- end
- local function resetNavToStart()
- home = { x = 0, y = 0, z = 0 }
- staging = { x = 0, y = 0, z = 0 }
- pos = { x = 0, y = 0, z = 0 }
- dir = HOME_DIR
- stepCount = 0
- path = {}
- torchSlot = 0
- lastTorchScanStep = 0
- dirtySteps = 0
- saveState(true)
- end
- local function turnLeft(rec)
- turtle.turnLeft()
- dir = (dir + 3) % 4
- if (rec) then path[#path + 1] = "L" end
- dirtySteps = dirtySteps + 1; saveState(false)
- end
- local function turnRight(rec)
- turtle.turnRight()
- dir = (dir + 1) % 4
- if (rec) then path[#path + 1] = "R" end
- dirtySteps = dirtySteps + 1; saveState(false)
- end
- local function face(d)
- local diff = (d - dir) % 4
- if (diff == 0) then return end
- if (diff == 1) then turnRight(false); return end
- if (diff == 2) then turnRight(false); turnRight(false); return end
- turnLeft(false)
- end
- local function updateForward()
- if (dir == 0) then pos.z = pos.z - 1 elseif (dir == 1) then pos.x = pos.x + 1 elseif (dir == 2) then pos.z = pos.z + 1 else pos.x = pos.x - 1 end
- end
- local function updateBack()
- if (dir == 0) then pos.z = pos.z + 1 elseif (dir == 1) then pos.x = pos.x - 1 elseif (dir == 2) then pos.z = pos.z - 1 else pos.x = pos.x + 1 end
- end
- local function isOreName(name) return name and string.find(name, "ore", 1, true) ~= nil end
- local function isFluidName(name) if (not name) then return false end return (string.find(name, "water", 1, true) ~= nil) or (string.find(name, "lava", 1, true) ~= nil) end
- local function allowedBlockName(name)
- if (not name) then return false end
- if (isOreName(name)) then return true end
- if (ALLOWED_EXACT[name] == true) then return true end
- for i = 1, #ALLOWED_PREFIX do if (startsWith(name, ALLOWED_PREFIX[i])) then return true end end
- return false
- end
- local function atHome() return (pos.x == home.x and pos.y == home.y and pos.z == home.z) end
- local function protectedZone() return atHome() end
- local function suckAllAround()
- for _ = 1, SUCK_CYCLES do turtle.suck(); turtle.suckUp(); turtle.suckDown(); if (SUCK_SLEEP > 0) then sleep(SUCK_SLEEP) end end
- end
- local function tryFillFluid(where)
- if (FLUID_BLOCK_SLOT < 1 or FLUID_BLOCK_SLOT > 16) then return false end
- if (turtle.getItemCount(FLUID_BLOCK_SLOT) <= 0) then return false end
- local sel = turtle.getSelectedSlot()
- turtle.select(FLUID_BLOCK_SLOT)
- local ok = false
- if (where == "front") then ok = turtle.place() elseif (where == "down") then ok = turtle.placeDown() elseif (where == "up") then ok = turtle.placeUp() end
- turtle.select(sel)
- return ok
- end
- local function tryChestSuck(count)
- local startDir = dir
- for _ = 1, 4 do if (turtle.suck(count)) then return true end; turnRight(false) end
- while (dir ~= startDir) do turnRight(false) end
- return false
- end
- local function tryChestDrop()
- local startDir = dir
- for _ = 1, 4 do if (turtle.drop()) then return true end; turnRight(false) end
- while (dir ~= startDir) do turnRight(false) end
- return false
- end
- local function estimateHomeDistance()
- local dx = math.abs(pos.x - home.x)
- local dy = math.abs(pos.y - home.y)
- local dz = math.abs(pos.z - home.z)
- return dx + dy + dz
- end
- local function fuelOkForReturn()
- local f = turtle.getFuelLevel()
- if (f == "unlimited") then return true end
- return (f >= (estimateHomeDistance() + FUEL_RETURN_RESERVE))
- end
- local function refuelFromInventory(min)
- local lvl = turtle.getFuelLevel()
- if (lvl == "unlimited" or lvl >= min) then return true end
- for slot = 1, 16 do
- lvl = turtle.getFuelLevel()
- if (lvl == "unlimited" or lvl >= min) then turtle.select(1); return true end
- if (turtle.getItemCount(slot) > 0) then turtle.select(slot); if (turtle.refuel(0)) then turtle.refuel() end end
- end
- turtle.select(1)
- lvl = turtle.getFuelLevel()
- return (lvl == "unlimited" or lvl >= min)
- end
- local function abortHome(msg)
- print(msg)
- returnHomeFast(msg)
- saveState(true)
- error(msg)
- end
- local function moveStep(kind, miningAllowed, record)
- if (kind == "F") then
- while (not turtle.forward()) do
- if (not miningAllowed or protectedZone()) then abortHome("Blocked at protected zone (won't dig).") end
- local ok, data = turtle.inspect()
- local n = (data and data.name) or "unknown"
- if (ok and data and data.name and isFluidName(data.name)) then
- if (FLUID_BLOCK_SLOT ~= 0 and tryFillFluid("front")) then else abortHome("Front blocked by fluid: " .. n) end
- elseif (ok and data and data.name and allowedBlockName(data.name)) then
- turtle.dig(); suckAllAround()
- else
- abortHome("Blocked by non-allowed block in front: " .. n)
- end
- if (MOVE_SLEEP > 0) then sleep(MOVE_SLEEP) end
- end
- updateForward(); stepCount = stepCount + 1
- if (record) then path[#path + 1] = "F" end
- dirtySteps = dirtySteps + 1; saveState(false)
- return true
- end
- if (kind == "D") then
- while (not turtle.down()) do
- if (not miningAllowed or protectedZone()) then abortHome("Blocked at protected zone (won't dig).") end
- local ok, data = turtle.inspectDown()
- local n = (data and data.name) or "unknown"
- if (ok and data and data.name and isFluidName(data.name)) then
- if (FLUID_BLOCK_SLOT ~= 0 and tryFillFluid("down")) then else abortHome("Down blocked by fluid: " .. n) end
- elseif (ok and data and data.name and allowedBlockName(data.name)) then
- turtle.digDown(); suckAllAround()
- else
- abortHome("Blocked by non-allowed block below: " .. n)
- end
- if (MOVE_SLEEP > 0) then sleep(MOVE_SLEEP) end
- end
- pos.y = pos.y - 1; stepCount = stepCount + 1
- if (record) then path[#path + 1] = "D" end
- dirtySteps = dirtySteps + 1; saveState(false)
- return true
- end
- if (kind == "U") then
- while (not turtle.up()) do
- if (protectedZone()) then abortHome("Blocked at protected zone (won't dig).") end
- local ok, data = turtle.inspectUp()
- local n = (data and data.name) or "unknown"
- if (ok and data and data.name and isFluidName(data.name)) then
- if (FLUID_BLOCK_SLOT ~= 0 and tryFillFluid("up")) then else abortHome("Up blocked by fluid: " .. n) end
- elseif (ok and data and data.name and allowedBlockName(data.name)) then
- turtle.digUp(); suckAllAround()
- else
- abortHome("Up blocked by non-allowed block: " .. n)
- end
- if (MOVE_SLEEP > 0) then sleep(MOVE_SLEEP) end
- end
- pos.y = pos.y + 1
- dirtySteps = dirtySteps + 1; saveState(false)
- return true
- end
- if (kind == "B") then
- while (not turtle.back()) do if (MOVE_SLEEP > 0) then sleep(MOVE_SLEEP) end end
- updateBack()
- dirtySteps = dirtySteps + 1; saveState(false)
- return true
- end
- return false
- end
- local function oppositeStep(s)
- if (s == "F") then return "B" end
- if (s == "B") then return "F" end
- if (s == "U") then return "D" end
- if (s == "D") then return "U" end
- if (s == "L") then return "R" end
- if (s == "R") then return "L" end
- return nil
- end
- local function tryMoveNoDig(kind)
- if (kind == "F") then if (turtle.forward()) then updateForward(); return true end; local ok, data = turtle.inspect(); error("Home path blocked in front: " .. (((data and data.name) or "unknown"))) end
- if (kind == "B") then if (turtle.back()) then updateBack(); return true end; turnRight(false); turnRight(false); local ok, data = turtle.inspect(); turnRight(false); turnRight(false); error("Home path blocked behind: " .. (((data and data.name) or "unknown"))) end
- if (kind == "U") then if (turtle.up()) then pos.y = pos.y + 1; return true end; local ok, data = turtle.inspectUp(); error("Home path blocked above: " .. (((data and data.name) or "unknown"))) end
- if (kind == "D") then if (turtle.down()) then pos.y = pos.y - 1; return true end; local ok, data = turtle.inspectDown(); error("Home path blocked below: " .. (((data and data.name) or "unknown"))) end
- if (kind == "L") then turnLeft(false); return true end
- if (kind == "R") then turnRight(false); return true end
- return false
- end
- local function returnViaPathNoDig(reason)
- statusSend("return-path: " .. tostring(reason or ""), true)
- if (type(path) ~= "table" or #path == 0) then error("No recorded path. Refusing to dig home.") end
- for i = #path, 1, -1 do
- local opp = oppositeStep(path[i])
- if (opp) then tryMoveNoDig(opp) end
- if ((i % 16) == 0) then saveState(false) end
- end
- path = {}
- dir = HOME_DIR
- saveState(true)
- end
- function returnHomeFast(reason)
- statusSend("return-fast: " .. tostring(reason or ""), true)
- while (pos.x ~= home.x) do ensureFuel(); face((pos.x < home.x) and 1 or 3); moveStep("F", true, false) end
- while (pos.z ~= home.z) do ensureFuel(); face((pos.z < home.z) and 2 or 0); moveStep("F", true, false) end
- while (pos.y ~= home.y) do ensureFuel(); moveStep((pos.y < home.y) and "U" or "D", true, false) end
- path = {}
- dir = HOME_DIR
- dirtySteps = dirtySteps + 1
- saveState(true)
- end
- local function refuelFromChest(min)
- local lvl = turtle.getFuelLevel()
- if (lvl == "unlimited" or lvl >= min) then return end
- if (not atHome()) then returnHomeFast("refuel") end
- turtle.select(16)
- for _ = 1, 64 do
- lvl = turtle.getFuelLevel()
- if (lvl == "unlimited" or lvl >= min) then break end
- if (turtle.getItemCount(16) == 0) then if (not tryChestSuck(64)) then abortHome("No accessible chest adjacent at home (fuel).") end end
- if (turtle.getItemCount(16) > 0 and turtle.refuel(0)) then turtle.refuel() else if (not refuelFromInventory(min)) then break end end
- if (MOVE_SLEEP > 0) then sleep(MOVE_SLEEP) end
- end
- turtle.select(1)
- lvl = turtle.getFuelLevel()
- if (lvl ~= "unlimited" and lvl < min) then abortHome("Not enough fuel. Put coal/charcoal into adjacent chest at home.") end
- end
- function ensureFuel()
- local f = turtle.getFuelLevel()
- if (f == "unlimited") then return end
- if (fuelOkForReturn()) then return end
- statusSend("fuel low -> return", true)
- returnHomeFast("fuel")
- refuelFromChest(FUEL_REFUEL_MIN)
- statusSend("resume", true)
- end
- local function scanTorchSlot()
- if (TORCH_SLOT_PREF >= 1 and TORCH_SLOT_PREF <= 16 and turtle.getItemCount(TORCH_SLOT_PREF) > 0) then
- local d = turtle.getItemDetail(TORCH_SLOT_PREF)
- if (d and isTorchName(d.name)) then torchSlot = TORCH_SLOT_PREF; return torchSlot end
- end
- for i = 1, 16 do
- if (turtle.getItemCount(i) > 0) then
- local d = turtle.getItemDetail(i)
- if (d and isTorchName(d.name)) then torchSlot = i; return torchSlot end
- end
- end
- torchSlot = 0
- return 0
- end
- local function ensureTorchSlot(rescanEvery)
- if (torchSlot >= 1 and torchSlot <= 16 and turtle.getItemCount(torchSlot) > 0) then
- local d = turtle.getItemDetail(torchSlot)
- if (d and isTorchName(d.name)) then return end
- end
- if (rescanEvery and rescanEvery > 0 and (stepCount - lastTorchScanStep) < rescanEvery) then return end
- lastTorchScanStep = stepCount
- scanTorchSlot()
- dirtySteps = dirtySteps + 1; saveState(false)
- end
- local function placeTorchBackWall()
- if (torchSlot < 1 or torchSlot > 16 or turtle.getItemCount(torchSlot) <= 0) then return false end
- local sel = turtle.getSelectedSlot()
- turtle.select(torchSlot)
- turnRight(false); turnRight(false)
- local ok = false
- if (turtle.detect()) then ok = turtle.place() end
- turnRight(false); turnRight(false)
- turtle.select(sel)
- return ok
- end
- local function stairsDigOrAbort(label, inspectFn, digFn, fluidWhere, allowFluids)
- local ok, data = inspectFn()
- if (not ok) then return true end
- local n = (data and data.name) or "unknown"
- if (isTorchName(n)) then return true end
- if (isFluidName(n)) then
- if (FLUID_BLOCK_SLOT ~= 0 and tryFillFluid(fluidWhere)) then return true end
- if (allowFluids) then return true end
- abortHome("Stairs blocked by fluid (" .. label .. "): " .. n)
- return false
- end
- if (allowedBlockName(n)) then digFn(); suckAllAround(); return true end
- abortHome("Stairs blocked by non-allowed block (" .. label .. "): " .. n)
- return false
- end
- local function clearCeilHere(allowFluids)
- if (STAIR_HEADROOM <= 1) then return end
- stairsDigOrAbort("up", turtle.inspectUp, turtle.digUp, "up", allowFluids)
- if (STAIR_HEADROOM <= 2) then return end
- for _ = 2, STAIR_HEADROOM - 1 do moveStep("U", true, false); stairsDigOrAbort("up", turtle.inspectUp, turtle.digUp, "up", allowFluids) end
- for _ = 1, STAIR_HEADROOM - 2 do moveStep("D", true, false) end
- end
- local function shiftToLeft()
- turnLeft(false); moveStep("F", true, false); turnRight(false)
- end
- local function shiftToRight()
- turnRight(false); moveStep("F", true, false); turnLeft(false)
- end
- local function shiftBackFromLeft()
- turnLeft(false); moveStep("B", true, false); turnRight(false)
- end
- local function shiftBackFromRight()
- turnRight(false); moveStep("B", true, false); turnLeft(false)
- end
- local function sweep3Wide(fn)
- fn(0)
- if (STAIR_WIDTH < 3) then return end
- shiftToLeft(); fn(-1); shiftBackFromLeft()
- shiftToRight(); fn(1); shiftBackFromRight()
- end
- local function clearFrontHere(allowFluids)
- stairsDigOrAbort("front", turtle.inspect, turtle.dig, "front", allowFluids)
- end
- local function digDownHere(allowFluids)
- stairsDigOrAbort("down", turtle.inspectDown, turtle.digDown, "down", allowFluids)
- end
- local function safeForward(miningAllowed, record)
- ensureFuel()
- moveStep("F", miningAllowed, record)
- end
- local function safeDown(miningAllowed, record)
- ensureFuel()
- moveStep("D", miningAllowed, record)
- end
- local function tryPlaceTorchStairs()
- if (not STAIR_TORCHES or STAIR_TORCH_INTERVAL <= 0) then return end
- if ((stepCount % STAIR_TORCH_INTERVAL) ~= 0) then return end
- ensureTorchSlot(STAIR_TORCH_RESCAN_INTERVAL)
- if (torchSlot <= 0) then return end
- placeTorchBackWall()
- end
- local function digStairsDown(steps)
- for i = 1, steps do
- statusSend("stairs " .. i .. "/" .. steps, false)
- sweep3Wide(function() clearFrontHere(true); clearCeilHere(true) end)
- safeForward(true, true)
- sweep3Wide(function() clearCeilHere(true) end)
- sweep3Wide(function() digDownHere(true) end)
- safeDown(true, true)
- sweep3Wide(function() clearCeilHere(true) end)
- tryPlaceTorchStairs()
- end
- end
- local function scanForOres()
- if (not scanner) then return {} end
- local ok, res = pcall(function() return scanner.scan(radius) end)
- if (not ok or type(res) ~= "table") then return {} end
- local ores = {}
- for i = 1, #res do local b = res[i]; if (b and b.name and string.find(b.name, "ore", 1, true) ~= nil) then ores[#ores + 1] = b end end
- return ores
- end
- local function mineRowForward(len)
- for _ = 1, len do
- local ok, data = turtle.inspect()
- if (ok and data and data.name and isFluidName(data.name)) then
- local n = data.name
- if (FLUID_BLOCK_SLOT ~= 0 and tryFillFluid("front")) then else abortHome("Front blocked by fluid: " .. n) end
- elseif (ok and data and data.name and allowedBlockName(data.name)) then
- turtle.dig(); suckAllAround()
- elseif (ok and data and data.name) then
- abortHome("Blocked by non-allowed block in front: " .. data.name)
- end
- safeForward(true, true)
- end
- return true
- end
- local function mineRoomLayer()
- local rowLen = math.max(8, MINE_ROOM_LEN)
- for r = 1, MINE_ROOM_ROWS do
- statusSend("mine row " .. r .. "/" .. MINE_ROOM_ROWS, false)
- local _ = scanForOres()
- if (not mineRowForward(rowLen)) then return false end
- if (r < MINE_ROOM_ROWS) then
- if ((r % 2) == 1) then turnRight(true); safeForward(true, true); turnRight(true) else turnLeft(true); safeForward(true, true); turnLeft(true) end
- end
- end
- return true
- end
- local function mineLayers(layers)
- for l = 1, layers do
- statusSend("mine layer " .. l .. "/" .. layers, false)
- if (not mineRoomLayer()) then return false end
- if (l < layers) then for _ = 1, MINE_LAYER_DROP do safeDown(true, true) end end
- end
- return true
- end
- local function dropAllToChestAtHome()
- if (pos.x ~= home.x or pos.y ~= home.y or pos.z ~= home.z) then returnHomeFast("dump") end
- for slot = 1, 15 do
- turtle.select(slot)
- if (turtle.getItemCount(slot) > 0) then
- local startDir = dir
- local dropped = false
- for _ = 1, 4 do if (turtle.drop()) then dropped = true; break end; turnRight(false) end
- while (dir ~= startDir) do turnRight(false) end
- if (not dropped) then abortHome("No accessible chest adjacent at home (dump).") end
- end
- end
- turtle.select(1)
- end
- local function escapeFromBaseForwardNoDig()
- if (pos.x ~= home.x or pos.y ~= home.y or pos.z ~= home.z) then return end
- statusSend("escape", true)
- turnRight(true); turnRight(true)
- for i = 1, START_ESCAPE_STEPS do
- while (not turtle.forward()) do abortHome("Escape blocked (won't dig at home).") end
- updateForward()
- path[#path + 1] = "F"
- stepCount = stepCount + 1
- dirtySteps = dirtySteps + 1
- if (i == 1) then staging = { x = pos.x, y = pos.y, z = pos.z } end
- saveState(false)
- end
- saveState(true)
- end
- if (resume) then if (not loadState()) then resetNavToStart() end else resetNavToStart() end
- print("Mode:", mode)
- print("Radius:", radius)
- if (scanner) then print("Scanner:", scannerSide, scannerType) else print("Scanner: none (fallback mining only)") end
- if (MODEM_SIDE) then print("Modem:", MODEM_SIDE) else print("Modem: none") end
- statusSend("starting", true)
- refuelFromChest(FUEL_REFUEL_MIN)
- ensureTorchSlot(0)
- if (goHome) then
- if (not fs.exists(STATE_FILE) or not loadState()) then print("No state found. Can't go home safely."); return end
- if (type(path) == "table" and #path > 0) then returnViaPathNoDig("manual-home") else print("No recorded path. Refusing to dig home."); return end
- statusSend("idle", true)
- print("Done.")
- return
- end
- if (pos.x == home.x and pos.y == home.y and pos.z == home.z) then escapeFromBaseForwardNoDig() end
- if (STAIR_ENABLE and STAIR_STEPS > 0) then digStairsDown(STAIR_STEPS) end
- if (MINE_ENABLE) then if (mode == "both") then mineRoomLayer() else mineLayers(MINE_LAYERS) end end
- statusSend("return", true)
- returnHomeFast("finished")
- dropAllToChestAtHome()
- statusSend("idle", true)
- print("Done.")
Advertisement
Add Comment
Please, Sign In to add comment