-- Server-Driven Turtle v5 (Pure Eval Protocol)-- Advanced Autonomous Mining Turtle v4 (Eval/Response Protocol) -- All behavior is driven by the server via eval commands.-- Features: Server-driven state machine, UUID command correlation, -- This script only handles: eval execution, status broadcasting,-- GPS tracking, local fallback intelligence, block scanning -- GPS tracking, inventory/peripheral events. local CHANNEL_RECEIVE = 100 local CHANNEL_RECEIVE = 100local CHANNEL_SEND = 101 local CHANNEL_SEND = 101local STATUS_CHANNEL = 102 local STATUS_CHANNEL = 102 -- State tracking (lightweight - server drives behavior via eval) -- State tracking (lightweight - server drives everything)local state = { local state = { mode = "idle", position = nil, position = nil, homePosition = nil, homePosition = nil, fuel = 0, fuel = 0, inventory = {}, inventory = {}, facing = 0, facing = 0, lastStatusUpdate = 0, lastStatusUpdate = 0, } evalSupported = true, } -- Configuration local config = {-- Configuration statusUpdateInterval = 5,local config = { } statusUpdateInterval = 5, valuableBlocks = { -- Check for modem ["minecraft:coal_ore"] = 1, local modem = peripheral.find("modem") ["minecraft:iron_ore"] = 2, if not modem then ["minecraft:gold_ore"] = 3, error("No wireless modem found!") ["minecraft:diamond_ore"] = 5, end ["minecraft:emerald_ore"] = 5, modem.open(CHANNEL_RECEIVE) ["minecraft:redstone_ore"] = 2, print("Server-Driven Turtle v5 (Pure Eval Protocol)") ["minecraft:lapis_ore"] = 2, print("ID: " .. os.getComputerID()) ["minecraft:deepslate_coal_ore"] = 1, print("Modem opened on channel " .. CHANNEL_RECEIVE) ["minecraft:deepslate_iron_ore"] = 2, ["minecraft:deepslate_gold_ore"] = 3, -- Store facing in global for eval access ["minecraft:deepslate_diamond_ore"] = 5, _G._turtleFacing = 0 ["minecraft:deepslate_emerald_ore"] = 5, ["minecraft:deepslate_redstone_ore"] = 2, -- ========== GPS Functions ========== ["minecraft:deepslate_lapis_ore"] = 2, } local function updatePosition()} local x, y, z = gps.locate(2) if x then-- Check for modem state.position = {x = math.floor(x), y = math.floor(y), z = math.floor(z)}local modem = peripheral.find("modem") return trueif not modem then end error("No wireless modem found!") return falseend endmodem.open(CHANNEL_RECEIVE) print("Advanced Mining Turtle v4 (Eval Protocol)") -- ========== Fuel & Inventory ==========print("ID: " .. os.getComputerID()) print("Modem opened on channel " .. CHANNEL_RECEIVE) local function updateFuel() state.fuel = turtle.getFuelLevel()-- Store facing in global for eval access return state.fuel_G._turtleFacing = 0 end -- ========== GPS Functions ========== local function updateInventory() state.inventory = {}local function updatePosition() for slot = 1, 16 do local x, y, z = gps.locate(2) local item = turtle.getItemDetail(slot) if x then if item then state.position = {x = math.floor(x), y = math.floor(y), z = math.floor(z)} table.insert(state.inventory, { return true slot = slot, end name = item.name, return false count = item.countend }) end-- ========== Movement Functions (with position tracking) ========== end endlocal function updateFacingAfterTurn(right) if right then -- ========== Status Broadcasting ========== state.facing = (state.facing + 1) % 4 else local function broadcastStatus() state.facing = (state.facing - 1) % 4 updateFuel() end updateInventory() _G._turtleFacing = state.facing end local surroundings = {} local hasBlock, datalocal function smartForward() local success = turtle.forward() hasBlock, data = turtle.inspect() if success and state.position then if hasBlock then surroundings.forward = {name = data.name, metadata = data.metadata or 0} end if state.facing == 0 then state.position.z = state.position.z - 1 elseif state.facing == 1 then state.position.x = state.position.x + 1 hasBlock, data = turtle.inspectUp() elseif state.facing == 2 then state.position.z = state.position.z + 1 if hasBlock then surroundings.up = {name = data.name, metadata = data.metadata or 0} end elseif state.facing == 3 then state.position.x = state.position.x - 1 end hasBlock, data = turtle.inspectDown() end if hasBlock then surroundings.down = {name = data.name, metadata = data.metadata or 0} end return success end local statusPacket = { type = "status",local function smartBack() turtleID = os.getComputerID(), local success = turtle.back() position = state.position, if success and state.position then homePosition = state.homePosition, if state.facing == 0 then state.position.z = state.position.z + 1 fuel = state.fuel, elseif state.facing == 1 then state.position.x = state.position.x - 1 inventoryCount = #state.inventory, elseif state.facing == 2 then state.position.z = state.position.z - 1 inventory = state.inventory, elseif state.facing == 3 then state.position.x = state.position.x + 1 facing = state.facing, end surroundings = surroundings, end evalSupported = true, return success label = os.getComputerLabel(),end } local function smartUp() modem.transmit(STATUS_CHANNEL, CHANNEL_RECEIVE, statusPacket) local success = turtle.up() end if success and state.position then state.position.y = state.position.y + 1 -- ========== Eval/Response Protocol ========== end return success local function executeEval(uuid, code)end local fn, compileError = load(code, "eval", "t") if not fn thenlocal function smartDown() modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { local success = turtle.down() type = "eval_response", if success and state.position then uuid = uuid, state.position.y = state.position.y - 1 result = nil, end error = "Compile error: " .. tostring(compileError), return success turtleID = os.getComputerID()end }) returnlocal function smartTurnRight() end local success = turtle.turnRight() if success then updateFacingAfterTurn(true) end local results = table.pack(pcall(fn)) return success local ok = results[1]end if ok thenlocal function smartTurnLeft() local returnVal local success = turtle.turnLeft() if results.n <= 2 then if success then updateFacingAfterTurn(false) end returnVal = results[2] return success elseend returnVal = {} for i = 2, results.n do-- ========== Fuel & Inventory ========== returnVal[i - 1] = results[i] endlocal function updateFuel() end state.fuel = turtle.getFuelLevel() modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { return state.fuel type = "eval_response",end uuid = uuid, result = returnVal,local function tryRefuel() error = nil, for slot = 1, 16 do turtleID = os.getComputerID() turtle.select(slot) }) if turtle.refuel(0) then else local count = turtle.getItemCount() modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { if count > 0 then type = "eval_response", turtle.refuel(1) uuid = uuid, return true result = nil, end error = "Runtime error: " .. tostring(results[2]), end turtleID = os.getComputerID() end }) return false endend end local function updateInventory() -- ========== Message Processing ========== state.inventory = {} for slot = 1, 16 do local function processMessage(channel, message) local item = turtle.getItemDetail(slot) if type(message) ~= "table" then return end if item then local myID = os.getComputerID() table.insert(state.inventory, { if message.target and message.target ~= myID then return end slot = slot, name = item.name, if message.type == "eval" and message.uuid and message.code then count = item.count print("Eval: " .. message.uuid:sub(1, 8) .. "...") }) executeEval(message.uuid, message.code) end end elseif message.type == "home_position" and message.turtleID == myID thenend if message.homePosition then state.homePosition = message.homePositionlocal function inventoryFull() print("Home synced from server") for slot = 1, 16 do end if turtle.getItemCount(slot) == 0 then return false elseif message.type == "home_set_confirm" and message.turtleID == myID then end if message.homePosition then end state.homePosition = message.homePosition return true print("Home confirmed by server")end end -- ========== Block Scanning ========== elseif message.type == "rename" and message.name then os.setComputerLabel(message.name)local function scanAllDirections() print("Renamed to: " .. message.name) if not state.position then return {} end broadcastStatus() end local scannedBlocks = {} end local myID = os.getComputerID() -- ========== Sync Home ========== local function addBlock(relX, relY, relZ, blockData) if blockData and blockData.name then local function syncHomeWithServer() table.insert(scannedBlocks, { modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { x = state.position.x + relX, type = "request_home", y = state.position.y + relY, turtleID = os.getComputerID() z = state.position.z + relZ, }) name = blockData.name, return true metadata = blockData.metadata or 0, end discoveredBy = myID }) -- ========== Initialization ========== end end print("Initializing...") local x, y, z = gps.locate(5) local hasBlock, data if x then hasBlock, data = turtle.inspectUp() state.position = {x = math.floor(x), y = math.floor(y), z = math.floor(z)} if hasBlock then addBlock(0, 1, 0, data) end print("GPS: OK - " .. state.position.x .. "," .. state.position.y .. "," .. state.position.z) else hasBlock, data = turtle.inspectDown() print("GPS: Not available") if hasBlock then addBlock(0, -1, 0, data) end state.position = nil end local originalFacing = state.facing for i = 0, 3 do syncHomeWithServer() hasBlock, data = turtle.inspect() updateFuel() if hasBlock then print("Ready! Turtle " .. os.getComputerID() .. " online (v5 server-driven)") local relX, relZ = 0, 0 broadcastStatus() if state.facing == 0 then relZ = -1 elseif state.facing == 1 then relX = 1 -- ========== Main Loop ========== elseif state.facing == 2 then relZ = 1 elseif state.facing == 3 then relX = -1 parallel.waitForAny( end function() addBlock(relX, 0, relZ, data) -- GPS retry loop end while true do if i < 3 then smartTurnRight() end if not state.position then end sleep(10) if updatePosition() then if state.facing ~= originalFacing then print("GPS acquired!") smartTurnRight() broadcastStatus() end end else return scannedBlocks sleep(30)end end endlocal function reportDiscoveredBlocks(blocks) end, if #blocks == 0 then return end modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { function() type = "blocks_discovered", -- Status broadcast loop turtleID = os.getComputerID(), while true do blocks = blocks, sleep(config.statusUpdateInterval) timestamp = os.epoch("utc") broadcastStatus() }) endend end, -- ========== Status Broadcasting ========== function() -- Command processing (eval protocol)local function broadcastStatus() while true do updateFuel() local event, side, channel, replyChannel, message = os.pullEvent("modem_message") updateInventory() if channel == CHANNEL_RECEIVE then processMessage(channel, message) local surroundings = {} end local hasBlock, data end end, hasBlock, data = turtle.inspect() if hasBlock then surroundings.forward = {name = data.name, metadata = data.metadata or 0} end function() -- Inventory change events (real-time) hasBlock, data = turtle.inspectUp() while true do if hasBlock then surroundings.up = {name = data.name, metadata = data.metadata or 0} end os.pullEvent("turtle_inventory") local inventory = {} hasBlock, data = turtle.inspectDown() for i = 1, 16 do if hasBlock then surroundings.down = {name = data.name, metadata = data.metadata or 0} end local item = turtle.getItemDetail(i) if item then local statusPacket = { table.insert(inventory, { type = "status", slot = i, turtleID = os.getComputerID(), name = item.name, mode = state.mode, count = item.count position = state.position, }) homePosition = state.homePosition, end fuel = state.fuel, end inventoryCount = #state.inventory, inventory = state.inventory, modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { facing = state.facing, type = "inventory_update", surroundings = surroundings, turtleID = os.getComputerID(), evalSupported = true, inventory = inventory, label = os.getComputerLabel(), timestamp = os.epoch("utc") } }) end modem.transmit(STATUS_CHANNEL, CHANNEL_RECEIVE, statusPacket) end,end function()-- ========== Eval/Response Protocol ========== -- Peripheral attached events (real-time) while true dolocal function executeEval(uuid, code) os.pullEvent("peripheral") local fn, compileError = load(code, "eval", "t") sleep(0.1) if not fn then local peripherals = {} modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { local names = peripheral.getNames() type = "eval_response", for _, name in ipairs(names) do uuid = uuid, peripherals[name] = {types = {peripheral.getType(name)}} result = nil, end error = "Compile error: " .. tostring(compileError), turtleID = os.getComputerID() modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { }) type = "peripheral_attached", return turtleID = os.getComputerID(), end peripherals = peripherals, timestamp = os.epoch("utc") local results = table.pack(pcall(fn)) }) local ok = results[1] end end, if ok then local returnVal function() if results.n <= 2 then -- Peripheral detached events (real-time) -- Single return value while true do returnVal = results[2] local _, side = os.pullEvent("peripheral_detach") else if not peripheral.isPresent(side) then -- Multiple return values - pack into array modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { returnVal = {} type = "peripheral_detached", for i = 2, results.n do turtleID = os.getComputerID(), returnVal[i - 1] = results[i] side = side, end timestamp = os.epoch("utc") end }) modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { end type = "eval_response", end uuid = uuid, end result = returnVal, ) error = nil, turtleID = os.getComputerID() }) else modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "eval_response", uuid = uuid, result = nil, error = "Runtime error: " .. tostring(results[2]), turtleID = os.getComputerID() }) end end -- ========== Legacy Command Handling ========== local legacyCommands = { 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 hasBlock, data = turtle.inspect() if hasBlock then turtle.dig() return true, "Dug: " .. (data.name or "block") end return false, "Nothing to dig" end, digUp = function() local hasBlock, data = turtle.inspectUp() if hasBlock then turtle.digUp() return true, "Dug up: " .. (data.name or "block") end return false, "Nothing above" end, digDown = function() local hasBlock, data = turtle.inspectDown() if hasBlock then turtle.digDown() return true, "Dug down: " .. (data.name or "block") end return false, "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, setHome = function() if not state.position then if not updatePosition() then return false, "No GPS" end end state.homePosition = { x = state.position.x, y = state.position.y, z = state.position.z } modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "set_home", turtleID = os.getComputerID(), position = state.homePosition }) return true, "Home set" end, explore = function() if not state.homePosition then if state.position then state.homePosition = { x = state.position.x, y = state.position.y, z = state.position.z } modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "set_home", turtleID = os.getComputerID(), position = state.homePosition }) else return false, "No home or GPS" end end state.mode = "exploring" broadcastStatus() return true, "Exploring" end, mine = function() if not state.homePosition then if state.position then state.homePosition = { x = state.position.x, y = state.position.y, z = state.position.z } modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "set_home", turtleID = os.getComputerID(), position = state.homePosition }) else return false, "No home or GPS" end end state.mode = "mining" broadcastStatus() return true, "Mining" end, returnHome = function() state.mode = "returning" broadcastStatus() return true, "Returning home" end, stop = function() state.mode = "idle" broadcastStatus() return true, "Stopped" end, manual = function() state.mode = "manual" broadcastStatus() return true, "Manual control" end, } local function processLegacyCommand(message) if type(message) ~= "table" then return end local myID = os.getComputerID() if message.target and message.target ~= myID then return end if message.command then local handler = legacyCommands[message.command] if handler then local success, result = handler(message.param) modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { status = success and "ok" or "error", message = result or "", turtleID = myID }) broadcastStatus() end end end -- ========== Message Processing ========== local function processMessage(channel, message) if type(message) ~= "table" then return end local myID = os.getComputerID() if message.target and message.target ~= myID then return end if message.type == "eval" and message.uuid and message.code then print("Eval: " .. message.uuid:sub(1, 8) .. "...") executeEval(message.uuid, message.code) if message.stateUpdate then state.mode = message.stateUpdate end elseif message.type == "state_change" and message.state then state.mode = message.state broadcastStatus() elseif message.type == "home_position" and message.turtleID == myID then if message.homePosition then state.homePosition = message.homePosition print("Home synced from server") end elseif message.type == "home_set_confirm" and message.turtleID == myID then if message.homePosition then state.homePosition = message.homePosition print("Home confirmed by server") end elseif message.type == "rename" and message.name then os.setComputerLabel(message.name) print("Renamed to: " .. message.name) broadcastStatus() elseif message.command then processLegacyCommand(message) end end -- ========== Local Autonomous Behavior (fallback) ========== local localStuckCounter = 0 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 local function localExploreStep() if state.position then local blocks = scanAllDirections() if #blocks > 0 then reportDiscoveredBlocks(blocks) end end -- Mine valuable ores for _, direction in ipairs({"forward", "up", "down"}) do local inspectFn = direction == "forward" and turtle.inspect or direction == "up" and turtle.inspectUp or turtle.inspectDown local digFn = direction == "forward" and turtle.dig or direction == "up" and turtle.digUp or turtle.digDown local hasBlock, data = inspectFn() if hasBlock and config.valuableBlocks[data.name] then digFn() end end local r = math.random(1, 100) if r < 75 then local hasBlock = turtle.inspect() if hasBlock then turtle.dig() end if not smartForward() then smartTurnRight() localStuckCounter = localStuckCounter + 1 else localStuckCounter = 0 end elseif r < 90 and state.position and state.position.y > 15 then local hasBlock = turtle.inspectDown() if hasBlock then turtle.digDown() end smartDown() else local hasBlock = turtle.inspectUp() if hasBlock then turtle.digUp() end smartUp() end if localStuckCounter > 5 then turtle.digUp() smartUp() localStuckCounter = 0 end end local function localReturnHomeStep() if not state.homePosition or not state.position then state.mode = "idle" return true end if getDistance(state.position, state.homePosition) <= 1 then state.mode = "idle" broadcastStatus() return true end local dx = state.homePosition.x - state.position.x local dy = state.homePosition.y - state.position.y local dz = state.homePosition.z - state.position.z if math.abs(dy) > 3 then if dy > 0 then turtle.digUp(); smartUp() else turtle.digDown(); smartDown() end else 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 while state.facing ~= targetFacing do smartTurnRight() end turtle.dig() if not smartForward() then smartTurnRight() end end return false end -- ========== Sync Home ========== local function syncHomeWithServer() modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "request_home", turtleID = os.getComputerID() }) return true end -- ========== Initialization ========== print("Initializing...") 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 - " .. state.position.x .. "," .. state.position.y .. "," .. state.position.z) else print("GPS: Not available") state.position = nil end syncHomeWithServer() updateFuel() print("Ready! Turtle " .. os.getComputerID() .. " online (v4 eval protocol)") broadcastStatus() -- ========== Main Loop ========== parallel.waitForAny( function() -- GPS retry while true do if not state.position then sleep(10) if updatePosition() then print("GPS acquired!") broadcastStatus() end else sleep(30) end end end, function() -- Status broadcast while true do sleep(config.statusUpdateInterval) broadcastStatus() end end, function() -- Command processing while true do local event, side, channel, replyChannel, message = os.pullEvent("modem_message") if channel == CHANNEL_RECEIVE then processMessage(channel, message) end end end, function() -- Inventory change events (real-time) while true do os.pullEvent("turtle_inventory") local inventory = {} for i = 1, 16 do local item = turtle.getItemDetail(i) if item then table.insert(inventory, { slot = i, name = item.name, count = item.count }) end end modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "inventory_update", turtleID = os.getComputerID(), inventory = inventory, timestamp = os.epoch("utc") }) end end, function() -- Peripheral attached events (real-time) while true do os.pullEvent("peripheral") sleep(0.1) -- Small delay to let CC register local peripherals = {} local names = peripheral.getNames() for _, name in ipairs(names) do peripherals[name] = {types = {peripheral.getType(name)}} end modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "peripheral_attached", turtleID = os.getComputerID(), peripherals = peripherals, timestamp = os.epoch("utc") }) end end, function() -- Peripheral detached events (real-time) while true do local _, side = os.pullEvent("peripheral_detach") if not peripheral.isPresent(side) then modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, { type = "peripheral_detached", turtleID = os.getComputerID(), side = side, timestamp = os.epoch("utc") }) end end end, function() -- Local autonomous fallback while true do if state.mode == "exploring" or state.mode == "mining" then updateFuel() if state.position and state.homePosition then local dist = getDistance(state.position, state.homePosition) if dist > 200 then state.mode = "returning" broadcastStatus() elseif state.fuel ~= "unlimited" and state.fuel < 500 then if not tryRefuel() then state.mode = "returning" broadcastStatus() end elseif inventoryFull() then state.mode = "returning" broadcastStatus() else localExploreStep() sleep(0.2) end else localExploreStep() sleep(0.2) end elseif state.mode == "returning" then local done = localReturnHomeStep() if not done then sleep(0.1) end else sleep(0.5) end end end )