398 lines
9.5 KiB
Lua
398 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"
|
|
local TASK = "task"
|
|
local FAILED = "failed"
|
|
-- Constant messaging
|
|
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)
|
|
reqData = {
|
|
token=TOKEN,
|
|
recipient=HOST,
|
|
sender=UNIT,
|
|
type=REQUEST,
|
|
request=request,
|
|
content=arg
|
|
}
|
|
modem.transmit(CHANNEL, CHANNEL, textutils.serialise(reqData))
|
|
end
|
|
|
|
local function sendLog(log, ...)
|
|
print("Sending message: " .. log)
|
|
logData = {
|
|
token=TOKEN,
|
|
recipient=HOST,
|
|
sender=UNIT,
|
|
type=LOG,
|
|
log=log,
|
|
content=arg
|
|
}
|
|
modem.transmit(CHANNEL, CHANNEL, textutils.serialise(logData))
|
|
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 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(name, f, ...)
|
|
sendLog(TASK, "Attempting to start task.")
|
|
if task ~= nil then
|
|
sendLog(FAILED, "Unable to start task due to another task running.")
|
|
return
|
|
end
|
|
task = {name=name, func=f, args=arg}
|
|
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(POSITION, "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(MOVEBY, "Attempting to move by (" .. delta.x .. "," .. delta.y .. "," .. delta.z .. ") (x,y,z).")
|
|
-- x first
|
|
if delta.x ~= 0 then
|
|
sendLog(MOVEBY, "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(MOVEBY, "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(MOVEBY, "Moving on y axis by: " .. delta.y)
|
|
for y=1,delta.y do
|
|
attemptMoveUp()
|
|
end
|
|
elseif delta.y < 0 then
|
|
sendLog(MOVEBY, "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
|
|
sendLog(TASK, "Executing task: " .. task["name"])
|
|
task["func"](unpack(task["args"]))
|
|
task = nil
|
|
end
|
|
sleep(5)
|
|
end
|
|
end
|
|
|
|
local function listen()
|
|
while running do
|
|
print("Listening for directives...")
|
|
local event, side, sendChannel, replyChannel, serialized, distance = os.pullEvent("modem_message")
|
|
print("Recieved data...")
|
|
local data = textutils.unserialise(serialized)
|
|
if data["token"] == TOKEN and data["recipient"] == UNIT and data["type"] == REQUEST then
|
|
print("Got request: " .. data["request"])
|
|
|
|
if data["request"] == LUA_PREFIX then
|
|
print("Executing: " .. data["content"][0])
|
|
local f = loadstring(luaScript)
|
|
if f ~= nil then
|
|
local freturn = f()
|
|
|
|
if freturn ~= nil then
|
|
sendLog(LUA_PREFIX, textutils.serialise(freturn))
|
|
end
|
|
else
|
|
printError("Unable to load lua string.")
|
|
end
|
|
elseif data["request"] == MOVETO then
|
|
local x = data["content"][1]
|
|
local y = data["content"][2]
|
|
local z = data["content"][3]
|
|
if heading ~= nil then
|
|
print("Using actual coordinates.")
|
|
sendLog(MOVETO, "Using actual coordinates to move.")
|
|
attemptStartTask(MOVETO, moveTo, vector.new(x,y,z), heading, rightAxis)
|
|
else
|
|
print("Using relative coordinates.")
|
|
sendLog(MOVETO, "Using relative coordinates to move.")
|
|
attemptStartTask(MOVETO, moveTo, vector.new(x,y,z), relHeading, relRightAxis)
|
|
end
|
|
elseif data["request"] == MOVEBY then
|
|
local x = data["content"][1]
|
|
local y = data["content"][2]
|
|
local z = data["content"][3]
|
|
if heading ~= nil then
|
|
print("Using actual coordinates.")
|
|
sendLog(MOVEBY, "Using actual coordinates to move.")
|
|
attemptStartTask(MOVEBY, moveBy, vector.new(x,y,z), heading, rightAxis)
|
|
else
|
|
print("Using relative coordinates.")
|
|
sendLog(MOVEBY, "Using relative coordinates to move.")
|
|
attemptStartTask(MOVEBY, moveBy, vector.new(x,y,z), relHeading, relRightAxis)
|
|
end
|
|
elseif data["request"] == STATUS then
|
|
status = {
|
|
relative_position = {
|
|
coordinates=relativePos,
|
|
forward=relHeading,
|
|
right=relRightAxis
|
|
},
|
|
position={
|
|
coordinates=position,
|
|
forward=heading,
|
|
right=rightAxis
|
|
},
|
|
fuel=turtle.getFuelLevel(),
|
|
task=(task and task["name"] or "nothing")
|
|
}
|
|
sendLog(STATUS, status)
|
|
elseif data["request"] == POSITION then
|
|
locatePosition()
|
|
elseif data["request"] == HEADING then
|
|
determineHeading()
|
|
elseif data["request"] == QUARRY then
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
parallel.waitForAll(listen, executeTasks) |