ccminingturtle/mineleader.lua

503 lines
12 KiB
Lua
Raw Normal View History

2021-05-02 00:39:10 +00:00
--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"
2021-05-03 23:15:22 +00:00
local QUARRYCHUNK = "quarry"
local TASK = "task"
local FAILED = "failed"
-- Constant messaging
2021-05-02 00:39:10 +00:00
local LOG = "LOG"
local REQUEST = "REQ"
-- Constant requests
local BLOCKED = "blocked"
local ITEM = "item"
2021-05-03 23:15:22 +00:00
-- avoid breaking pattern
local notPattern = "^allthemodium"
2021-05-02 00:39:10 +00:00
-- INIT SEQUENCE
print("Initiating leader mining turtle.")
running = true
2021-05-02 00:39:10 +00:00
local task = nil
local taskArgs = {}
2021-05-02 00:39:10 +00:00
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, ...)
2021-05-02 00:39:10 +00:00
print("Sending request: " .. request)
reqData = {
token=TOKEN,
recipient=HOST,
sender=UNIT,
type=REQUEST,
request=request,
content=arg
}
modem.transmit(CHANNEL, CHANNEL, textutils.serialise(reqData))
2021-05-02 00:39:10 +00:00
end
local function sendLog(log, ...)
2021-05-02 00:39:10 +00:00
print("Sending message: " .. log)
logData = {
token=TOKEN,
recipient=HOST,
sender=UNIT,
type=LOG,
log=log,
2021-05-03 19:29:58 +00:00
content=arg
}
modem.transmit(CHANNEL, CHANNEL, textutils.serialise(logData))
2021-05-02 00:39:10 +00:00
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
2021-05-03 23:15:22 +00:00
local function attemptBreak(breakf, inspectf, notPattern)
local exists, data = inspectf()
if not exists then
return false
end
if string.match(data.name, pattern) then
return false
end
breakf()
end
2021-05-03 21:11:41 +00:00
local function locatePosition()
local x, y, z = gps.locate()
if x == nil then return false end
position = vector.new(x, y, z)
return true
end
2021-05-02 00:39:10 +00:00
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
2021-05-03 21:11:41 +00:00
if (position ~= nil) then
2021-05-03 23:15:22 +00:00
if ( heading ~= nil ) then
2021-05-03 21:11:41 +00:00
position = position + heading
else
locatePosition()
end
2021-05-02 00:39:10 +00:00
end
return true
end
return false
end
local function attemptMoveBackward()
if attemptMove(turtle.back) then
relativePos = relativePos - relHeading
2021-05-03 21:11:41 +00:00
if (position ~= nil) then
2021-05-03 23:15:22 +00:00
if (heading ~= nil) then
2021-05-03 21:11:41 +00:00
position = position - heading
else
locatePosition()
end
2021-05-02 00:39:10 +00:00
end
return true
end
return false
end
local function attemptMoveLeft()
if attemptMove(turtle.turnLeft) then
local previousHeading = relHeading
relHeading = -relRightAxis
relRightAxis = previousHeading
2021-05-03 23:15:22 +00:00
if heading ~= nil then
2021-05-02 00:39:10 +00:00
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
2021-05-02 00:39:10 +00:00
2021-05-03 23:15:22 +00:00
if heading ~= nil then
2021-05-02 00:39:10 +00:00
local previousHeading = heading
heading = rightAxis
rightAxis = -previousHeading
end
return true
end
return true
end
2021-05-03 23:15:22 +00:00
local function attemptBreakUp(notPattern)
return attemptBreak(turtle.digUp, turtle.inspectUp, notPattern);
end
local function attemptBreakFront(notPattern)
return attemptBreak(turtle.dig, turtle.inspect, notPattern)
end
local function attemptBreakDown(notPattern)
return attemptBreak(turtle.digDown, turtle.inspectDown, notPattern)
end
2021-05-02 00:39:10 +00:00
local function orient(v, forward, right)
print("Attempting to orient such that " .. tostring(v) .. " == " .. tostring(forward) .. ".")
if vectorEqual(v, forward) then
return true
2021-05-02 00:39:10 +00:00
elseif vectorEqual(v, right) then
return attemptMoveRight()
2021-05-02 00:39:10 +00:00
elseif vectorEqual(v, -right) then
return attemptMoveLeft()
2021-05-02 00:39:10 +00:00
else
return attemptMoveRight() and attemptMoveRight()
2021-05-02 00:39:10 +00:00
end
return false
end
2021-05-03 19:49:44 +00:00
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
2021-05-03 19:49:44 +00:00
task = {name=name, func=f, args=arg}
taskArgs = arg
2021-05-02 00:39:10 +00:00
end
2021-05-03 21:11:41 +00:00
-- Actions
local function determinePosition()
if not locatePosition() then
sendLog(FAILED, "Unable to obtain GPS based position.")
return
end
sendLog(POSITION, "Position obtained: " .. tostring(position))
2021-05-02 00:39:10 +00:00
end
local function determineHeading()
sendLog(HEADING, "Calculating heading.")
2021-05-03 21:12:15 +00:00
if position == nil and locatePosition() then
2021-05-03 21:11:41 +00:00
sendLog(FAILED, "Unable to get current position.")
2021-05-02 00:39:10 +00:00
return
end
local oldPos = vector.new(position.x, position.y, position.z)
if not attemptMoveForward() then
sendLog(FAILED, "Could not move to get delta.")
2021-05-02 00:39:10 +00:00
return
end
2021-05-03 20:28:43 +00:00
local fDelta = position - oldPos
2021-05-02 00:39:10 +00:00
2021-05-03 21:11:41 +00:00
if not attemptMoveBackward() then
sendLog(FAILED, "Could not return to original position after first axis.")
return
end
2021-05-02 00:39:10 +00:00
if not attemptMoveRight() then
sendLog(FAILED, "Unable to rotate right.")
2021-05-02 00:39:10 +00:00
return
end
2021-05-03 21:11:41 +00:00
2021-05-02 00:39:10 +00:00
if not attemptMoveForward() then
sendLog(FAILED, "Unable to move forward after rotation.")
2021-05-02 00:39:10 +00:00
return
end
2021-05-03 21:11:41 +00:00
local rDelta = position - oldPos
if not attemptMoveBackward() then
sendLog(FAILED, "Could not return to original position after second axis.")
return
end
2021-05-02 00:39:10 +00:00
if not attemptMoveLeft() then
sendLog(FAILED, "Unable to rotate left.")
2021-05-02 00:39:10 +00:00
return
end
2021-05-03 21:11:41 +00:00
2021-05-03 20:28:43 +00:00
heading = fDelta
2021-05-03 21:11:41 +00:00
rightAxis = rDelta
sendLog(HEADING, "Heading obtained. \nForward: " .. textutils.serialiseJSON(heading) .. "\nRight direction: " .. textutils.serialiseJSON(rightAxis))
2021-05-02 00:39:10 +00:00
end
local function moveBy(delta, forward, right)
2021-05-03 19:33:36 +00:00
sendLog(MOVEBY, "Attempting to move by (" .. delta.x .. "," .. delta.y .. "," .. delta.z .. ") (x,y,z).")
2021-05-02 00:39:10 +00:00
-- 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
2021-05-03 23:18:53 +00:00
if not attemptMoveForward() then
sendLog(FAILED, "Unable to move forward.")
return
end
end
2021-05-02 00:39:10 +00:00
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
2021-05-03 23:18:53 +00:00
if not attemptMoveForward() then
sendLog(FAILED, "Unable to move forward.")
return
end
end
2021-05-02 00:39:10 +00:00
end
if delta.y > 0 then
sendLog(MOVEBY, "Moving on y axis by: " .. delta.y)
for y=1,delta.y do
2021-05-03 23:18:53 +00:00
if not attemptMoveUp() then
sendLog(FAILED, "Unable to move up.")
return
end
2021-05-02 00:39:10 +00:00
end
elseif delta.y < 0 then
sendLog(MOVEBY, "Moving on y axis by: " .. delta.y)
for y=1,math.abs(delta.y) do
2021-05-03 23:18:53 +00:00
if not attemptMoveDown() then
sendLog(FAILED, "Unable to move down.")
return
end
2021-05-02 00:39:10 +00:00
end
end
end
2021-05-03 23:15:22 +00:00
local function moveTo(dest, range)
sendLog(MOVETO, "Attempting to move by (" .. dest.x .. "," .. dest.y .. "," .. dest.z .. ") (x,y,z).")
if position == nil or heading == nil then
sendLog(FAILED, "Position or heading is invalid.")
return
2021-05-03 23:15:22 +00:00
end
local xBlocked, yBlocked, zBlocked = false, false, false
local oldPos = nil
2021-05-05 23:48:41 +00:00
while not vectorEqual(dest, position) do
2021-05-03 23:26:09 +00:00
if oldPos ~= nil and vectorEqual(oldPos, position) then
2021-05-03 23:15:22 +00:00
sendLog(FAILED, "Cannot proceed to due obstacle.")
return
end
oldPos = vector.new(position.x, position.y, position.z);
if position.x ~= dest.x then
2021-05-05 23:48:41 +00:00
if not orient(vector.new(dest.x - position.x, 0, 0):normalize(), heading, rightAxis) then
2021-05-03 23:15:22 +00:00
sendLog(FAILED, "Unable to orient for X axis.")
return
end
attemptMoveForward()
end
if position.y ~= dest.y then
if dest.y - position.y > 0 then
attemptMoveUp()
else
attemptMoveDown()
end
end
if position.z ~= dest.z then
2021-05-05 23:48:41 +00:00
if not orient(vector.new(0, 0, dest.z - position.z):normalize(), heading, rightAxis) then
2021-05-03 23:15:22 +00:00
sendLog(FAILED, "Unable to orient for Z axis.")
return
end
attemptMoveForward()
end
end
end
2021-05-03 18:20:03 +00:00
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
2021-05-03 19:49:44 +00:00
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 = nil
if not pcall(function() data = textutils.unserialise(serialized) end) then
print("Message already table, not deserializing.")
data = serialized
end
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.")
2021-05-03 19:49:44 +00:00
attemptStartTask(MOVETO, moveTo, vector.new(x,y,z), heading, rightAxis)
else
print("Using relative coordinates.")
sendLog(MOVETO, "Using relative coordinates to move.")
2021-05-03 19:49:44 +00:00
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.")
2021-05-03 19:49:44 +00:00
attemptStartTask(MOVEBY, moveBy, vector.new(x,y,z), heading, rightAxis)
else
print("Using relative coordinates.")
sendLog(MOVEBY, "Using relative coordinates to move.")
2021-05-03 19:49:44 +00:00
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, "Relative position: " .. textutils.serializeJSON(status["relative_position"]) ..
"\nPosition: " .. (status["position"]["coordinates"] and textutils.serialiseJSON(status["position"]) or "not positioned.") ..
"\nfuel: " .. tostring(status["fuel"]) ..
"\ncurrent task: " .. status["task"], status)
elseif data["request"] == POSITION then
2021-05-03 21:11:41 +00:00
determinePosition()
elseif data["request"] == HEADING then
determineHeading()
elseif data["request"] == QUARRY then
end
end
end
end
parallel.waitForAll(listen, executeTasks)