local channel = 31415 local m = peripheral.find("modem", function(_, o) return o.isWireless() end) if not m then error "Modem required!" end local tele = peripheral.find "Teleporter" if not tele then error "Teleporter (see Mekanism wiki) required!" end local sign = peripheral.find "minecraft:sign" local rift_ID = os.getComputerLabel():match "Rift:([A-Za-z0-9_-]+)" if not rift_ID then error "Please relabel this computer `Rift:[unique rift identifier]`." end m.open(channel) local function display_status(...) if sign then sign.setSignText(rift_ID, ...) end end local function split_at_spaces(s) local t = {} for i in string.gmatch(s, "%S+") do table.insert(t, i) end return t end local function first_letter(s) return string.sub(s, 1, 1) end local function update_self() print "Downloading update." local h = http.get "https://pastebin.com/raw/jta5puZL" local t = h.readAll() h.close() local fn, err = load(t, "@rift") if not fn then printError("Not updating: syntax error:\n" .. err) end local f = fs.open("startup", "w") f.write(t) f.close() os.reboot() end local teleporter_errors = { [2] = "Frame invalid.", [3] = "Pairing error.", [4] = "Insufficient energy." } local function send_message(...) m.transmit(channel, channel, { ... }) end local function disconnect(remote) display_status "Idle" if not remote then send_message("command", "handle_disconnect", rift_ID) end tele.setFrequency(("rift-%s-null"):format(rift_ID), true) end local connected_to = nil local remote_commands = { ping = function() return { rift_ID } end, update = function() update_self() end, dial = function(from, to) if to ~= rift_ID then return end if type(from) ~= "string" then error("Invalid or no originator specified!") end local freq = ("rift-%s-%s"):format(from, to) tele.setFrequency(freq, true) local status = tele.canTeleport() if status == 1 then print(("Connection established from %s."):format(from)) display_status("Dialed from:", from) connected_to = from return { true } else local e = teleporter_errors[status] or "Unknown error." display_status("Error:", e) printError(("Error receiving connection from %s: %s"):format(from, e)) return { false, e } end end, handle_disconnect = function(other_end) if other_end == connected_to then disconnect(true) end end } local function timeout(fn, time) local timer = os.startTimer(time) local co = coroutine.create(fn) local filter while true do local ev = { os.pullEvent() } if coroutine.status(co) == "dead" or ev[1] == "timer" and ev[2] == timer then return end if not filter or filter == ev[1] then local ok, res = coroutine.resume(co, unpack(ev)) if not ok then error(res) else filter = res end end end end local usage = [[Welcome to Rift. All listed commands are accessible by single-letter shortcuts. dial [destination] - Open a connection to rift [destination]. scan - Scan for available rifts. scan [filter] - Scan for available rifts whose names contain [filter]. help - Print this. update - Update this. disconnect - Disconnect from current paired rift. id - Get the ID of the current rift.]] local CLI_commands = { help = function() textutils.pagedPrint(usage) end, dial = function(dest) if not dest then error "No destination rift specified." end local freq = ("rift-%s-%s"):format(rift_ID, dest) print(("Setting frequency to %s."):format(freq)) tele.setFrequency(freq, true) print(("Sending dial request to %s."):format(dest)) send_message("command", "dial", rift_ID, dest) local result timeout(function() while true do local _, response_to, success, error_type = os.pullEvent "remote_result" if response_to == "dial" then if not success then print(dest, "reports error:", error_type) result = "remote_error" else print(dest, "reports success.") local status = tele.canTeleport() if status == 1 then result = "success" print "Link established." display_status("Dialed to:", dest) connected_to = dest else result = "local_error" local e = teleporter_errors[status] or "Unknown error." display_status("Error:", e) print(e) end end break end end end, 1) if result == nil then error(dest .. " is unreachable or nonexistent.", 0) end end, update = function(what) if what == "all" then send_message("command", "update") print "Update command broadcast" end update_self() end, scan = function(filter) send_message("command", "ping") print "Scanning..." timeout(function() while true do local _, resp_to, from = os.pullEvent "remote_result" if resp_to == "ping" and from and (not filter or from:match(filter)) then print("Found:", from) end end end, 1) end, disconnect = disconnect, id = function() print("Rift ID:", rift_ID) end } local function command_prompt() print "Welcome to Rift!" local history = {} while true do write "|> " local text = read(nil, history) if text ~= "" then table.insert(history, text) end local tokens = split_at_spaces(text) local command = table.remove(tokens, 1) local args = tokens local fn = CLI_commands[command] if not fn then for command_name, func in pairs(CLI_commands) do if command and first_letter(command_name) == first_letter(command) then fn = func end end end if not fn then print("Command", command, "not found.") else local ok, err = pcall(fn, table.unpack(args)) if not ok then printError(err) end end end end local function message_handler() while true do local _, _, _, _, message = os.pullEvent "modem_message" if type(message) == "table" then local mtype = table.remove(message, 1) if mtype == "command" then local cmd = table.remove(message, 1) local cmd_fn = remote_commands[cmd] if cmd_fn then local ok, res = pcall(cmd_fn, unpack(message)) if ok then if type(res) == "table" then send_message("result", cmd, unpack(res)) end else printError(res) send_message("error", res) end end elseif mtype == "result" then os.queueEvent("remote_result", unpack(message)) elseif mtype == "error" then os.queueEvent("remote_error", unpack(message)) end end end end if ... == "update" then update_self() end disconnect() parallel.waitForAny(message_handler, command_prompt)