-- rnc2.lua (CC:T API version – no module/table tricks) local BASE_PORT = 39000 local MODEMS = { peripheral.find("modem") } if #MODEMS == 0 then error("rnc2: no modems found") end -- open base port for _, m in ipairs(MODEMS) do m.open(BASE_PORT) end local function shortHash(s) local h = 0 for i = 1, #s do h = (h + s:byte(i)) % 1000 end return h end local function progPort(prog) return BASE_PORT + shortHash(prog) end local function openProg(prog) local p = progPort(prog) for _, m in ipairs(MODEMS) do if not m.isOpen(p) then m.open(p) end end return p end -- ✅ these are the PUBLIC ones CC will expose as rnc2.getId(...) function getId(prog) return ("%s@%d"):format(prog, os.getComputerID()) end function getPort(prog) return progPort(prog) end function send(prog, target, body) local port = openProg(prog) local pkt = { prog = prog, from = getId(prog), to = target or "*", t = os.epoch("utc"), body = body } local data = textutils.serialize(pkt) for _, m in ipairs(MODEMS) do m.transmit(port, port, data) end end function broadcast(prog, body) return send(prog, "*", body) end function recv(prog, timeout) local port = openProg(prog) local timerId if timeout and timeout > 0 then timerId = os.startTimer(timeout) end while true do local ev, p1, p2, p3, p4 = os.pullEvent() if ev == "modem_message" and p2 == port then local ok, pkt = pcall(textutils.unserialize, p4) if ok and type(pkt) == "table" then local me = getId(prog) if (not pkt.to) or pkt.to == "*" or pkt.to == me then return pkt end end elseif ev == "timer" and p1 == timerId then return nil end end end function autoPong(prog, pkt) if pkt.body and pkt.body.type == "ping" then send(prog, pkt.from, { type = "pong" }) return true end return false end