Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Modem Emulation Protocol over CRFv3.1, using multicast
- local fake_modems = {}
- local open_channels = {}
- local peripheral_old = {}
- local listen_all = false -- Should we emit *all* fake modem messages, no matter if we even have a fake modem open to the sending channel?
- for i,v in pairs(peripheral) do
- peripheral_old[i] = v
- end
- if not LANClient then
- error("The LAN Client API has not loaded yet!")
- end
- LANClient.join_group(2)
- peripheral.isPresent = function(side)
- if fake_modems[side] ~= nil then
- return true
- end
- return peripheral_old.isPresent(side)
- end
- peripheral.getType = function(side)
- if fake_modems[side] ~= nil then
- return "modem"
- end
- return peripheral_old.getType(side)
- end
- peripheral.getMethods = function(side)
- if fake_modems[side] ~= nil then
- return {"isOpen", "open", "close", "closeAll", "transmit", "isWireless"}
- end
- return peripheral_old.getMethods(side)
- end
- peripheral.call = function(side, method, ...)
- local args = {...}
- if fake_modems[side] ~= nil then
- if fake_modems[side][method] then
- return fake_modems[side][method](unpack(args))
- end
- end
- return peripheral_old.call(side, method, unpack(args))
- end
- peripheral.getNames = function()
- local names = peripheral_old.getNames()
- for i,v in pairs(fake_modems) do
- table.insert(names, i)
- end
- return names
- end
- peripheral.wrap = function(side)
- if fake_modems[side] ~= nil then
- return fake_modems[side] -- we're trusting the caller to not screw with the modem object
- end
- return peripheral_old.wrap(side)
- end
- function backgroundListener()
- while true do
- local sender, msg = LANClient.receive()
- local data = textutils.unserialize(msg)
- if type(data) == "table" then
- --print("Got a message from "..sender)
- if data[1] == "ModemEmulator" then
- local sCh = tonumber(data[2])
- local rCh = tonumber(data[3])
- local modemData = data[4]
- --[[
- print("Got a fake modem message from "..sender)
- print("sch: "..sCh.." type: "..type(sCh))
- print("rch: "..rCh.." type: "..type(rCh))
- print("data: "..modemData)
- local foundSide = false
- ]]
- if open_channels[sCh] then
- local side = next(fake_modems) -- Get the first modem we find
- os.queueEvent("modem_message", side, sCh, rCh, modemData, 0)
- --print("side: "..side)
- elseif listen_all then -- fuck it, emit as an obviously fake event
- os.queueEvent("modem_message", "listen_all", sCh, rCh, modemData, 0)
- --print("side: listen_all")
- end
- end
- end
- end
- end
- local function create_fake_modem()
- local modem = {
- channels = {},
- isWireless = function() return true end,
- isFake = function() return true end,
- }
- modem.transmit = function(channel, replyChannel, data)
- LANClient.send(-2, textutils.serialize({"ModemEmulator", channel, replyChannel, data}))
- end
- modem.isOpen = function(channel)
- if open_channels[channel] then
- --print("open_channels["..channel.."] :"..open_channels[channel])
- return true
- end
- return false
- end
- modem.open = function(channel)
- --print("ch: "..channel.." type: "..type(channel))
- if open_channels[channel] then
- open_channels[channel] = open_channels[channel]+1
- else
- open_channels[channel] = 1
- end
- --print("open_channels["..channel.."] :"..open_channels[channel])
- modem.channels[channel] = true
- end
- modem.close = function(channel)
- if open_channels[channel] then
- open_channels[channel] = open_channels[channel]-1
- if open_channels[channel] <= 0 then
- open_channels[channel] = nil
- end
- modem.channels[channel] = nil
- end
- end
- modem.closeAll = function()
- local copy = {}
- for i,v in pairs(modem.channels) do
- copy[i] = v
- end
- for i,v in pairs(copy) do
- modem.close(i)
- end
- end
- return modem
- end
- function register_modem(side)
- if peripheral.isPresent(side) then
- return false
- end
- fake_modems[side] = create_fake_modem()
- return true
- end
- function unregister_modem(side)
- if fake_modems[side] then
- fake_modems[side] = nil
- else
- return false
- end
- return true
- end
- function get_all_listen()
- return listen_all
- end
- function toggle_all_listen()
- listen_all = not listen_all
- return listen_all
- end
- function get_open_channels()
- return open_channels
- end
- if shell then
- local file = fs.open(shell.getRunningProgram(), "r")
- if file then
- local l = file.readLine()
- file.close()
- if string.match(l, "Modem Emulation Protocol") then
- if not modem_emulator then -- The API's useless if the background function isn't running
- error("The modem_emulator API has not loaded yet!")
- end
- local args = {...}
- if #args == 2 then
- if args[1] == "register" then
- if register_modem(args[2]) then
- print("Virtual modem successfully created.")
- else
- print("A peripheral already exists there.")
- end
- elseif args[1] == "unregister" then
- if unregister_modem(args[2]) then
- print("Virtual modem successfully deleted.")
- else
- print("No peripheral exists there.")
- end
- end
- elseif (#args == 1) and (args[1] == "listen_all") then
- if toggle_all_listen() then
- print("All-Listen enabled.")
- else
- print("All-Listen disabled.")
- end
- else
- print("modem_emulator -- Modem emulator API and interface")
- print(string.rep("-", term.getSize()))
- print("Usage: modem_emulator [action] [side]")
- print("Actions:")
- print("register (\"modem_emulator register [side]\"): Create a new virtual modem.")
- print("unregister (\"modem_emulator unregister [side]\"): Delete a virtual modem.")
- print("listen_all (\"modem_emulator listen_all\"): Toggle listen state; when on, then we emit all events regardless of whether we have a modem opened to the sending channel.")
- end
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement