upload tutel
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
--[[
|
||||
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
|
||||
modem.close(0)
|
||||
|
||||
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)
|
||||
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)
|
||||
|
||||
--[[
|
||||
main
|
||||
]]
|
||||
function pollAndProcessMessages()
|
||||
local eventType, side, channel, replyChannel, message, dist = os.pullEvent("modem_message")
|
||||
|
||||
-- ignore messages not from host, HOST_CHANNEL and REPLY_CHANNEL will get assigned after receiving SCAN on channel 0
|
||||
if TURTLE_CHANNEL and channel ~= TURTLE_CHANNEL then return end
|
||||
|
||||
-- message 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
|
||||
|
||||
-- command validation
|
||||
if not message.name then
|
||||
log.warning("received nameless message")
|
||||
return
|
||||
end
|
||||
|
||||
if not commands[message.name] then
|
||||
log.error("unhandled message (%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.handler(message.data)
|
||||
|
||||
-- message handling
|
||||
log.info("processed command (%s)", message.name)
|
||||
end
|
||||
|
||||
log.general("tutel client init")
|
||||
|
||||
while true do
|
||||
pollAndProcessMessages()
|
||||
end
|
||||
@@ -0,0 +1,184 @@
|
||||
--[[
|
||||
tutel host
|
||||
|
||||
__
|
||||
.,-;-;-,. /'_\
|
||||
_/_/_/_|_\_\) /
|
||||
'-<_><_><_><_>=/\
|
||||
`/_/====/_/-'\_\
|
||||
"" "" ""
|
||||
]]
|
||||
|
||||
--[[
|
||||
network variables
|
||||
]]
|
||||
local HOST_CHANNEL = 1337
|
||||
local TURTLE_CHANNEL_BASE = 1338
|
||||
|
||||
local MSG_HEADER = 0x747574656C
|
||||
|
||||
local modem = peripheral.find("modem") or error("No modems found", 0)
|
||||
modem.open(HOST_CHANNEL)
|
||||
|
||||
--[[
|
||||
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
|
||||
|
||||
--[[
|
||||
turtle tracking
|
||||
]]
|
||||
local turtles = {}
|
||||
|
||||
function registerTurtle(pos, fuel, id)
|
||||
local channel = TURTLE_CHANNEL_BASE + #turtles
|
||||
|
||||
local turt = {
|
||||
["channel"] = channel,
|
||||
["index"] = #turtles,
|
||||
["position"] = pos,
|
||||
["fuel"] = fuel,
|
||||
["status"] = "IDLE",
|
||||
["id"] = id
|
||||
}
|
||||
|
||||
table.insert(turtles, turt)
|
||||
|
||||
return turt
|
||||
end
|
||||
|
||||
--[[
|
||||
helper networking functions
|
||||
]]
|
||||
function sendToAll(name, msgData)
|
||||
local message = {
|
||||
["header"] = MSG_HEADER,
|
||||
["name"] = name,
|
||||
["data"] = msgData or {}
|
||||
}
|
||||
|
||||
modem.transmit(0, 0, message)
|
||||
end
|
||||
|
||||
--[[
|
||||
command handling
|
||||
]]
|
||||
local commands = {}
|
||||
function declareCommandHandler(name, handler, requiredKeys)
|
||||
commands[name] = {
|
||||
["keys"] = requiredKeys or {},
|
||||
["handler"] = handler
|
||||
}
|
||||
end
|
||||
|
||||
-- scan
|
||||
function handleScan(keys, id)
|
||||
local turt = registerTurtle({ keys.positionX, keys.positionY, keys.positionZ }, keys.fuel, id)
|
||||
|
||||
log.info("Received turtle info (pos: %d, %d, %d - fuel: %d - channel: %d - id: %d)", turt.position[1],
|
||||
turt.position[2], turt.position[3], turt.fuel, turt.channel, id)
|
||||
|
||||
sendToAll("REGISTER", { ["id"] = id, ["turtleChannel"] = turt.channel })
|
||||
end
|
||||
|
||||
declareCommandHandler("SCAN", handleScan,
|
||||
{
|
||||
["positionX"] = "number",
|
||||
["positionY"] = "number",
|
||||
["positionZ"] = "number",
|
||||
["fuel"] = "number"
|
||||
})
|
||||
|
||||
--[[
|
||||
main
|
||||
]]
|
||||
function pollAndProcessMessages()
|
||||
local eventType, side, channel, replyChannel, message, dist = os.pullEvent("modem_message")
|
||||
|
||||
-- to-do: check if reply channel is valid turtle channel
|
||||
if channel ~= HOST_CHANNEL then return end
|
||||
|
||||
-- message 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
|
||||
|
||||
-- command validation
|
||||
if not message.name then
|
||||
log.warning("received nameless message")
|
||||
return
|
||||
end
|
||||
|
||||
if not commands[message.name] then
|
||||
log.error("unhandled message (%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.handler(message.data, message.id)
|
||||
|
||||
-- message handling
|
||||
log.info("received command (%s)", message.name)
|
||||
end
|
||||
|
||||
log.general("tutel host init")
|
||||
|
||||
-- transmit scan
|
||||
sendToAll("SCAN", { ["hostChannel"] = HOST_CHANNEL })
|
||||
log.info("broadcasted scan message")
|
||||
|
||||
|
||||
while true do
|
||||
pollAndProcessMessages()
|
||||
end
|
||||
Reference in New Issue
Block a user