Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Minecraft Intranet
- Device
- --]]
- mcnet = mcnet or {}
- local device = mcnet.device or {}
- mcnet.device = device
- local Device = common.newClass(common.Observable, {
- deviceType = nil,
- address = nil,
- isRunning = false,
- ___registeredMessage = false
- })
- device.Device = Device
- -- Constructor
- function Device:init()
- common.Observable.init(self)
- self.neighboursList = {}
- self:registerRednetMessage()
- end
- -- Check if the given address matches this device's address
- function Device:checkAddress(address)
- return address.domainPart == self.address.domainPart and address.localPart == self.address.localPart
- end
- -- Rednet message handler
- function Device:handleRednetMessage(senderId, msg)
- if senderId == nil then
- return false
- end
- local msg = mcnet.message.unserialize(msg)
- if msg == nil then return false end
- self:trigger("mcnet_message", senderId, msg)
- return true
- end
- -- Register rednet message handler
- function Device:registerRednetMessage()
- if self.___registeredMessage then return end
- self:on("rednet_message", self.handleRednetMessage, self)
- self.___registeredMessage = true
- end
- -- Add message handler for the given message type
- function Device:addMessageHandler(messageType, handler)
- if (type(messageType) == "table") then
- -- Table of types and handlers
- for k,v in pairs(messageType) do
- self:addMessageHandler(k, v)
- end
- else
- assert(type(messageType) == "string", "invalid message type")
- assert(type(handler) == "function", "invalid message handler")
- -- Single type and handler
- self:on("mcnet_message", function(self, senderId, msg)
- if (common.startsWith(msg.type, messageType)) then
- return handler(self, senderId, msg)
- end
- end, self)
- end
- end
- function Device:handleDeviceOn(senderId, msg)
- -- Add and notify if device started
- self.neighboursList[senderId] = true
- mcnet.message.send(senderId, mcnet.message.new{
- type = "deviceDetect",
- from = self.address,
- device = self.deviceType
- })
- return true
- end
- function Device:handleDeviceDetect(senderId, msg)
- -- Add if device detected
- self.neighboursList[senderId] = true
- return true
- end
- function Device:handleDeviceOff(senderId, msg)
- -- Remove if device stopped
- self.neighboursList[senderId] = nil
- return true
- end
- -- Start device
- function Device:start(timeout)
- assert (not self.isRunning, "Device already started")
- timeout = math.max(timeout, 0)
- -- Set as running
- self.isRunning = true
- -- Open modem port
- for i,side in ipairs(rs.getSides()) do
- if (peripheral.isPresent(side) and peripheral.getType(side) == "modem") then
- rednet.open(side)
- break
- end
- end
- -- Add device message handlers
- self:addMessageHandler{
- deviceOn = self.handleDeviceOn,
- deviceDetect = self.handleDeviceDetect,
- deviceOff = self.handleDeviceOff
- }
- -- Notify others of starting device
- mcnet.message.broadcast(mcnet.message.new{
- type = "deviceOn",
- from = self.address,
- device = self.deviceType
- })
- local detectTimer = os.startTimer(timeout)
- while true do
- local event, p1, p2 = os.pullEvent()
- local refresh = false
- if (event == "rednet_message") then
- -- Handled by event handlers
- refresh = self:trigger(event, p1, p2)
- elseif (event == "timer" and p1 == detectTimer) then
- -- Detection timed out
- break
- end
- if refresh then
- -- Refresh timer
- detectTimer = os.startTimer(timeout)
- end
- end
- end
- -- Stop device
- function Device:stop()
- assert (self.isRunning, "Device already stopped")
- -- Set as stopped
- self.isRunning = false
- -- Notify others of stopping device
- mcnet.message.broadcast(mcnet.message.new{
- type = "deviceOff",
- from = self.address,
- device = self.deviceType
- })
- self.neighboursList = {}
- -- Close modem port
- for i,side in ipairs(rs.getSides()) do
- if (peripheral.isPresent(side) and peripheral.getType(side) == "modem") then
- rednet.close(side)
- break
- end
- end
- end
- -- Send message
- function Device:send(receiverId, msg)
- if (receiverId == nil) then
- return false
- end
- -- Send from device if no sender
- if (msg.from == nil) then
- msg.from = self.address
- end
- -- Send message
- return mcnet.message.send(receiverId, msg, true)
- end
- -- Get the neighbours of this device
- function Device:neighbours()
- local t = {}
- for k,v in pairs(self.neighboursList) do
- if v then
- table.insert(t, k)
- end
- end
- return t
- end
- -- Get the neighbours of this device, except the given computer(s)
- function Device:neighboursExcept(...)
- local except = { ... }
- local t = {}
- for k,v in pairs(self.neighboursList) do
- if v then
- local allow = true
- for i,e in ipairs(except) do
- if k == e then
- allow = false
- break
- end
- end
- if allow then
- table.insert(t, k)
- end
- end
- end
- return t
- end
Advertisement
Add Comment
Please, Sign In to add comment