random-stuff/computercraft/basenet.lua

97 lines
2.3 KiB
Lua

local channel = settings.get "basenet.channel" or 23032
local modem = peripheral.find "modem"
if not modem then error "modem required" end
modem.open(channel)
local name = settings.get "basenet.name" or _G.basenet_name or error "name required"
local basenet = {
listening_to = {},
tasks = {}
}
function basenet.listen(fn, from)
if type(from) ~= "string" then error "from must be a string" end
basenet.listening_to[from] = true
basenet.run_task(function()
while true do
local _, ufrom, data = os.pullEvent "update"
if ufrom == from then
fn(data)
end
end
end)
end
function basenet.update(data)
modem.transmit(channel, channel, { type = "update", from = name, data = data })
end
local task_ID = 0
function basenet.run_task(fn, ...)
local args = {...}
task_ID = task_ID + 1
basenet.tasks[task_ID] = { coroutine = coroutine.create(fn), init_args = args, ID = task_ID }
os.queueEvent "dummy"
return task_ID
end
function basenet.interval(fn, time)
if not time then error "time required" end
basenet.run_task(function()
while true do
fn()
sleep(time)
end
end)
end
local function process_message(msg)
if msg.type == "update" and type(msg.from) == "string" then
if basenet.listening_to[msg.from] then
os.queueEvent("update", msg.from, msg.data)
end
end
end
basenet.run_task(function()
while true do
local _, _, c, rc, msg, distance = os.pullEvent "modem_message"
if c == channel and type(msg) == "table" then
process_message(msg)
end
end
end)
local function tick_task(task, evt)
if task.init_args then
local init = task.init_args
task.init_args = nil
local ok = tick_task(task, init)
if not ok then return end
end
if coroutine.status(task.coroutine) == "dead" then
basenet.tasks[task.ID] = nil
else
if task.filter == nil or task.filter == evt[1] then
local ok, result = coroutine.resume(task.coroutine, unpack(evt))
if ok then
task.filter = result
else
printError(("TASK %d ERROR: %s"):format(task.ID, result))
basenet.tasks[task.ID] = nil
end
return ok
end
end
end
function basenet.run()
while true do
local evt = {os.pullEvent()}
for ID, task in pairs(basenet.tasks) do
tick_task(task, evt)
end
end
end
return basenet