388 lines
9.5 KiB
Lua
388 lines
9.5 KiB
Lua
--configurables
|
|
local CHANNEL = 55555
|
|
local TOKEN = "LxdIjZPDLL2oZoayb7uR2Lbz7bnnbkxz"
|
|
|
|
-- Constant
|
|
local HOST = "HOST"
|
|
local UNIT = "LEAD"
|
|
local LUA_PREFIX = "?"
|
|
-- Constant actions
|
|
local MOVEBY = "moveby"
|
|
local MOVETO = "moveto"
|
|
local STATUS = "status"
|
|
local POSITION = "position"
|
|
local HEADING = "heading"
|
|
local QUARRY = "quarry"
|
|
-- Constant log
|
|
local LOG = "LOG"
|
|
local REQUEST = "REQ"
|
|
-- Constant requests
|
|
local BLOCKED = "blocked"
|
|
local ITEM = "item"
|
|
|
|
-- INIT SEQUENCE
|
|
print("Initiating leader mining turtle.")
|
|
|
|
running = true
|
|
local task = nil
|
|
local taskArgs = {}
|
|
local modem = nil
|
|
local heading = nil
|
|
local position = nil
|
|
local rightAxis = nil
|
|
local relHeading = vector.new(1,0,0)
|
|
local relativePos = vector.new(0,0,0)
|
|
local relRightAxis = vector.new(0,0,1)
|
|
|
|
do
|
|
periphs = peripheral.find("modem")
|
|
if not periphs then
|
|
error("Modem peripheral not found.")
|
|
else
|
|
print("Modem found.")
|
|
modem = periphs
|
|
end
|
|
end
|
|
print("Opening channel: " .. CHANNEL)
|
|
modem.open(CHANNEL)
|
|
|
|
-- helpers
|
|
local function getMessage(data)
|
|
if string.find(data, TOKEN .. ":") == 1 then
|
|
print("Validated data token.")
|
|
local validated = string.sub(data, string.len(TOKEN) + 1 + 1)
|
|
print("Validated sequence: " .. validated)
|
|
if string.find(validated, UNIT .. ":") == 1 then
|
|
print("Checking unit...")
|
|
return string.sub(validated, string.len(UNIT) + 1 + 1)
|
|
end
|
|
end
|
|
print("Data was unable to be parsed.")
|
|
return nil
|
|
end
|
|
|
|
local function SendRequest(request)
|
|
print("Sending request: " .. request)
|
|
modem.transmit(CHANNEL, CHANNEL, TOKEN .. ":" .. HOST .. ":" .. UNIT .. ":" .. REQUEST .. ":" .. request)
|
|
end
|
|
|
|
local function sendLog(log)
|
|
print("Sending message: " .. log)
|
|
modem.transmit(CHANNEL, CHANNEL, TOKEN .. ":" .. HOST .. ":" .. UNIT .. ":" .. LOG .. ":" .. log)
|
|
end
|
|
|
|
local function captureString(str, seq)
|
|
if seq == nil then seq = "([^%s]+)" end
|
|
res = {}
|
|
for i in string.gmatch(str, seq) do
|
|
table.insert(res, i)
|
|
end
|
|
return res
|
|
end
|
|
|
|
local function interpretData(data)
|
|
res = captureString(data, "([^%\][^%:]+)")
|
|
if res ~= nil then
|
|
res[5] = table.concat(res, ":", 5)
|
|
return res[1], res[2], res[3], res[4], res[5]
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function findItem(str)
|
|
for s=1,16 do
|
|
if string.sub(str, -string.len(str)) == str then
|
|
return s
|
|
end
|
|
end
|
|
return 0
|
|
end
|
|
|
|
local function refuel()
|
|
local slot = findItem("coal")
|
|
if slot == 0 then
|
|
--TODO: request more coal
|
|
end
|
|
turtle.select(slot)
|
|
turtle.refuel()
|
|
end
|
|
|
|
local function checkFuel()
|
|
if turtle.getFuelLevel() > 0 then return false end
|
|
refuel()
|
|
return true;
|
|
end
|
|
|
|
local function vectorEqual(a, b)
|
|
return a.x == b.x and a.y == b.y and a.z == b.z
|
|
end
|
|
|
|
local function attemptMove(movef)
|
|
if not movef() then
|
|
refuel()
|
|
return movef();
|
|
end
|
|
return true
|
|
end
|
|
|
|
local function attemptMoveUp()
|
|
if attemptMove(turtle.up) then
|
|
relativePos.y = relativePos.y + 1
|
|
if position ~= nil then position.y = position.y + 1 end
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function attemptMoveDown()
|
|
if attemptMove(turtle.down) then
|
|
relativePos.y = relativePos.y - 1
|
|
if position ~= nil then position.y = position.y - 1 end
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function attemptMoveForward()
|
|
if attemptMove(turtle.forward) then
|
|
relativePos = relativePos + relHeading
|
|
if (position ~= nil and heading ~= nil) then
|
|
position = position + heading
|
|
end
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function attemptMoveBackward()
|
|
if attemptMove(turtle.back) then
|
|
relativePos = relativePos - relHeading
|
|
if (position ~= nil and heading ~= nil) then
|
|
position = position - heading
|
|
end
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function attemptMoveLeft()
|
|
if attemptMove(turtle.turnLeft) then
|
|
local previousHeading = relHeading
|
|
relHeading = -relRightAxis
|
|
relRightAxis = previousHeading
|
|
|
|
if heading ~= nil then
|
|
local previousHeading = heading
|
|
heading = -rightAxis
|
|
rightAxis = previousHeading
|
|
end
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function attemptMoveRight()
|
|
if attemptMove(turtle.turnRight) then
|
|
local previousHeading = relHeading
|
|
relHeading = relRightAxis
|
|
relRightAxis = -previousHeading
|
|
|
|
if heading ~= nil then
|
|
local previousHeading = heading
|
|
heading = rightAxis
|
|
rightAxis = -previousHeading
|
|
end
|
|
return true
|
|
end
|
|
return true
|
|
end
|
|
|
|
local function orient(v, forward, right)
|
|
print("Attempting to orient such that " .. tostring(v) .. " == " .. tostring(forward) .. ".")
|
|
if vectorEqual(v, forward) then
|
|
return
|
|
elseif vectorEqual(v, right) then
|
|
attemptMoveRight()
|
|
elseif vectorEqual(v, -right) then
|
|
attemptMoveLeft()
|
|
else
|
|
attemptMoveRight()
|
|
attemptMoveRight()
|
|
end
|
|
print("Orientation complete.")
|
|
end
|
|
|
|
local function attemptStartTask(f, ...)
|
|
sendLog("attempting to start a task.")
|
|
if task ~= nil then
|
|
sendLog("failed: unable to start task due to another task running.")
|
|
return
|
|
end
|
|
task = f
|
|
taskArgs = arg
|
|
end
|
|
|
|
-- actions
|
|
|
|
local function locatePosition()
|
|
sendLog("position: using GPS to determine position.")
|
|
local x, y, z = gps.locate()
|
|
if x == nil then sendLog("failed: could not locate.") end
|
|
position = vector.new(x, y, z)
|
|
end
|
|
|
|
local function determineHeading()
|
|
sendLog("heading: calculating heading.")
|
|
if position == nil then
|
|
sendLog("failed: no current position")
|
|
return
|
|
end
|
|
local oldPos = vector.new(position.x, position.y, position.z)
|
|
if not attemptMoveForward() then
|
|
sendLog("failed: could not move to get delta.")
|
|
return
|
|
end
|
|
if x == nil then
|
|
sendLog("failed: could not locate.")
|
|
return
|
|
end
|
|
heading = position - oldPos
|
|
|
|
|
|
if not attemptMoveRight() then
|
|
sendLog("failed: unable to rotate right.")
|
|
heading = nil
|
|
return
|
|
end
|
|
local oldPos = vector.new(position.x, position.y, position.z)
|
|
if not attemptMoveForward() then
|
|
sendLog("failed: unable to move forward after rotation.")
|
|
heading = nil
|
|
return
|
|
end
|
|
if not attemptMoveLeft() then
|
|
sendLog("failed: unable to rotate left.")
|
|
heading = nil
|
|
return
|
|
end
|
|
rightAxis = position - oldPos
|
|
end
|
|
|
|
local function moveBy(delta, forward, right)
|
|
sendLog("Attempting to move by (" .. delta.x .. "," .. delta.y .. "," .. delta.z .. ") (x,y,z).")
|
|
-- x first
|
|
if delta.x ~= 0 then
|
|
sendLog("Moving on x axis by: " .. delta.x)
|
|
orient(vector.new(delta.x, 0, 0):normalize(), forward, right)
|
|
for x=1,math.abs(delta.x) do
|
|
attemptMoveForward()
|
|
end
|
|
end
|
|
if delta.z ~= 0 then
|
|
sendLog("Moving on z axis by: " .. delta.z)
|
|
orient(vector.new(0, 0, delta.z):normalize(), forward, right)
|
|
for z=1,math.abs(delta.z) do
|
|
attemptMoveForward()
|
|
end
|
|
end
|
|
if delta.y > 0 then
|
|
sendLog("Moving on y axis by: " .. delta.y)
|
|
for y=1,delta.y do
|
|
attemptMoveUp()
|
|
end
|
|
elseif delta.y < 0 then
|
|
sendLog("Moving on y axis by: " .. delta.y)
|
|
for y=1,math.abs(delta.y) do
|
|
attemptMoveDown()
|
|
end
|
|
end
|
|
end
|
|
|
|
local function quarry(a, b)
|
|
sendLog("quarry: Starting quarry task from positions " .. tostring(a) .. " to " .. tostring(b) ".")
|
|
end
|
|
|
|
local function executeTasks()
|
|
while running do
|
|
if task ~= nil then
|
|
task(unpack(taskArgs))
|
|
task = nil
|
|
end
|
|
sleep(5)
|
|
end
|
|
end
|
|
|
|
local function listen()
|
|
while running do
|
|
print("Listening for directives...")
|
|
local event, side, sendChannel, replyChannel, data, distance = os.pullEvent("modem_message")
|
|
print("Recieved data: " .. data)
|
|
local token, recipient, sender, type, content = interpretData(data)
|
|
if token == TOKEN and recipient == UNIT then
|
|
print("Got content: " .. content)
|
|
if string.find(content, LUA_PREFIX) == 1 then
|
|
local luaScript = string.sub(content, string.len(LUA_PREFIX) + 1)
|
|
print("Executing: " .. luaScript)
|
|
local f = loadstring(luaScript)
|
|
if f ~= nil then
|
|
local freturn = f()
|
|
|
|
if freturn ~= nil then
|
|
modem.transmit(CHANNEL, CHANNEL, TOKEN .. ":" .. UNIT .. ":" .. "obj" .. ":")
|
|
modem.transmit(CHANNEL, CHANNEL, freturn)
|
|
end
|
|
else
|
|
printError("Unable to load lua string.")
|
|
end
|
|
elseif string.find(content, MOVETO .. ":") == 1 then
|
|
local coordsRaw = string.sub(content, string.len(MOVETO .. ":") + 1)
|
|
print("Raw coordinate data: " .. coordsRaw)
|
|
local coords = captureString(coordsRaw, "([+-]?%d+)")
|
|
local x = coords[1]
|
|
local y = coords[2]
|
|
local z = coords[3]
|
|
if heading ~= nil then
|
|
attemptStartTask(moveTo, vector.new(x,y,z), heading, rightAxis)
|
|
else
|
|
attemptStartTask(moveTo, vector.new(x,y,z), relHeading, relRightAxis)
|
|
end
|
|
elseif string.find(content, MOVEBY .. ":") == 1 then
|
|
local valuesRaw = string.sub(content, string.len(MOVEBY .. ":") + 1)
|
|
print("Raw coordinate data: " .. valuesRaw)
|
|
local deltas = captureString(valuesRaw, "([+-]?%d+)")
|
|
local x = deltas[1]
|
|
local y = deltas[2]
|
|
local z = deltas[3]
|
|
if heading ~= nil then
|
|
print("Using actual coordinates.")
|
|
attemptStartTask(moveBy, vector.new(x,y,z), heading, rightAxis)
|
|
else
|
|
print("Using relative coordinates.")
|
|
attemptStartTask(moveBy, vector.new(x,y,z), relHeading, relRightAxis)
|
|
end
|
|
elseif string.find(content, STATUS) == 1 then
|
|
status = {
|
|
relative_position = {
|
|
coordinates=relativePos,
|
|
forward=relHeading,
|
|
right=relRightAxis
|
|
},
|
|
position={
|
|
coordinates=position,
|
|
forward=heading,
|
|
right=rightAxis
|
|
},
|
|
fuel=turtle.getFuelLevel(),
|
|
}
|
|
sendLog("status:" .. textutils.serialise(status))
|
|
elseif string.find(content, POSITION) == 1 then
|
|
locatePosition()
|
|
elseif string.find(content, HEADING) == 1 then
|
|
determineHeading()
|
|
elseif string.find(content, QUARRY) == 1 then
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
parallel.waitForAll(listen, executeTasks) |