-- pastebin ID: LXSNkj5r -- URL: https://pastebin.com/LXSNkj5r local logFilePath = "mine.log" local noChest = false local startChest = true -- Make startChest the default behavior -- Precious blocks list - blocks to detect and avoid mining unless blocking path local preciousBlocks = { "diamond", "lapis", "debris" } -- Mainframe communication local MAINFRAME_ID = nil local modemSide = nil local detectionRunning = false -- Direction vectors: north (-Z), east (+X), south (+Z), west (-X) local dirs = { [0] = {x = 0, z = -1}, -- North [1] = {x = 1, z = 0}, -- East [2] = {x = 0, z = 1}, -- South [3] = {x = -1, z = 0}, -- West } -- Initial state - use relative coordinates for movement local pos = {x = 0, y = 0, z = 0} local heading = 0 -- 0=north, 1=east, 2=south, 3=west -- Function to find and open modem function openModem() if modemSide then return true end local sides = {"left", "right", "top", "bottom", "front", "back"} for _, side in ipairs(sides) do if peripheral.getType(side) == "modem" then rednet.open(side) modemSide = side log("Modem opened on " .. side) return true end end log("No modem found for mainframe communication") return false end -- Function to discover mainframe ID via broadcast function discoverMainframe() if MAINFRAME_ID then return MAINFRAME_ID end if not openModem() then log("Cannot discover mainframe - no modem available") return nil end log("Broadcasting to discover mainframe...") rednet.broadcast("discover_mainframe") -- Wait for responses for up to 3 seconds local timeout = os.clock() + 3 while os.clock() < timeout do local senderId, message = rednet.receive(0.1) if senderId and message == "mainframe_here" then MAINFRAME_ID = senderId log("Discovered mainframe at ID: " .. MAINFRAME_ID) return MAINFRAME_ID end end log("No mainframe found via broadcast") return nil end -- Function to report precious block to mainframe function reportPreciousBlock(blockName, x, y, z) local mainframeId = discoverMainframe() if mainframeId and openModem() then local message = { type = "precious", blockName = blockName, x = x, y = y, z = z } rednet.send(mainframeId, message) log("Reported to mainframe " .. mainframeId .. ": " .. blockName .. " at (" .. x .. ", " .. y .. ", " .. z .. ")") else log("Cannot report precious block - mainframe not available") end end -- Function to report current GPS location to mainframe function reportLocationToMainframe() local mainframeId = discoverMainframe() if mainframeId and openModem() then local gpsX, gpsY, gpsZ = gps.locate() if gpsX and gpsY and gpsZ then local message = { type = "location", x = gpsX, y = gpsY, z = gpsZ } rednet.send(mainframeId, message) log("Reported location to mainframe " .. mainframeId .. ": (" .. gpsX .. ", " .. gpsY .. ", " .. gpsZ .. ")") else -- Fallback to relative coordinates if GPS not available local absPos = getAbsolutePosition() local message = { type = "location", x = absPos.x, y = absPos.y, z = absPos.z } rednet.send(mainframeId, message) log("Reported relative location to mainframe " .. mainframeId .. ": (" .. absPos.x .. ", " .. absPos.y .. ", " .. absPos.z .. ")") end else log("Cannot report location - mainframe not available") end end -- Function to scrub precious locations from mainframe for this turtle function scrubPreciousLocations() local mainframeId = discoverMainframe() if mainframeId and openModem() then local myId = os.getComputerID() local message = "scrub_precious " .. myId rednet.send(mainframeId, message) log("Requested mainframe " .. mainframeId .. " to scrub precious locations for turtle " .. myId) -- Wait for confirmation local timeout = os.clock() + 2 while os.clock() < timeout do local senderId, response = rednet.receive(0.1) if senderId == mainframeId and type(response) == "string" and string.find(response, "Scrubbed") then log("Mainframe confirmed: " .. response) return true end end log("No confirmation received from mainframe for scrub request") else log("Cannot scrub precious locations - mainframe not available") end return false end -- Continuous precious block detection that runs in parallel function continuousDetection() detectionRunning = true log("Starting continuous precious block detection...") while detectionRunning do -- Get current GPS coordinates directly local gpsX, gpsY, gpsZ = gps.locate() if not gpsX then -- Fallback to relative coordinates if GPS not available gpsX, gpsY, gpsZ = pos.x, pos.y, pos.z end -- Check only forward, up, and down directions (no side inspection to avoid interfering with mining) local directions = { {name = "forward", detect = turtle.inspect}, {name = "up", detect = turtle.inspectUp}, {name = "down", detect = turtle.inspectDown} } -- Check forward, up, down only for _, dir in ipairs(directions) do local success, data = dir.detect() if success and data and data.name and isPreciousBlock(data.name) then reportPreciousBlock(data.name, gpsX, gpsY, gpsZ) end end -- Sleep briefly to avoid overwhelming the system sleep(0.5) end log("Continuous precious block detection stopped") end -- Function to stop continuous detection function stopDetection() detectionRunning = false end -- Function to log messages to a file function log(message) local file = fs.open(logFilePath, "a") print(message) file.writeLine(message) file.close() end -- Function to clean block name by removing everything before ':' function cleanBlockName(blockName) if not blockName then return "unknown" end local colonPos = string.find(blockName, ":") if colonPos then return string.sub(blockName, colonPos + 1) else return blockName end end -- Function to check if a block name contains precious materials function isPreciousBlock(blockName) if not blockName then return false end for _, precious in ipairs(preciousBlocks) do if string.find(string.lower(blockName), precious) then return true end end return false end -- Function to detect and log precious blocks in all directions function detectPreciousBlocks() local directions = { {name = "forward", detect = turtle.inspect, pos = "front"}, {name = "up", detect = turtle.inspectUp, pos = "above"}, {name = "down", detect = turtle.inspectDown, pos = "below"} } for _, dir in ipairs(directions) do local success, data = dir.detect() if success and data and data.name then if isPreciousBlock(data.name) then log("PRECIOUS BLOCK DETECTED " .. dir.pos .. ": " .. data.name .. " at relative position (" .. pos.x .. ", " .. pos.y .. ", " .. pos.z .. ")") end end end end -- Function to get GPS coordinates for absolute positioning function getGPSPosition() local x, y, z = gps.locate() if x and y and z then log("GPS coordinates obtained: (" .. x .. ", " .. y .. ", " .. z .. ")") return {x = x, y = y, z = z} else log("WARNING: GPS not available, absolute coordinates will not be available") return nil end end -- Get starting GPS position for absolute coordinate conversion local startGPS = getGPSPosition() -- Function to get current absolute coordinates function getAbsolutePosition() if startGPS then return { x = startGPS.x + pos.x, y = startGPS.y + pos.y, z = startGPS.z + pos.z } else -- If GPS not available, return relative coordinates return {x = pos.x, y = pos.y, z = pos.z} end end -- Helpers function turnLeft() turtle.turnLeft() heading = (heading - 1 + 4) % 4 -- Ensure positive modulo result end function turnRight() turtle.turnRight() heading = (heading + 1) % 4 end function moveForward() while not turtle.forward() do turtle.attack() digForward() sleep(0.5) end pos.x = pos.x + dirs[heading].x pos.z = pos.z + dirs[heading].z reportLocationToMainframe() end function moveBackward() turtle.back() pos.x = pos.x - dirs[heading].x pos.z = pos.z - dirs[heading].z reportLocationToMainframe() end function moveUp() while not turtle.up() do turtle.attackUp() digUp() sleep(0.5) end pos.y = pos.y + 1 reportLocationToMainframe() end function moveDown() while not turtle.down() do turtle.attackDown() digDown() sleep(0.5) end pos.y = pos.y - 1 reportLocationToMainframe() end function digForward() while turtle.detect() do turtle.dig() sleep(0.3) end end function digUp() while turtle.detectUp() do turtle.digUp() sleep(0.3) end end function digDown() while turtle.detectDown() do turtle.digDown() sleep(0.3) end end function isInventoryFull() for i = 1, 16 do if turtle.getItemCount(i) == 0 then return false end end log("InventoryFull. startChest: " .. tostring(startChest) .. ", noChest: " .. tostring(noChest)) return true end function refuelIfNeeded() for i = 1, 16 do turtle.select(i) local itemDetail = turtle.getItemDetail() if itemDetail and string.find(itemDetail.name, "coal") then while turtle.getItemCount(i) > 0 do turtle.refuel(1) end log("Refueled with " .. itemDetail.name .. " from slot " .. i) end end turtle.select(1) end function dumpJunk() local junkItems = { "cobblestone", "diorite", "gravel", "dirt", "tuff", "blackstone", "pebble", "polished blackstone wall", "nether brick wall", "nether brick fence", "red nether brick", "nether brick staires", "cracked nether bricks", "nether bricks", "granite", "deepslate", "netherrack", "rhyolite", "schist", "pebble", "asphalt", "andesite" } for i = 1, 16 do turtle.select(i) local itemDetail = turtle.getItemDetail() if itemDetail then for _, junk in ipairs(junkItems) do if string.find(itemDetail.name, junk) then turtle.drop() log("Dropped junk item: " .. itemDetail.name .. " from slot " .. i) break end end end end turtle.select(1) end -- Safe digging functions for digTriplet - avoid precious blocks that aren't blocking movement function digForwardSafe() while turtle.detect() do local success, data = turtle.inspect() if success and data and data.name and isPreciousBlock(data.name) then local cleanedName = cleanBlockName(data.name) log("AVOIDING precious block in front (not blocking path): " .. cleanedName .. " at position (" .. pos.x .. ", " .. pos.y .. ", " .. pos.z .. ")") break -- Don't dig precious blocks when just clearing area end turtle.dig() sleep(0.3) end end function digUpSafe() while turtle.detectUp() do local success, data = turtle.inspectUp() if success and data and data.name and isPreciousBlock(data.name) then local cleanedName = cleanBlockName(data.name) log("AVOIDING precious block above (not blocking path): " .. cleanedName .. " at position (" .. pos.x .. ", " .. pos.y + 1 .. ", " .. pos.z .. ")") break -- Don't dig precious blocks when just clearing area end turtle.digUp() sleep(0.3) end end function digDownSafe() while turtle.detectDown() do local success, data = turtle.inspectDown() if success and data and data.name and isPreciousBlock(data.name) then local cleanedName = cleanBlockName(data.name) log("AVOIDING precious block below (not blocking path): " .. cleanedName .. " at position (" .. pos.x .. ", " .. pos.y - 1 .. ", " .. pos.z .. ")") break -- Don't dig precious blocks when just clearing area end turtle.digDown() sleep(0.3) end end function digTriplet() -- Detect precious blocks in all directions before mining detectPreciousBlocks() digForwardSafe() -- Use safe version - not actually moving forward here moveForward() -- Detect precious blocks again after moving detectPreciousBlocks() -- Use safe digging for up/down since turtle isn't moving in those directions digUpSafe() digDownSafe() end function dig() digTriplet() if isInventoryFull() then log("Checking where to drop the stuff. startChest: " .. tostring(startChest) .. ", noChest: " .. tostring(noChest)) if noChest then for i = 1, 16 do turtle.select(i) turtle.drop() end elseif startChest then local currentPos = {x = pos.x, y = pos.y, z = pos.z, d = heading} goTo(0, 0, 0, 2) for i = 1, 16 do turtle.select(i) turtle.drop() end goTo(currentPos.x, currentPos.y, currentPos.z, currentPos.d) -- Return to the original position else placeChestAndUnload() end end -- log("Dug block at position: (" .. pos.x .. ", " .. pos.y .. ", " .. pos.z .. ")") end function placeChestAndUnload() turtle.select(1) -- Select slot 1, assuming it's for the chest -- Loop until a chest is found in slot 1 local itemInSlot1 = turtle.getItemDetail(1) while not itemInSlot1 or not string.find(itemInSlot1.name, "chest") do log("Waiting for chest in slot 1. Current item: " .. (itemInSlot1 and itemInSlot1.name or "nil")) print("Please place a chest in slot 1 to continue.") sleep(2) -- Wait for 2 seconds before re-checking itemInSlot1 = turtle.getItemDetail(1) end -- Now that a chest is confirmed in slot 1, proceed with placing it while not turtle.placeDown() do log("Waiting to place chest. Please ensure the space below is clear.") print("Waiting to place chest. Please ensure the space below is clear.") sleep(2) -- Wait for 2 seconds before retrying end log("Placed chest below at position: (" .. pos.x .. ", " .. pos.y .. ", " .. pos.z .. ")") for i = 2, 16 do -- Start from slot 2, assuming slot 1 is for the chest turtle.select(i) turtle.dropDown() end turtle.select(1) -- Re-select slot 1 end function digTunnel(x) for i = 1, x do dig() end refuelIfNeeded() dumpJunk() end function goTo(x, y, z, d) while pos.y < y do moveUp() end while pos.y > y do moveDown() end local dx = x - pos.x if dx ~= 0 then -- Determine target heading based on dx local targetHeadingX = (dx > 0) and 1 or 3 -- East or West faceDirection(targetHeadingX) for i = 1, math.abs(dx) do digTriplet() end end local dz = z - pos.z if dz ~= 0 then -- Determine target heading based on dz local targetHeadingZ = (dz > 0) and 2 or 0 -- South or North faceDirection(targetHeadingZ) for i = 1, math.abs(dz) do digTriplet() end end faceDirection(d) end function faceDirection(dir) while heading ~= dir do turnRight() end end local args = { ... } function digLayer(width, length, spacing) tunnelLength = width - 1 numTunnels = math.floor((length + spacing) / (1 + spacing)) log("Starting layer mining with tunnel length: " .. tunnelLength .. ", number of tunnels: " .. numTunnels .. ", spacing: " .. spacing) for _ = 1, math.floor(numTunnels / 2) do -- Move to start of first tunnel (connecting segment) digTunnel(1 + spacing) -- Turn into first main tunnel turnLeft() digTunnel(tunnelLength) -- Turn to move to next connecting segment turnRight() digTunnel(1 + spacing) -- Turn into second main tunnel turnRight() digTunnel(tunnelLength) -- Turn back to original orientation for next pair of tunnels turnLeft() end if numTunnels % 2 == 1 then log("Warning: numTunnels is odd. The last tunnel might not follow the full zig-zag pattern.") end if noChest then log("No chest mode: Dropping items on the ground.") for i = 1, 16 do turtle.select(i) turtle.drop() end elseif startChest then log("Start chest mode: Returning to start to unload.") goTo(0, 0, 0, 2) for i = 1, 16 do turtle.select(i) turtle.drop() end end end -- Mining function that runs the actual mining operations function runMining() local width = tonumber(args[1]) local length = tonumber(args[2]) local tspacing = tonumber(args[3]) local layers = tonumber(args[4]) local lspacing = tonumber(args[5]) for i = 1, layers do log("Starting layer ".. i) goTo(0, - (i - 1) * (3 + lspacing), 0, 0) digLayer(width, length, tspacing) end if noChest then log("No chest mode: Dropping items on the ground.") for i = 1, 16 do turtle.select(i) turtle.drop() end elseif startChest then log("Start chest mode: Returning to start to unload.") goTo(0, 0, 0, 2) for i = 1, 16 do turtle.select(i) turtle.drop() end end goTo(0, 0, 0, 0) -- Stop continuous detection when mining is complete stopDetection() log("Mining complete.") end function main() if #args < 5 then print("Usage: mine [--nochest | --nostartchest]") return end local width = tonumber(args[1]) local length = tonumber(args[2]) local tspacing = tonumber(args[3]) local layers = tonumber(args[4]) local lspacing = tonumber(args[5]) -- Parse optional flags for i = 6, #args do if args[i] == "--nochest" then log("Detected --nochest") noChest = true startChest = false -- Override default when --nochest is specified elseif args[i] == "--nostartchest" then log("Detected --nostartchest") startChest = false end end log("startChest: " .. tostring(startChest) .. ", noChest: " .. tostring(noChest)) if not width or not length or not tspacing or not layers or not lspacing then print("Invalid input.") return end -- Scrub previous precious locations when starting new mining operation log("Starting new mining operation - scrubbing previous precious locations...") scrubPreciousLocations() -- Report initial location to mainframe reportLocationToMainframe() -- Run mining and continuous detection in parallel parallel.waitForAll(runMining, continuousDetection) end main()