MattiasBuelens

MCNet device

Jun 8th, 2012
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.48 KB | None | 0 0
  1. --[[
  2.  
  3.     Minecraft Intranet
  4.     Device
  5.  
  6. --]]
  7.  
  8. mcnet = mcnet or {}
  9. local device = mcnet.device or {}
  10. mcnet.device = device
  11.  
  12. local Device = common.newClass(common.Observable, {
  13.     deviceType = nil,
  14.     address = nil,
  15.     isRunning = false,
  16.     ___registeredMessage = false
  17. })
  18. device.Device = Device
  19.  
  20. -- Constructor
  21. function Device:init()
  22.     common.Observable.init(self)
  23.     self.neighboursList = {}
  24.     self:registerRednetMessage()
  25. end
  26.  
  27. -- Check if the given address matches this device's address
  28. function Device:checkAddress(address)
  29.     return address.domainPart == self.address.domainPart and address.localPart == self.address.localPart
  30. end
  31.  
  32. -- Rednet message handler
  33. function Device:handleRednetMessage(senderId, msg)
  34.     if senderId == nil then
  35.         return false
  36.     end
  37.  
  38.     local msg = mcnet.message.unserialize(msg)
  39.     if msg == nil then return false end
  40.  
  41.     self:trigger("mcnet_message", senderId, msg)
  42.     return true
  43. end
  44.  
  45. -- Register rednet message handler
  46. function Device:registerRednetMessage()
  47.     if self.___registeredMessage then return end
  48.  
  49.     self:on("rednet_message", self.handleRednetMessage, self)
  50.     self.___registeredMessage = true
  51. end
  52.  
  53. -- Add message handler for the given message type
  54. function Device:addMessageHandler(messageType, handler)
  55.     if (type(messageType) == "table") then
  56.         -- Table of types and handlers
  57.         for k,v in pairs(messageType) do
  58.             self:addMessageHandler(k, v)
  59.         end
  60.     else
  61.         assert(type(messageType) == "string", "invalid message type")
  62.         assert(type(handler) == "function", "invalid message handler")
  63.  
  64.         -- Single type and handler
  65.         self:on("mcnet_message", function(self, senderId, msg)
  66.             if (common.startsWith(msg.type, messageType)) then
  67.                 return handler(self, senderId, msg)
  68.             end
  69.         end, self)
  70.     end
  71. end
  72.  
  73. function Device:handleDeviceOn(senderId, msg)
  74.     -- Add and notify if device started
  75.     self.neighboursList[senderId] = true
  76.     mcnet.message.send(senderId, mcnet.message.new{
  77.         type = "deviceDetect",
  78.         from = self.address,
  79.         device = self.deviceType
  80.     })
  81.     return true
  82. end
  83.  
  84. function Device:handleDeviceDetect(senderId, msg)
  85.     -- Add if device detected
  86.     self.neighboursList[senderId] = true
  87.     return true
  88. end
  89.  
  90. function Device:handleDeviceOff(senderId, msg)
  91.     -- Remove if device stopped
  92.     self.neighboursList[senderId] = nil
  93.     return true
  94. end
  95.  
  96. -- Start device
  97. function Device:start(timeout)
  98.     assert (not self.isRunning, "Device already started")
  99.  
  100.     timeout = math.max(timeout, 0)
  101.  
  102.     -- Set as running
  103.     self.isRunning = true
  104.  
  105.     -- Open modem port
  106.     for i,side in ipairs(rs.getSides()) do
  107.         if (peripheral.isPresent(side) and peripheral.getType(side) == "modem") then
  108.             rednet.open(side)
  109.             break
  110.         end
  111.     end
  112.  
  113.     -- Add device message handlers
  114.     self:addMessageHandler{
  115.         deviceOn = self.handleDeviceOn,
  116.         deviceDetect = self.handleDeviceDetect,
  117.         deviceOff = self.handleDeviceOff
  118.     }
  119.  
  120.     -- Notify others of starting device
  121.     mcnet.message.broadcast(mcnet.message.new{
  122.         type = "deviceOn",
  123.         from = self.address,
  124.         device = self.deviceType
  125.     })
  126.  
  127.     local detectTimer = os.startTimer(timeout)
  128.     while true do
  129.         local event, p1, p2 = os.pullEvent()
  130.         local refresh = false
  131.  
  132.         if (event == "rednet_message") then
  133.             -- Handled by event handlers
  134.             refresh = self:trigger(event, p1, p2)
  135.         elseif (event == "timer" and p1 == detectTimer) then
  136.             -- Detection timed out
  137.             break
  138.         end
  139.  
  140.         if refresh then
  141.             -- Refresh timer
  142.             detectTimer = os.startTimer(timeout)
  143.         end
  144.     end
  145. end
  146.  
  147. -- Stop device
  148. function Device:stop()
  149.     assert (self.isRunning, "Device already stopped")
  150.  
  151.     -- Set as stopped
  152.     self.isRunning = false
  153.  
  154.     -- Notify others of stopping device
  155.     mcnet.message.broadcast(mcnet.message.new{
  156.         type = "deviceOff",
  157.         from = self.address,
  158.         device = self.deviceType
  159.     })
  160.     self.neighboursList = {}
  161.  
  162.     -- Close modem port
  163.     for i,side in ipairs(rs.getSides()) do
  164.         if (peripheral.isPresent(side) and peripheral.getType(side) == "modem") then
  165.             rednet.close(side)
  166.             break
  167.         end
  168.     end
  169. end
  170.  
  171. -- Send message
  172. function Device:send(receiverId, msg)
  173.     if (receiverId == nil) then
  174.         return false
  175.     end
  176.  
  177.     -- Send from device if no sender
  178.     if (msg.from == nil) then
  179.         msg.from = self.address
  180.     end
  181.  
  182.     -- Send message
  183.     return mcnet.message.send(receiverId, msg, true)
  184. end
  185.  
  186. -- Get the neighbours of this device
  187. function Device:neighbours()
  188.     local t = {}
  189.     for k,v in pairs(self.neighboursList) do
  190.         if v then
  191.             table.insert(t, k)
  192.         end
  193.     end
  194.     return t
  195. end
  196.  
  197. -- Get the neighbours of this device, except the given computer(s)
  198. function Device:neighboursExcept(...)
  199.     local except = { ... }
  200.     local t = {}
  201.     for k,v in pairs(self.neighboursList) do
  202.         if v then
  203.             local allow = true
  204.             for i,e in ipairs(except) do
  205.                 if k == e then
  206.                     allow = false
  207.                     break
  208.                 end
  209.             end
  210.             if allow then
  211.                 table.insert(t, k)
  212.             end
  213.         end
  214.     end
  215.     return t
  216. end
Advertisement
Add Comment
Please, Sign In to add comment