-- 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 } -- 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 local function syncHomeWithServer() if not http then print("HTTP not available, can't sync with server") return false end local url = "http://webbridge:3001/api/turtle/" .. os.getComputerID() .. "/home" local response = http.get(url) if response then local data = textutils.unserializeJSON(response.readAll()) response.close() if data and data.homePosition then state.homePosition = data.homePosition print("📍 Synced home from server:", textutils.serialize(data.homePosition)) return true end end return false end -- Set home position (server-authoritative) local function setHome() print("Setting home position...") if not updatePosition() then print("Failed to get GPS position for home") return false end -- Send to server if http then local url = "http://webbridge:3001/api/turtle/" .. os.getComputerID() .. "/home" local response = http.post(url, textutils.serializeJSON({ position = state.position }), {["Content-Type"] = "application/json"}) if response then local data = textutils.unserializeJSON(response.readAll()) response.close() if data and data.success then state.homePosition = data.homePosition print("✅ Home set at:", textutils.serialize(state.homePosition)) return true end end end -- Fallback to local storage if server unavailable state.homePosition = { x = state.position.x, y = state.position.y, z = state.position.z } print("⚠️ Home set locally (server unavailable)") 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 -- 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 with better navigation local function returnHome() print("Returning home...") state.mode = "returning" state.stuckCounter = 0 broadcastStatus() local maxAttempts = 1000 local attempts = 0 while state.homePosition and state.position and getDistance(state.position, state.homePosition) > 1 and attempts < maxAttempts do -- Check for stop command if state.mode ~= "returning" then print("Return cancelled") return end updateFuel() if needsRefuel() then print("Low fuel, trying to refuel...") if tryRefuel() then print("Refueled!") else print("WARNING: Out of fuel!") state.mode = "idle" broadcastStatus() return end end local arrived = navigateTowards(state.homePosition) if arrived then break end attempts = attempts + 1 -- Update GPS position every few steps if attempts % 10 == 0 then updatePosition() print("Distance to home: " .. getDistance(state.position, state.homePosition)) end sleep(0.1) end if attempts >= maxAttempts then print("Could not reach home - gave up after " .. maxAttempts .. " attempts") else print("Arrived at home!") end state.mode = "idle" state.stuckCounter = 0 broadcastStatus() end -- Exploration algorithm local function exploreStep() -- Check all directions for valuable ores for _, direction in ipairs({"forward", "up", "down"}) do local dug, valuable, blockName = smartDig(direction) if valuable then print("Found: " .. blockName) broadcastStatus() end end -- Random exploration with preference for going deeper local r = math.random(1, 10) if r <= 3 then -- Go down 30% of the time if not smartDown() then smartDig("down") smartDown() end elseif r <= 5 then -- Turn if math.random() > 0.5 then smartTurnRight() else smartTurnLeft() end else -- Move forward if not smartForward() then smartDig("forward") if not smartForward() then smartTurnRight() end 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 return false, "Home not set! Use setHome first" end if isTooFarFromHome() then return false, "Already at max distance from home" end state.mode = "exploring" state.stuckCounter = 0 broadcastStatus() return true, "Starting exploration" end, mine = function() print("Mine command received") if not state.homePosition then return false, "Home not set! Use setHome first" end if isTooFarFromHome() then return false, "Already at max distance from home" end state.mode = "exploring" -- Use exploring mode for mining state.stuckCounter = 0 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.") 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() -- 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 processMessage(message) 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...") state.mode = "returning" broadcastStatus() -- 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") state.mode = "returning" broadcastStatus() else exploreStep() sleep(0.2) end elseif state.mode == "returning" then returnHome() else -- Idle or manual mode sleep(0.5) end end end )