-- For testing modem = require("modem") -- For deployment -- modem = require("component").modem serializer = require("serialization") Queue = {first = 0, last = -1} function Queue:new() local o = {} setmetatable(o, self) self.__index = self return o end function Queue:insert(value) local last = self.last + 1 self.last = last self[last] = value end function Queue:isempty() return self.first > self.last end function Queue:remove() local first = self.first if self:isempty() then error("Queue is empty") end local value = self[first] self[first] = nil self.first = first + 1 return value end message_type = { request_noun = 1, call_verb = 2, noun_response = 3, hello = 4, goodbye = 5, hello_response = 6, } CFG_PORT = 1234 bc = {} function bc:init(my_address, local_nouns, local_verbs) local o = {} setmetatable(o, self) self.__index = self o.queue = Queue:new() o.remote_verbs = {} o.remote_nouns = {} -- Modem listener function modem_listener(localAddress, remoteAddress, port, dist, message) dbg = message message = serializer.unserialize(message) if port == CFG_PORT then if message.ty == message_type.request_noun then msg = {ty=message_type.noun_response, noun=message.noun, value=o.local_nouns[message.noun] } o.modem:send(remoteAddress, port, serializer.serialize(msg)) elseif message.ty == message_type.noun_response then -- TODO: Make this a bit better, this is dumb o._nr = message.value elseif message.ty == message_type.call_verb then o.local_verbs[message.verb](o, message.param) elseif message.ty == message_type.hello then for i,verb in ipairs(message.verbs) do o.remote_verbs[verb] = remoteAddress end for i,noun in ipairs(message.nouns) do o.remote_nouns[noun] = remoteAddress end -- Respond with own verbs and nouns local mynouns = {} for noun in pairs(o.local_nouns) do table.insert(mynouns, noun) end local myverbs = {} for verb in pairs(o.local_verbs) do table.insert(myverbs, verb) end o.modem:send(remoteAddress, port, serializer.serialize({ty=message_type.hello_response, verbs=myverbs, nouns=mynouns})) elseif message.ty == message_type.hello_response then for i,verb in ipairs(message.verbs) do o.remote_verbs[verb] = remoteAddress end for i,noun in ipairs(message.nouns) do o.remote_nouns[noun] = remoteAddress end end end end -- Change this for deployment VVV o.modem = modem:init(my_address, modem_listener) -- Init local stuff o.local_verbs = local_verbs o.local_nouns = local_nouns -- Send own nouns and verbs and request all remotes to send theirs local mynouns = {} for noun in pairs(local_nouns) do table.insert(mynouns, noun) end local myverbs = {} for verb in pairs(local_verbs) do table.insert(myverbs, verb) end o.modem:broadcast(CFG_PORT, serializer.serialize({ty=message_type.hello, verbs=myverbs, nouns=mynouns})) return o end function bc:get_noun(n) if self.local_nouns[n] ~= nil then -- This noun is local, makes it easy return self.local_nouns[n] elseif self.remote_nouns[n] ~= nil then -- This noun is remote self.modem:send(self.remote_nouns[n], CFG_PORT, serializer.serialize({ty=message_type.request_noun, noun=n})) while self._nr == nil do -- Nothing, wait for response, TODO: Research performance impact end local value = self._nr self._nr = nil -- Reset return value else error("Noun not found, Node might be offline") end end function bc:set_noun(n, value) if self.local_nouns[n] ~= nil then self.local_nouns[n] = value else error("Can't set remote nouns") end end function bc:call_verb(v, param) if self.local_verbs[v] ~= nil then self.local_verbs[v](self, param) elseif self.remote_verbs[v] ~= nil then self.modem:send(self.remote_verbs[v], CFG_PORT, serializer.serialize({ty=message_type.call_verb, verb=v, param=param})) else error("Verb not found, Node might be offline") end end return bc