100 lines
3.4 KiB
Lua
100 lines
3.4 KiB
Lua
|
-- SPDX-FileCopyrightText: 2017 Daniel Ratcliffe
|
||
|
--
|
||
|
-- SPDX-License-Identifier: LicenseRef-CCPL
|
||
|
|
||
|
-- Find modems
|
||
|
local tModems = {}
|
||
|
for _, sModem in ipairs(peripheral.getNames()) do
|
||
|
if peripheral.getType(sModem) == "modem" then
|
||
|
table.insert(tModems, sModem)
|
||
|
end
|
||
|
end
|
||
|
if #tModems == 0 then
|
||
|
print("No modems found.")
|
||
|
return
|
||
|
elseif #tModems == 1 then
|
||
|
print("1 modem found.")
|
||
|
else
|
||
|
print(#tModems .. " modems found.")
|
||
|
end
|
||
|
|
||
|
local function open(nChannel)
|
||
|
for n = 1, #tModems do
|
||
|
local sModem = tModems[n]
|
||
|
peripheral.call(sModem, "open", nChannel)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function close(nChannel)
|
||
|
for n = 1, #tModems do
|
||
|
local sModem = tModems[n]
|
||
|
peripheral.call(sModem, "close", nChannel)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Open channels
|
||
|
print("0 messages repeated.")
|
||
|
open(rednet.CHANNEL_REPEAT)
|
||
|
|
||
|
-- Main loop (terminate to break)
|
||
|
local ok, error = pcall(function()
|
||
|
local tReceivedMessages = {}
|
||
|
local tReceivedMessageTimeouts = {}
|
||
|
local nTransmittedMessages = 0
|
||
|
|
||
|
while true do
|
||
|
local sEvent, sModem, nChannel, nReplyChannel, tMessage = os.pullEvent()
|
||
|
if sEvent == "modem_message" then
|
||
|
-- Got a modem message, rebroadcast it if it's a rednet thing
|
||
|
if nChannel == rednet.CHANNEL_REPEAT then
|
||
|
if type(tMessage) == "table" and tMessage.nMessageID and tMessage.nRecipient and type(tMessage.nRecipient) == "number" then
|
||
|
if not tReceivedMessages[tMessage.nMessageID] then
|
||
|
-- Ensure we only repeat a message once
|
||
|
tReceivedMessages[tMessage.nMessageID] = true
|
||
|
tReceivedMessageTimeouts[os.startTimer(30)] = tMessage.nMessageID
|
||
|
|
||
|
local recipient_channel = tMessage.nRecipient
|
||
|
if tMessage.nRecipient ~= rednet.CHANNEL_BROADCAST then
|
||
|
recipient_channel = recipient_channel % rednet.MAX_ID_CHANNELS
|
||
|
end
|
||
|
|
||
|
-- Send on all other open modems, to the target and to other repeaters
|
||
|
for n = 1, #tModems do
|
||
|
local sOtherModem = tModems[n]
|
||
|
peripheral.call(sOtherModem, "transmit", rednet.CHANNEL_REPEAT, nReplyChannel, tMessage)
|
||
|
peripheral.call(sOtherModem, "transmit", recipient_channel, nReplyChannel, tMessage)
|
||
|
end
|
||
|
|
||
|
-- Log the event
|
||
|
nTransmittedMessages = nTransmittedMessages + 1
|
||
|
local _, y = term.getCursorPos()
|
||
|
term.setCursorPos(1, y - 1)
|
||
|
term.clearLine()
|
||
|
if nTransmittedMessages == 1 then
|
||
|
print(nTransmittedMessages .. " message repeated.")
|
||
|
else
|
||
|
print(nTransmittedMessages .. " messages repeated.")
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
elseif sEvent == "timer" then
|
||
|
-- Got a timer event, use it to clear the message history
|
||
|
local nTimer = sModem
|
||
|
local nMessageID = tReceivedMessageTimeouts[nTimer]
|
||
|
if nMessageID then
|
||
|
tReceivedMessageTimeouts[nTimer] = nil
|
||
|
tReceivedMessages[nMessageID] = nil
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|
||
|
end)
|
||
|
if not ok then
|
||
|
printError(error)
|
||
|
end
|
||
|
|
||
|
-- Close channels
|
||
|
close(rednet.CHANNEL_REPEAT)
|