mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-29 12:57:46 +00:00 
			
		
		
		
	Fix computer IDs greater than 65535 crashing Rednet (#900)
This commit is contained in:
		| @@ -61,6 +61,8 @@ | ||||
|       (table space) | ||||
|       (index no-space)) | ||||
|  | ||||
|     (allow-clarifying-parens true) | ||||
|  | ||||
|     ;; colours imports from colors, and we don't handle that right now. | ||||
|     ;; keys is entirely dynamic, so we skip it. | ||||
|     (dynamic-modules colours keys _G) | ||||
|   | ||||
| @@ -25,10 +25,18 @@ CHANNEL_BROADCAST = 65535 | ||||
| --- The channel used by the Rednet API to repeat messages. | ||||
| CHANNEL_REPEAT = 65533 | ||||
|  | ||||
| --- The number of channels rednet reserves for computer IDs. Computers with IDs | ||||
| -- greater or equal to this limit wrap around to 0. | ||||
| MAX_ID_CHANNELS = 65500 | ||||
|  | ||||
| local tReceivedMessages = {} | ||||
| local tReceivedMessageTimeouts = {} | ||||
| local tHostnames = {} | ||||
|  | ||||
| local function id_as_channel(id) | ||||
|     return (id or os.getComputerID()) % MAX_ID_CHANNELS | ||||
| end | ||||
|  | ||||
| --[[- Opens a modem with the given @{peripheral} name, allowing it to send and | ||||
| receive messages over rednet. | ||||
|  | ||||
| @@ -47,7 +55,7 @@ function open(modem) | ||||
|     if peripheral.getType(modem) ~= "modem" then | ||||
|         error("No such modem: " .. modem, 2) | ||||
|     end | ||||
|     peripheral.call(modem, "open", os.getComputerID()) | ||||
|     peripheral.call(modem, "open", id_as_channel()) | ||||
|     peripheral.call(modem, "open", CHANNEL_BROADCAST) | ||||
| end | ||||
|  | ||||
| @@ -64,7 +72,7 @@ function close(modem) | ||||
|         if peripheral.getType(modem) ~= "modem" then | ||||
|             error("No such modem: " .. modem, 2) | ||||
|         end | ||||
|         peripheral.call(modem, "close", os.getComputerID()) | ||||
|         peripheral.call(modem, "close", id_as_channel()) | ||||
|         peripheral.call(modem, "close", CHANNEL_BROADCAST) | ||||
|     else | ||||
|         -- Close all modems | ||||
| @@ -87,7 +95,7 @@ function isOpen(modem) | ||||
|     if modem then | ||||
|         -- Check if a specific modem is open | ||||
|         if peripheral.getType(modem) == "modem" then | ||||
|             return peripheral.call(modem, "isOpen", os.getComputerID()) and peripheral.call(modem, "isOpen", CHANNEL_BROADCAST) | ||||
|             return peripheral.call(modem, "isOpen", id_as_channel()) and peripheral.call(modem, "isOpen", CHANNEL_BROADCAST) | ||||
|         end | ||||
|     else | ||||
|         -- Check if any modem is open | ||||
| @@ -134,10 +142,11 @@ function send(nRecipient, message, sProtocol) | ||||
|     tReceivedMessageTimeouts[os.startTimer(30)] = nMessageID | ||||
|  | ||||
|     -- Create the message | ||||
|     local nReplyChannel = os.getComputerID() | ||||
|     local nReplyChannel = id_as_channel() | ||||
|     local tMessage = { | ||||
|         nMessageID = nMessageID, | ||||
|         nRecipient = nRecipient, | ||||
|         nSender = os.getComputerID(), | ||||
|         message = message, | ||||
|         sProtocol = sProtocol, | ||||
|     } | ||||
| @@ -145,10 +154,14 @@ function send(nRecipient, message, sProtocol) | ||||
|     local sent = false | ||||
|     if nRecipient == os.getComputerID() then | ||||
|         -- Loopback to ourselves | ||||
|         os.queueEvent("rednet_message", nReplyChannel, message, sProtocol) | ||||
|         os.queueEvent("rednet_message", os.getComputerID(), message, sProtocol) | ||||
|         sent = true | ||||
|     else | ||||
|         -- Send on all open modems, to the target and to repeaters | ||||
|         if nRecipient ~= CHANNEL_BROADCAST then | ||||
|             nRecipient = id_as_channel(nRecipient) | ||||
|         end | ||||
|  | ||||
|         for _, sModem in ipairs(peripheral.getNames()) do | ||||
|             if isOpen(sModem) then | ||||
|                 peripheral.call(sModem, "transmit", nRecipient, nReplyChannel, tMessage) | ||||
| @@ -390,13 +403,14 @@ function run() | ||||
|         if sEvent == "modem_message" then | ||||
|             -- Got a modem message, process it and add it to the rednet event queue | ||||
|             local sModem, nChannel, nReplyChannel, tMessage = p1, p2, p3, p4 | ||||
|             if isOpen(sModem) and (nChannel == os.getComputerID() or nChannel == CHANNEL_BROADCAST) then | ||||
|             if isOpen(sModem) and (nChannel == id_as_channel() or nChannel == CHANNEL_BROADCAST) then | ||||
|                 if type(tMessage) == "table" and type(tMessage.nMessageID) == "number" | ||||
|                     and tMessage.nMessageID == tMessage.nMessageID and not tReceivedMessages[tMessage.nMessageID] | ||||
|                     and ((tMessage.nRecipient and tMessage.nRecipient == os.getComputerID()) or nChannel == CHANNEL_BROADCAST) | ||||
|                 then | ||||
|                     tReceivedMessages[tMessage.nMessageID] = true | ||||
|                     tReceivedMessageTimeouts[os.startTimer(30)] = tMessage.nMessageID | ||||
|                     os.queueEvent("rednet_message", nReplyChannel, tMessage.message, tMessage.sProtocol) | ||||
|                     os.queueEvent("rednet_message", tMessage.nSender or nReplyChannel, tMessage.message, tMessage.sProtocol) | ||||
|                 end | ||||
|             end | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,10 @@ else | ||||
|     print(#tModems .. " modems found.") | ||||
| end | ||||
|  | ||||
| local function idAsChannel(id) | ||||
|     return (id or os.getComputerID()) % rednet.MAX_ID_CHANNELS | ||||
| end | ||||
|  | ||||
| local function open(nChannel) | ||||
|     for n = 1, #tModems do | ||||
|         local sModem = tModems[n] | ||||
| @@ -53,7 +57,7 @@ local ok, error = pcall(function() | ||||
|                         for n = 1, #tModems do | ||||
|                             local sOtherModem = tModems[n] | ||||
|                             peripheral.call(sOtherModem, "transmit", rednet.CHANNEL_REPEAT, nReplyChannel, tMessage) | ||||
|                             peripheral.call(sOtherModem, "transmit", tMessage.nRecipient, nReplyChannel, tMessage) | ||||
|                             peripheral.call(sOtherModem, "transmit", idAsChannel(tMessage.nRecipient), nReplyChannel, tMessage) | ||||
|                         end | ||||
|  | ||||
|                         -- Log the event | ||||
|   | ||||
| @@ -84,7 +84,7 @@ describe("The rednet library", function() | ||||
|         end) | ||||
|     end) | ||||
|  | ||||
|     describe("on a fake computers", function() | ||||
|     describe("on fake computers", function() | ||||
|         local fake_computer = require "support.fake_computer" | ||||
|  | ||||
|         local function computer_with_rednet(id, fn, options) | ||||
| @@ -168,5 +168,24 @@ describe("The rednet library", function() | ||||
|  | ||||
|             fake_computer.run_all({ computer_1, computer_2, computer_3 }, { computer_1, computer_3 }) | ||||
|         end) | ||||
|  | ||||
|         it("repeats messages between computers with massive ids", function() | ||||
|             local id_1, id_3 = 24283947, 93428798 | ||||
|             local computer_1, modem_1 = computer_with_rednet(id_1, function(rednet, _ENV) | ||||
|                 rednet.send(id_3, "Hello") | ||||
|                 local id, message = rednet.receive() | ||||
|                 expect { id, message }:same { id_3, "World" } | ||||
|             end, { open = true }) | ||||
|             local computer_2, modem_2 = computer_with_rednet(2, nil, { open = true, rep = true }) | ||||
|             local computer_3, modem_3 = computer_with_rednet(id_3, function(rednet) | ||||
|                 rednet.send(id_1, "World") | ||||
|                 local id, message = rednet.receive() | ||||
|                 expect { id, message }:same { id_1, "Hello" } | ||||
|             end, { open = true }) | ||||
|             fake_computer.add_modem_edge(modem_1, modem_2) | ||||
|             fake_computer.add_modem_edge(modem_2, modem_3) | ||||
|  | ||||
|             fake_computer.run_all({ computer_1, computer_2, computer_3 }, { computer_1, computer_3 }) | ||||
|         end) | ||||
|     end) | ||||
| end) | ||||
|   | ||||
| @@ -70,15 +70,22 @@ local function make_computer(id, fn) | ||||
|     return { env = env, peripherals = peripherals, queue_event = queue_event, step = step, co = co } | ||||
| end | ||||
|  | ||||
| local function parse_channel(c) | ||||
|     if c < 0 or c > 65535 then error("Expected number in range 0-65535", 3) end | ||||
|     return c | ||||
| end | ||||
|  | ||||
| --- Add a modem to a computer on a particular side | ||||
| local function add_modem(owner, side) | ||||
|     local open, adjacent = {}, {} | ||||
|     local peripheral = setmetatable({ | ||||
|         open = function(channel) open[channel] = true end, | ||||
|         close = function(channel) open[channel] = false end, | ||||
|         open = function(channel) open[parse_channel(channel)] = true end, | ||||
|         close = function(channel) open[parse_channel(channel)] = false end, | ||||
|         closeAll = function(channel) open = {} end, | ||||
|         isOpen = function(channel) return open[channel] == true end, | ||||
|         isOpen = function(channel) return open[parse_channel(channel)] == true end, | ||||
|         transmit = function(channel, reply_channel, payload) | ||||
|             channel, reply_channel = parse_channel(channel), parse_channel(reply_channel) | ||||
|  | ||||
|             for _, adjacent in pairs(adjacent) do | ||||
|                 if adjacent.open[channel] then | ||||
|                     adjacent.owner.queue_event("modem_message", adjacent.side, channel, reply_channel, payload, 123) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Alessandro
					Alessandro