237 lines
5.6 KiB
Lua
237 lines
5.6 KiB
Lua
--[[
|
|
tutel client
|
|
|
|
__
|
|
.,-;-;-,. /'_\
|
|
_/_/_/_|_\_\) /
|
|
'-<_><_><_><_>=/\
|
|
`/_/====/_/-'\_\
|
|
"" "" ""
|
|
]]
|
|
|
|
--[[
|
|
network variables
|
|
]]
|
|
local HOST_CHANNEL
|
|
local TURTLE_CHANNEL
|
|
|
|
local MSG_HEADER = 0x747574656C
|
|
|
|
local modem = peripheral.find("modem") or error("No modems found", 0)
|
|
modem.open(0) -- general port used for scanning
|
|
|
|
--[[
|
|
logging
|
|
]]
|
|
local logTypes = {
|
|
["general"] = {
|
|
["BG"] = colours.green,
|
|
["FG"] = colours.white
|
|
},
|
|
|
|
["info"] = {
|
|
["BG"] = colours.blue,
|
|
["FG"] = colours.white
|
|
},
|
|
|
|
["warning"] = {
|
|
["BG"] = colours.orange,
|
|
["FG"] = colours.black,
|
|
["AffectContent"] = true
|
|
},
|
|
|
|
["error"] = {
|
|
["BG"] = colours.red,
|
|
["FG"] = colours.black,
|
|
["AffectContent"] = true
|
|
}
|
|
}
|
|
|
|
local log = {}
|
|
|
|
for typeName, format in pairs(logTypes) do
|
|
log[typeName] = function(fmt, ...)
|
|
local prevColourBg = term.getBackgroundColour()
|
|
local prevColourFg = term.getTextColour()
|
|
|
|
term.setBackgroundColour(format["BG"])
|
|
term.setTextColour(format["FG"])
|
|
io.write(("[%s @ line %d]"):format(typeName, debug.getinfo(2, "l").currentline))
|
|
|
|
if format["AffectContent"] then
|
|
io.write(" ", string.format(fmt, ...), "\n")
|
|
term.setBackgroundColour(prevColourBg)
|
|
term.setTextColour(prevColourFg)
|
|
else
|
|
term.setBackgroundColour(prevColourBg)
|
|
term.setTextColour(prevColourFg)
|
|
io.write(" ", string.format(fmt, ...), "\n")
|
|
end
|
|
end
|
|
end
|
|
|
|
--[[
|
|
helper networking functions
|
|
]]
|
|
function sendToHost(name, msgData)
|
|
local message = {
|
|
["header"] = MSG_HEADER,
|
|
["name"] = name,
|
|
["data"] = msgData or {},
|
|
["id"] = os.getComputerID()
|
|
}
|
|
|
|
modem.transmit(HOST_CHANNEL, TURTLE_CHANNEL or 0, message)
|
|
end
|
|
|
|
--[[
|
|
command handling
|
|
]]
|
|
local commands = {}
|
|
function declareCommandHandler(name, handler, requiredKeys)
|
|
commands[name] = {
|
|
["keys"] = requiredKeys or {},
|
|
["handler"] = handler
|
|
}
|
|
end
|
|
|
|
-- scan
|
|
function handleScan(keys)
|
|
-- to-do: check and maybe inform if turtle is already linked to another host
|
|
HOST_CHANNEL = keys.hostChannel
|
|
|
|
log.info("received scan, host channel assigned to %d, replying...", keys.hostChannel)
|
|
|
|
local x, y, z = gps.locate()
|
|
|
|
sendToHost("SCAN", {
|
|
["positionX"] = x,
|
|
["positionY"] = y,
|
|
["positionZ"] = z,
|
|
["fuel"] = turtle.getFuelLevel()
|
|
})
|
|
|
|
-- HOST_CHANNEL = keys.hostChannel
|
|
-- REPLY_CHANNEL = keys.replyChannel
|
|
-- log.info("Received scan, HOST_CHANNEL: %d - REPLY_CHANNEL: %d", HOST_CHANNEL, REPLY_CHANNEL)
|
|
end
|
|
|
|
declareCommandHandler("SCAN", handleScan, { ["hostChannel"] = "number" })
|
|
|
|
-- register
|
|
function handleRegister(keys)
|
|
log.info("received register for id:", keys.id)
|
|
|
|
if (keys.id ~= os.getComputerID()) then return end -- message was not meant for this computer
|
|
TURTLE_CHANNEL = keys.turtleChannel
|
|
|
|
log.info("received register, host assigned channel: %d", keys.turtleChannel)
|
|
modem.open(keys.turtleChannel)
|
|
modem.close(0)
|
|
end
|
|
|
|
declareCommandHandler("REGISTER", handleRegister, { ["id"] = "number", ["turtleChannel"] = "number" })
|
|
|
|
-- status
|
|
function handleStatus(keys)
|
|
|
|
end
|
|
|
|
declareCommandHandler("STATUS", handleStatus)
|
|
|
|
-- goto
|
|
function handleGoTo(keys)
|
|
|
|
end
|
|
|
|
declareCommandHandler("GOTO", handleGoTo, { ["destX"] = "number", ["destY"] = "number", ["destZ"] = "number" })
|
|
|
|
-- mine area
|
|
function handleMineArea(keys)
|
|
|
|
end
|
|
|
|
declareCommandHandler("MINE-AREA", handleGoTo,
|
|
{ ["startX"] = "number", ["startY"] = "number", ["destX"] = "number", ["destZ"] = "number" })
|
|
|
|
-- abort
|
|
function handleAbort()
|
|
|
|
end
|
|
|
|
declareCommandHandler("ABORT", handleAbort)
|
|
|
|
--[[
|
|
event handling
|
|
]]
|
|
local eventListeners = {}
|
|
local function registerEventListener(name, listener)
|
|
if not eventListeners[name] then eventListeners[name] = {} end
|
|
table.insert(eventListeners[name], listener)
|
|
end
|
|
|
|
local function dispatchEvents(event, ...)
|
|
local eventTbl = eventListeners[event]
|
|
if not eventTbl then return end
|
|
|
|
for i = 1, #eventTbl, 1 do
|
|
eventTbl[i](...)
|
|
end
|
|
end
|
|
local function handleMessages(side, channel, replyChannel, message, dist)
|
|
if TURTLE_CHANNEL and channel ~= TURTLE_CHANNEL then return end
|
|
|
|
-- msg validation
|
|
if type(message) ~= "table" then return end
|
|
if not message.header or message.header ~= MSG_HEADER then return end
|
|
if not message.data then message.data = {} end
|
|
|
|
-- cmd validation
|
|
if not message.name then
|
|
log.warning("received nameless command?")
|
|
return
|
|
end
|
|
|
|
if not commands[message.name] then
|
|
log.error("unhandled command (%s)", message.name)
|
|
return
|
|
end
|
|
|
|
local cmd = commands[message.name]
|
|
for i, v in pairs(cmd.keys) do
|
|
if type(message.data[i]) ~= v and v ~= "optional" then
|
|
log.error("command %s requires key %s of type %s (was %s)", message.name, i, v, type(message[i]))
|
|
return
|
|
end
|
|
end
|
|
|
|
-- cmd execution
|
|
local success, err = pcall(cmd.handler, message.data, message.id)
|
|
if not success then
|
|
log.error("error occurred while executing command %s: %s", message.name, err)
|
|
return
|
|
end
|
|
|
|
log.info("processed command (%s)", message.name)
|
|
end
|
|
registerEventListener("modem_message", handleMessages)
|
|
|
|
--[[
|
|
event polling
|
|
]]
|
|
function pollEvents()
|
|
local eventData = { os.pullEvent() }
|
|
|
|
local eventName = eventData[1]
|
|
table.remove(eventData, 1)
|
|
|
|
dispatchEvents(eventName, table.unpack(eventData))
|
|
end
|
|
|
|
--[[
|
|
main loop
|
|
]]
|
|
log.info("init")
|
|
while true do
|
|
pollEvents()
|
|
end |