refactor: update turtle script for improved server-driven functionality and code organization
This commit is contained in:
795
turtle.lua
795
turtle.lua
@@ -1,306 +1,609 @@
|
||||
-- Advanced Autonomous Mining Turtle v4 (Eval/Response Protocol)
|
||||
-- Features: Server-driven state machine, UUID command correlation,
|
||||
-- GPS tracking, local fallback intelligence, block scanning
|
||||
-- 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_SEND = 101
|
||||
|
||||
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)
|
||||
local state = {
|
||||
mode = "idle",
|
||||
position = nil,
|
||||
homePosition = nil,
|
||||
fuel = 0,
|
||||
inventory = {},
|
||||
facing = 0,
|
||||
lastStatusUpdate = 0,
|
||||
evalSupported = true,
|
||||
|
||||
-- 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 = {
|
||||
statusUpdateInterval = 5,
|
||||
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)
|
||||
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)")
|
||||
print("ID: " .. os.getComputerID())
|
||||
|
||||
-- ========== Fuel & Inventory ==========print("ID: " .. os.getComputerID())
|
||||
|
||||
print("Modem opened on channel " .. CHANNEL_RECEIVE)
|
||||
|
||||
-- Store facing in global for eval access
|
||||
_G._turtleFacing = 0
|
||||
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 updatePosition()
|
||||
local x, y, z = gps.locate(2)
|
||||
if x then
|
||||
state.position = {x = math.floor(x), y = math.floor(y), z = math.floor(z)}
|
||||
return true
|
||||
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
|
||||
return false
|
||||
end
|
||||
|
||||
-- ========== Movement Functions (with position tracking) ==========
|
||||
endlocal function updateFacingAfterTurn(right)
|
||||
|
||||
local function updateFacingAfterTurn(right)
|
||||
if right then
|
||||
state.facing = (state.facing + 1) % 4
|
||||
|
||||
-- ========== Status Broadcasting ========== state.facing = (state.facing + 1) % 4
|
||||
|
||||
else
|
||||
state.facing = (state.facing - 1) % 4
|
||||
end
|
||||
_G._turtleFacing = state.facing
|
||||
|
||||
local function broadcastStatus() state.facing = (state.facing - 1) % 4
|
||||
|
||||
updateFuel() end
|
||||
|
||||
updateInventory() _G._turtleFacing = state.facing
|
||||
|
||||
end
|
||||
|
||||
local function smartForward()
|
||||
local surroundings = {}
|
||||
|
||||
local hasBlock, datalocal function smartForward()
|
||||
|
||||
local success = turtle.forward()
|
||||
if success and state.position then
|
||||
if state.facing == 0 then state.position.z = state.position.z - 1
|
||||
|
||||
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
|
||||
elseif state.facing == 2 then state.position.z = state.position.z + 1
|
||||
elseif state.facing == 3 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
|
||||
end
|
||||
return success
|
||||
|
||||
hasBlock, data = turtle.inspectDown() end
|
||||
|
||||
if hasBlock then surroundings.down = {name = data.name, metadata = data.metadata or 0} end return success
|
||||
|
||||
end
|
||||
|
||||
local function smartBack()
|
||||
local success = turtle.back()
|
||||
if success and state.position then
|
||||
if state.facing == 0 then state.position.z = state.position.z + 1
|
||||
elseif state.facing == 1 then state.position.x = state.position.x - 1
|
||||
elseif state.facing == 2 then state.position.z = state.position.z - 1
|
||||
elseif state.facing == 3 then state.position.x = state.position.x + 1
|
||||
end
|
||||
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()
|
||||
local success = turtle.up()
|
||||
if success and state.position then
|
||||
|
||||
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
|
||||
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
|
||||
-- ========== 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()
|
||||
|
||||
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
|
||||
local results = table.pack(pcall(fn)) return success
|
||||
|
||||
-- ========== Fuel & Inventory ==========
|
||||
local ok = results[1]end
|
||||
|
||||
local function updateFuel()
|
||||
state.fuel = turtle.getFuelLevel()
|
||||
return state.fuel
|
||||
end
|
||||
|
||||
local function tryRefuel()
|
||||
for slot = 1, 16 do
|
||||
turtle.select(slot)
|
||||
if turtle.refuel(0) then
|
||||
local count = turtle.getItemCount()
|
||||
if count > 0 then
|
||||
turtle.refuel(1)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
|
||||
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()
|
||||
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()
|
||||
-- ========== Message Processing ========== state.inventory = {}
|
||||
|
||||
for slot = 1, 16 do
|
||||
if turtle.getItemCount(slot) == 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
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
|
||||
return true
|
||||
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 ==========
|
||||
|
||||
local function scanAllDirections()
|
||||
if not state.position then return {} end
|
||||
|
||||
local scannedBlocks = {}
|
||||
local myID = os.getComputerID()
|
||||
|
||||
local function addBlock(relX, relY, relZ, blockData)
|
||||
if blockData and blockData.name then
|
||||
table.insert(scannedBlocks, {
|
||||
x = state.position.x + relX,
|
||||
y = state.position.y + relY,
|
||||
z = state.position.z + relZ,
|
||||
name = blockData.name,
|
||||
metadata = blockData.metadata or 0,
|
||||
discoveredBy = myID
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local hasBlock, data
|
||||
hasBlock, data = turtle.inspectUp()
|
||||
if hasBlock then addBlock(0, 1, 0, data) end
|
||||
|
||||
hasBlock, data = turtle.inspectDown()
|
||||
if hasBlock then addBlock(0, -1, 0, data) end
|
||||
|
||||
local originalFacing = state.facing
|
||||
for i = 0, 3 do
|
||||
hasBlock, data = turtle.inspect()
|
||||
if hasBlock then
|
||||
local relX, relZ = 0, 0
|
||||
if state.facing == 0 then relZ = -1
|
||||
elseif state.facing == 1 then relX = 1
|
||||
elseif state.facing == 2 then relZ = 1
|
||||
elseif state.facing == 3 then relX = -1
|
||||
end
|
||||
addBlock(relX, 0, relZ, data)
|
||||
end
|
||||
if i < 3 then smartTurnRight() end
|
||||
end
|
||||
|
||||
if state.facing ~= originalFacing then
|
||||
smartTurnRight()
|
||||
end
|
||||
|
||||
return scannedBlocks
|
||||
end
|
||||
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
|
||||
|
||||
local function reportDiscoveredBlocks(blocks)
|
||||
if #blocks == 0 then return end
|
||||
modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, {
|
||||
type = "blocks_discovered",
|
||||
turtleID = os.getComputerID(),
|
||||
blocks = blocks,
|
||||
timestamp = os.epoch("utc")
|
||||
})
|
||||
end
|
||||
|
||||
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 ==========
|
||||
|
||||
local function broadcastStatus()
|
||||
updateFuel()
|
||||
updateInventory()
|
||||
|
||||
local surroundings = {}
|
||||
local hasBlock, data
|
||||
|
||||
hasBlock, data = turtle.inspect()
|
||||
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
|
||||
|
||||
hasBlock, data = turtle.inspectUp()
|
||||
if hasBlock then surroundings.up = {name = data.name, metadata = data.metadata or 0} end
|
||||
|
||||
hasBlock, data = turtle.inspectDown()
|
||||
if hasBlock then surroundings.down = {name = data.name, metadata = data.metadata or 0} end
|
||||
|
||||
local statusPacket = {
|
||||
type = "status",
|
||||
turtleID = os.getComputerID(),
|
||||
mode = state.mode,
|
||||
position = state.position,
|
||||
homePosition = state.homePosition,
|
||||
fuel = state.fuel,
|
||||
inventoryCount = #state.inventory,
|
||||
|
||||
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,
|
||||
facing = state.facing,
|
||||
surroundings = surroundings,
|
||||
evalSupported = true,
|
||||
label = os.getComputerLabel(),
|
||||
}
|
||||
|
||||
modem.transmit(STATUS_CHANNEL, CHANNEL_RECEIVE, statusPacket)
|
||||
end
|
||||
|
||||
-- ========== Eval/Response Protocol ==========
|
||||
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),
|
||||
|
||||
local function executeEval(uuid, code)
|
||||
local fn, compileError = load(code, "eval", "t")
|
||||
if not fn then
|
||||
modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, {
|
||||
type = "eval_response",
|
||||
uuid = uuid,
|
||||
result = nil,
|
||||
error = "Compile error: " .. tostring(compileError),
|
||||
turtleID = os.getComputerID()
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local results = table.pack(pcall(fn))
|
||||
local ok = results[1]
|
||||
|
||||
if ok then
|
||||
|
||||
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
|
||||
if results.n <= 2 then
|
||||
-- Single return value
|
||||
returnVal = results[2]
|
||||
else
|
||||
-- Multiple return values - pack into array
|
||||
returnVal = {}
|
||||
for i = 2, results.n do
|
||||
returnVal[i - 1] = results[i]
|
||||
end
|
||||
end
|
||||
modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, {
|
||||
type = "eval_response",
|
||||
uuid = uuid,
|
||||
result = returnVal,
|
||||
error = nil,
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user