-- Advanced Autonomous Mining Turtle (FIXED v3) -- Features: GPS tracking, auto-mining, fuel management, smart navigation local CHANNEL_RECEIVE = 100 local CHANNEL_SEND = 101 local STATUS_CHANNEL = 102 -- State management local state = { mode = "idle", -- idle, manual, exploring, mining, returning position = nil, homePosition = nil, fuel = 0, inventory = {}, target = nil, path = {}, lastStatusUpdate = 0, stuckCounter = 0, visitedPositions = {}, -- Track where we've been lastPosition = nil, stuckInHoleCounter = 0 } -- Configuration local config = { minFuelToReturn = 500, minFuelToExplore = 1000, statusUpdateInterval = 5, -- seconds maxStuckAttempts = 3, maxDistanceFromHome = 200, -- blocks - stay within reasonable range pauseIfNoPlayersNearby = false, -- set true if chunk loading is concern valuableBlocks = { ["minecraft:coal_ore"] = 1, ["minecraft:iron_ore"] = 2, ["minecraft:gold_ore"] = 3, ["minecraft:diamond_ore"] = 5, ["minecraft:emerald_ore"] = 5, ["minecraft:redstone_ore"] = 2, ["minecraft:lapis_ore"] = 2, ["minecraft:deepslate_coal_ore"] = 1, ["minecraft:deepslate_iron_ore"] = 2, ["minecraft:deepslate_gold_ore"] = 3, ["minecraft:deepslate_diamond_ore"] = 5, ["minecraft:deepslate_emerald_ore"] = 5, ["minecraft:deepslate_redstone_ore"] = 2, ["minecraft:deepslate_lapis_ore"] = 2, } } -- Check for modem local modem = peripheral.find("modem") if not modem then error("No wireless modem found!") end modem.open(CHANNEL_RECEIVE) print("Advanced Mining Turtle System") print("ID: " .. os.getComputerID()) -- GPS Functions local function updatePosition() -- Quick GPS check with short timeout local x, y, z = gps.locate(2) -- 2 second timeout if x then state.position = {x = math.floor(x), y = math.floor(y), z = math.floor(z)} return true end return false end -- Sync home position with server (via wireless broadcast) local function syncHomeWithServer() -- Request home position from server via webbridge print("Requesting home position from server...") modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "request_home", turtleID = os.getComputerID() }) -- Don't block - just request and continue -- The response will be handled in the message processing loop return true end -- Set home position (server-authoritative via wireless) local function setHome() print("Setting home position...") -- If we don't have current position, try to get it -- But don't block if we already have it if not state.position then if not updatePosition() then print("Failed to get GPS position for home") return false end end -- Set locally immediately state.homePosition = { x = state.position.x, y = state.position.y, z = state.position.z } -- Send to server via wireless (fire and forget) modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "set_home", turtleID = os.getComputerID(), position = state.homePosition }) print("✅ Home set at:", textutils.serialize(state.homePosition)) print(" (Syncing with server in background)") return true end -- Movement tracking local facing = 0 -- 0=North(Z-), 1=East(X+), 2=South(Z+), 3=West(X-) local function updateFacingAfterTurn(right) if right then facing = (facing + 1) % 4 else facing = (facing - 1) % 4 end end local function smartForward() local success = turtle.forward() if success and state.position then if facing == 0 then state.position.z = state.position.z - 1 elseif facing == 1 then state.position.x = state.position.x + 1 elseif facing == 2 then state.position.z = state.position.z + 1 elseif facing == 3 then state.position.x = state.position.x - 1 end end return success end local function smartBack() local success = turtle.back() if success and state.position then if facing == 0 then state.position.z = state.position.z + 1 elseif facing == 1 then state.position.x = state.position.x - 1 elseif facing == 2 then state.position.z = state.position.z - 1 elseif facing == 3 then state.position.x = state.position.x + 1 end end return success end local function smartUp() local success = turtle.up() if success and state.position then state.position.y = state.position.y + 1 end return success end local function smartDown() local success = turtle.down() if success and state.position then state.position.y = state.position.y - 1 end return success end local function smartTurnRight() local success = turtle.turnRight() if success then updateFacingAfterTurn(true) end return success end local function smartTurnLeft() local success = turtle.turnLeft() if success then updateFacingAfterTurn(false) end return success end -- Fuel management local function updateFuel() state.fuel = turtle.getFuelLevel() return state.fuel end local function needsRefuel() return state.fuel ~= "unlimited" and state.fuel < config.minFuelToReturn end local function tryRefuel() for slot = 1, 16 do turtle.select(slot) if turtle.refuel(0) then -- Check if it's fuel local count = turtle.getItemCount() if count > 0 then turtle.refuel(1) return true end end end return false end -- Inventory management local function updateInventory() state.inventory = {} for slot = 1, 16 do local item = turtle.getItemDetail(slot) if item then table.insert(state.inventory, { slot = slot, name = item.name, count = item.count }) end end end local function inventoryFull() for slot = 1, 16 do if turtle.getItemCount(slot) == 0 then return false end end return true end local function isValuableBlock(blockName) return config.valuableBlocks[blockName] ~= nil end -- Check if block is unbreakable local function isUnbreakable(blockName) if not blockName then return false end return string.find(blockName, "bedrock") or string.find(blockName, "barrier") end -- Mining functions local function smartDig(direction) direction = direction or "forward" local digFunc, inspectFunc if direction == "forward" then digFunc = turtle.dig inspectFunc = turtle.inspect elseif direction == "up" then digFunc = turtle.digUp inspectFunc = turtle.inspectUp elseif direction == "down" then digFunc = turtle.digDown inspectFunc = turtle.inspectDown end local hasBlock, data = inspectFunc() if hasBlock then if isUnbreakable(data.name) then return false, false, data.name end local valuable = isValuableBlock(data.name) digFunc() return true, valuable, data.name end return false, false, nil end -- Pathfinding (improved with obstacle handling) local function getDistance(pos1, pos2) return math.abs(pos1.x - pos2.x) + math.abs(pos1.y - pos2.y) + math.abs(pos1.z - pos2.z) end -- Check if turtle is too far from home local function isTooFarFromHome() if not state.position or not state.homePosition then return false end local distance = getDistance(state.position, state.homePosition) return distance > config.maxDistanceFromHome end -- Check if it's safe to continue operations (for chunk loading concerns) local function shouldPauseOperations() if not config.pauseIfNoPlayersNearby then return false -- Feature disabled end -- You can add player detection logic here if using commands -- For now, just check distance from home as a safety measure return isTooFarFromHome() end -- Try to dig and move forward local function forceForward() for i = 1, 5 do if smartForward() then return true end smartDig("forward") sleep(0.3) end return false end -- Try to dig and move up local function forceUp() for i = 1, 5 do if smartUp() then return true end smartDig("up") sleep(0.3) end return false end -- Try to dig and move down local function forceDown() for i = 1, 5 do if smartDown() then return true end smartDig("down") sleep(0.3) end return false end -- Advanced navigation with unstuck logic local function navigateTowards(target) if not state.position or not target then return false end local dx = target.x - state.position.x local dy = target.y - state.position.y local dz = target.z - state.position.z local lastPos = {x = state.position.x, y = state.position.y, z = state.position.z} -- Prioritize vertical movement if needed if math.abs(dy) > 3 then if dy > 0 then if forceUp() then state.stuckCounter = 0 return false end else if forceDown() then state.stuckCounter = 0 return false end end end -- Horizontal movement local targetFacing if math.abs(dx) > math.abs(dz) then targetFacing = dx > 0 and 1 or 3 else targetFacing = dz > 0 and 2 or 0 end -- Face the right direction while facing ~= targetFacing do smartTurnRight() end -- Try to move forward if forceForward() then state.stuckCounter = 0 else -- Stuck! Try alternative routes state.stuckCounter = state.stuckCounter + 1 print("Stuck counter: " .. state.stuckCounter) if state.stuckCounter > config.maxStuckAttempts then print("Trying alternative path...") state.stuckCounter = 0 -- Try going up to go over obstacle if forceUp() then return false end -- Try going around smartTurnRight() if forceForward() then return false end smartTurnLeft() smartTurnLeft() if forceForward() then return false end -- Last resort: dig down and try lower path smartTurnRight() forceDown() end end -- Check if we're close enough return getDistance(state.position, target) < 2 end -- Status broadcasting function broadcastStatus() updateFuel() updateInventory() -- Don't update position on every broadcast to avoid GPS delays -- Position will be updated by movement functions -- Debug: Log current position if state.position then print(string.format("Broadcasting position: X=%d Y=%d Z=%d", state.position.x, state.position.y, state.position.z)) else print("Broadcasting with NO POSITION (waiting for GPS)") end -- Scan surrounding blocks for map visualization local surroundings = {} local hasBlock, data -- Check forward hasBlock, data = turtle.inspect() if hasBlock and data then surroundings.forward = {name = data.name, metadata = data.metadata or 0} end -- Check up hasBlock, data = turtle.inspectUp() if hasBlock and data then surroundings.up = {name = data.name, metadata = data.metadata or 0} end -- Check down hasBlock, data = turtle.inspectDown() if hasBlock and data then surroundings.down = {name = data.name, metadata = data.metadata or 0} end modem.transmit(STATUS_CHANNEL, CHANNEL_RECEIVE, { type = "status", turtleID = os.getComputerID(), mode = state.mode, position = state.position, homePosition = state.homePosition, fuel = state.fuel, inventoryCount = #state.inventory, inventory = state.inventory, facing = facing, surroundings = surroundings }) end -- Return to home step (non-blocking) local returnHomeAttempts = 0 local function returnHomeStep() if not state.homePosition or not state.position then print("No home or position set!") state.mode = "idle" broadcastStatus() return true -- Done (failed) end if getDistance(state.position, state.homePosition) <= 1 then print("Arrived at home!") state.mode = "idle" state.stuckCounter = 0 broadcastStatus() return true -- Done (success) end if returnHomeAttempts >= 1000 then print("Could not reach home - gave up after 1000 attempts") state.mode = "idle" broadcastStatus() return true -- Done (failed) end updateFuel() if needsRefuel() then print("Low fuel, trying to refuel...") if not tryRefuel() then print("WARNING: Out of fuel!") state.mode = "idle" broadcastStatus() return true -- Done (failed) end print("Refueled!") end navigateTowards(state.homePosition) returnHomeAttempts = returnHomeAttempts + 1 -- Update GPS position every few steps if returnHomeAttempts % 10 == 0 then updatePosition() print("Distance to home: " .. getDistance(state.position, state.homePosition)) end return false -- Not done yet end -- Start return home (just initialize) local function returnHome() print("Returning home...") state.mode = "returning" state.stuckCounter = 0 returnHomeAttempts = 0 broadcastStatus() end -- Helper functions for intelligent exploration local function positionKey(pos) if not pos then return nil end return string.format("%d,%d,%d", pos.x, pos.y, pos.z) end local function hasVisited(pos) local key = positionKey(pos) return state.visitedPositions[key] ~= nil end local function markVisited(pos) local key = positionKey(pos) state.visitedPositions[key] = os.epoch("utc") end local function isStuckInSamePosition() if not state.lastPosition or not state.position then return false end return state.lastPosition.x == state.position.x and state.lastPosition.y == state.position.y and state.lastPosition.z == state.position.z end local function canMoveInDirection(direction) if direction == "forward" then local hasBlock = turtle.inspect() return not hasBlock elseif direction == "up" then local hasBlock = turtle.inspectUp() return not hasBlock elseif direction == "down" then local hasBlock = turtle.inspectDown() return not hasBlock end return false end local function isInHole() -- Check if turtle is in a hole (blocks above preventing escape) local aboveBlocked = turtle.inspectUp() local forwardBlocked = turtle.inspect() -- If above is blocked and we can't move forward easily, we might be in a hole return aboveBlocked and forwardBlocked end local function tryClimbOut() print("Attempting to climb out of hole...") -- Try to dig up and go up for i = 1, 3 do if canMoveInDirection("up") then if smartUp() then print("Climbed up 1 block") state.stuckInHoleCounter = 0 return true end else smartDig("up") sleep(0.1) end end -- Try all horizontal directions for i = 1, 4 do if canMoveInDirection("forward") then if smartForward() then print("Moved forward out of hole") state.stuckInHoleCounter = 0 return true end else smartDig("forward") sleep(0.1) if smartForward() then print("Dug and moved forward") state.stuckInHoleCounter = 0 return true end end smartTurnRight() end return false end -- Exploration algorithm with intelligent navigation local function exploreStep() -- Mark current position as visited if state.position then markVisited(state.position) end -- Check if stuck in same position if isStuckInSamePosition() then state.stuckInHoleCounter = state.stuckInHoleCounter + 1 if state.stuckInHoleCounter > 5 then print("⚠️ Stuck for " .. state.stuckInHoleCounter .. " steps!") end else state.stuckInHoleCounter = 0 end -- Save current position for next check if state.position then state.lastPosition = { x = state.position.x, y = state.position.y, z = state.position.z } end -- Check all directions for valuable ores first (priority) for _, direction in ipairs({"forward", "up", "down"}) do local dug, valuable, blockName = smartDig(direction) if valuable then print("💎 Found: " .. blockName) broadcastStatus() end end -- Only try to climb out if REALLY stuck (not just after a few steps) if state.stuckInHoleCounter > 8 then print("Trying to escape - stuck for too long") if tryClimbOut() then return end end -- Check what's around us local hasBlockUp, dataUp = turtle.inspectUp() local hasBlockForward, dataForward = turtle.inspect() local hasBlockDown, dataDown = turtle.inspectDown() -- Calculate positions for each direction local forwardPos = nil local upPos = nil local downPos = nil if state.position then -- Forward position forwardPos = {x = state.position.x, y = state.position.y, z = state.position.z} if facing == 0 then forwardPos.z = forwardPos.z - 1 elseif facing == 1 then forwardPos.x = forwardPos.x + 1 elseif facing == 2 then forwardPos.z = forwardPos.z + 1 elseif facing == 3 then forwardPos.x = forwardPos.x - 1 end -- Up and down positions upPos = {x = state.position.x, y = state.position.y + 1, z = state.position.z} downPos = {x = state.position.x, y = state.position.y - 1, z = state.position.z} end -- Check which directions have been visited local forwardVisited = hasVisited(forwardPos) local upVisited = hasVisited(upPos) local downVisited = hasVisited(downPos) -- Main exploration logic - heavily favor horizontal movement local r = math.random(1, 100) -- 75% of the time: horizontal exploration (forward movement + turns) if r < 75 then -- Try to move forward if unvisited if not forwardVisited then if hasBlockForward then smartDig("forward") end if smartForward() then return end end -- If forward is visited, try to find an unvisited direction local foundUnvisited = false for i = 1, 4 do if state.position then local testPos = {x = state.position.x, y = state.position.y, z = state.position.z} if facing == 0 then testPos.z = testPos.z - 1 elseif facing == 1 then testPos.x = testPos.x + 1 elseif facing == 2 then testPos.z = testPos.z + 1 elseif facing == 3 then testPos.x = testPos.x - 1 end if not hasVisited(testPos) then -- Found unvisited direction! local hasBlock = turtle.inspect() if hasBlock then smartDig("forward") end if smartForward() then foundUnvisited = true return end end end -- Only turn if we haven't found a direction yet if i < 4 then smartTurnRight() end end -- If all directions visited, just move forward anyway (dig if needed) if not foundUnvisited then if hasBlockForward then smartDig("forward") end if not smartForward() then -- Can't move forward at all, turn once and try again next step smartTurnRight() end end -- 15% down (only if safe and not too deep) elseif r < 90 and state.position and state.position.y > 15 and not downVisited then if hasBlockDown then smartDig("down") end smartDown() -- 10% up (only if needed - not visited or somewhat deep) elseif r < 100 and (not upVisited or (state.position and state.position.y < 10)) then if hasBlockUp then smartDig("up") end smartUp() -- Fallback: just move forward else if hasBlockForward then smartDig("forward") end if not smartForward() then -- Turn if can't move smartTurnRight() end end end -- Command handling local commands = { forward = function() return smartForward(), "Moved forward" end, back = function() return smartBack(), "Moved back" end, up = function() return smartUp(), "Moved up" end, down = function() return smartDown(), "Moved down" end, turnLeft = function() return smartTurnLeft(), "Turned left" end, turnRight = function() return smartTurnRight(), "Turned right" end, dig = function() local dug, val, name = smartDig("forward") return dug, dug and "Dug: " .. (name or "block") or "Nothing to dig" end, digUp = function() local dug, val, name = smartDig("up") return dug, dug and "Dug up: " .. (name or "block") or "Nothing above" end, digDown = function() local dug, val, name = smartDig("down") return dug, dug and "Dug down: " .. (name or "block") or "Nothing below" end, place = function() return turtle.place(), "Placed" end, select = function(slot) return turtle.select(slot), "Selected slot " .. slot end, refuel = function() local success = tryRefuel() updateFuel() broadcastStatus() return success, success and ("Refueled! Now: " .. state.fuel) or "No fuel" end, status = function() broadcastStatus() return true, "Status sent" end, -- Autonomous commands setHome = function() return setHome(), "Home set" end, explore = function() print("Explore command received") if not state.homePosition then -- Auto-set home at current position if we have GPS if state.position then print("Auto-setting home at current position") state.homePosition = { x = state.position.x, y = state.position.y, z = state.position.z } -- Sync to server modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "set_home", turtleID = os.getComputerID(), position = state.homePosition }) print("✅ Home auto-set at:", textutils.serialize(state.homePosition)) else return false, "Home not set and no GPS available! Use setHome first" end end if isTooFarFromHome() then return false, "Already at max distance from home" end state.mode = "exploring" state.stuckCounter = 0 state.stuckInHoleCounter = 0 state.visitedPositions = {} -- Clear visited positions for new exploration state.lastPosition = nil print("Starting fresh exploration with intelligent navigation") broadcastStatus() return true, "Starting exploration" end, mine = function() print("Mine command received") if not state.homePosition then -- Auto-set home at current position if we have GPS if state.position then print("Auto-setting home at current position") state.homePosition = { x = state.position.x, y = state.position.y, z = state.position.z } -- Sync to server modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "set_home", turtleID = os.getComputerID(), position = state.homePosition }) print("✅ Home auto-set at:", textutils.serialize(state.homePosition)) else return false, "Home not set and no GPS available! Use setHome first" end end if isTooFarFromHome() then return false, "Already at max distance from home" end state.mode = "exploring" -- Use exploring mode for mining state.stuckCounter = 0 state.stuckInHoleCounter = 0 state.visitedPositions = {} -- Clear visited positions for new mining state.lastPosition = nil print("Starting mining with intelligent navigation") broadcastStatus() return true, "Starting mining" end, returnHome = function() print("Return home command received") state.mode = "returning" state.stuckCounter = 0 broadcastStatus() return true, "Returning home" end, stop = function() print("STOP command received") state.mode = "idle" state.stuckCounter = 0 broadcastStatus() return true, "Stopped" end, manual = function() state.mode = "manual" broadcastStatus() return true, "Manual control" end, } -- Process incoming messages local function processMessage(message) if type(message) ~= "table" then return end -- Check if message is targeted to this turtle local myID = os.getComputerID() if message.target and message.target ~= myID then -- This command is for a different turtle, ignore it return end print("Received command message") print(" Target: " .. tostring(message.target)) print(" My ID: " .. myID) if message.command then print(" Command: " .. message.command) local handler = commands[message.command] if handler then print(" Executing command...") local success, result = handler(message.param) modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { status = success and "ok" or "error", message = result or "", turtleID = myID }) broadcastStatus() else print(" No handler found for command: " .. message.command) end end end -- Main loop print("Initializing...") print("Checking for wireless modem...") if not modem then print("ERROR: Wireless modem not found!") else print("Wireless modem: OK") end print("Attempting quick GPS check...") -- Single quick GPS attempt (5 second timeout instead of 10) local x, y, z = gps.locate(5) if x then state.position = {x = math.floor(x), y = math.floor(y), z = math.floor(z)} print("GPS: OK - Position acquired!") else print("GPS: Not available - will retry in background") print("Position tracking disabled for now.") -- Initialize position to nil so we know we need GPS state.position = nil print("⚠️ WARNING: Without GPS, relative positioning will be inaccurate!") print("⚠️ Please place GPS hosts or set home position manually.") end -- Sync state with server print("Syncing with server...") if syncHomeWithServer() then print("✅ Server sync complete") else print("⚠️ Server sync failed, using local state") end updateFuel() print("Ready! Waiting for commands...") print("Broadcasting initial status...") broadcastStatus() print("Turtle " .. os.getComputerID() .. " is online!") -- Main execution loop parallel.waitForAny( function() -- GPS retry loop for turtles without initial position while not state.position do sleep(10) -- Try every 10 seconds print("Retrying GPS...") if updatePosition() then print("✅ GPS acquired! Position:", textutils.serialize(state.position)) broadcastStatus() -- Send updated position immediately end end end, function() -- Status broadcast loop while true do sleep(config.statusUpdateInterval) broadcastStatus() end end, function() -- Command processing loop while true do local event, side, channel, replyChannel, message = os.pullEvent() if event == "modem_message" then print("Modem message on channel " .. channel) if channel == CHANNEL_RECEIVE then -- Handle home position sync responses if type(message) == "table" then if message.type == "home_position" and message.turtleID == os.getComputerID() then if message.homePosition then state.homePosition = message.homePosition print("📍 Synced home from server:", textutils.serialize(message.homePosition)) else print("No home position on server") end elseif message.type == "home_set_confirm" and message.turtleID == os.getComputerID() then if message.homePosition then state.homePosition = message.homePosition print("✅ Server confirmed home:", textutils.serialize(message.homePosition)) end else -- Regular command processing processMessage(message) end else processMessage(message) end end end end end, function() -- Autonomous execution loop while true do if state.mode == "exploring" then updateFuel() -- Safety check: too far from home if isTooFarFromHome() then print("Too far from home! Returning...") returnHome() -- Initialize return home -- Check if we need to pause (chunk loading concern) elseif shouldPauseOperations() then print("Pausing operations (safety limit)") state.mode = "idle" broadcastStatus() -- Check if we should stop elseif needsRefuel() or inventoryFull() then print("Need to return home") returnHome() -- Initialize return home else exploreStep() sleep(0.2) end elseif state.mode == "returning" then -- Non-blocking return home step local done = returnHomeStep() if not done then sleep(0.1) end else -- Idle or manual mode sleep(0.5) end end end )