-- modem_methods.lua
-- If target is a modem: list methods of device(s) connected to that modem.
-- CC:Tweaked
local function clamp(x,a,b) return math.max(a, math.min(b, x)) end
local function drawList(x, y, w, h, title, items, sel, scroll)
local function line(s)
term.setCursorPos(x, y)
term.write((" "):rep(w))
if s then
term.setCursorPos(x + 1, y)
term.write(s:sub(1, math.max(0, w-2)))
end
y = y + 1
end
term.setCursorPos(x, y)
term.write((" "):rep(w))
if title then
term.setCursorPos(x + 1, y)
term.write(title:sub(1, math.max(0, w-2)))
end
y = y + 1
local visible = h - 1
sel = clamp(sel, 1, math.max(1, #items))
scroll = clamp(scroll, 0, math.max(0, #items - visible))
for i = 1, visible do
local idx = scroll + i
local s = items[idx] or ""
if idx == sel then
term.setBackgroundColor(colors.gray)
term.setTextColor(colors.black)
line(s)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
else
line(s)
end
end
return sel, scroll
end
local function move(sel, scroll, total, maxRows, delta)
sel = clamp(sel + delta, 1, math.max(1, total))
local top = sel - 1
local bottom = sel
if top < scroll then
scroll = top
elseif bottom > scroll + maxRows then
scroll = bottom - maxRows
end
scroll = clamp(scroll, 0, math.max(0, total - maxRows))
return sel, scroll
end
local function pager(title, lines)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
local w, h = term.getSize()
local header = title or ""
local listH = h - 2
local sel, scr = 1, 0
while true do
term.clear()
term.setCursorPos(1,1)
term.write(header:sub(1, w))
sel, scr = drawList(1, 2, w, listH, nil, lines, sel, scr)
local e = { os.pullEvent() }
local ev = e[1]
if ev == "key" then
local k = e[2]
if k == keys.q or k == keys.enter then return
elseif k == keys.up then sel, scr = move(sel, scr, #lines, listH, -1)
elseif k == keys.down then sel, scr = move(sel, scr, #lines, listH, 1)
elseif k == keys.pageUp then sel, scr = move(sel, scr, #lines, listH, -(listH-1))
elseif k == keys.pageDown then sel, scr = move(sel, scr, #lines, listH, (listH-1))
elseif k == keys.home then sel, scr = move(1, 0, #lines, listH, 0)
elseif k == keys["end"] then sel, scr = move(#lines, math.max(0,#lines-listH), #lines, listH, 0)
end
elseif ev == "mouse_scroll" then
local d = e[2]
sel, scr = move(sel, scr, #lines, listH, d)
elseif ev == "term_resize" then
w, h = term.getSize()
listH = h - 2
scr = clamp(scr, 0, math.max(0, #lines - listH))
sel = clamp(sel, 1, math.max(1, #lines))
end
end
end
local function pickFromList(title, items)
if #items == 0 then return nil end
if #items == 1 then return items[1] end
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
local w, h = term.getSize()
local listH = h - 2
local sel, scr = 1, 0
while true do
term.clear()
term.setCursorPos(1,1)
term.write((title or "Select"):sub(1, w))
sel, scr = drawList(1, 2, w, listH, nil, items, sel, scr)
local e = { os.pullEvent() }
local ev = e[1]
if ev == "key" then
local k = e[2]
if k == keys.enter then return items[sel]
elseif k == keys.q then return nil
elseif k == keys.up then sel, scr = move(sel, scr, #items, listH, -1)
elseif k == keys.down then sel, scr = move(sel, scr, #items, listH, 1)
elseif k == keys.pageUp then sel, scr = move(sel, scr, #items, listH, -(listH-1))
elseif k == keys.pageDown then sel, scr = move(sel, scr, #items, listH, (listH-1))
elseif k == keys.home then sel, scr = move(1, 0, #items, listH, 0)
elseif k == keys["end"] then sel, scr = move(#items, math.max(0,#items-listH), #items, listH, 0)
end
elseif ev == "mouse_scroll" then
local d = e[2]
sel, scr = move(sel, scr, #items, listH, d)
elseif ev == "term_resize" then
w, h = term.getSize()
listH = h - 2
scr = clamp(scr, 0, math.max(0, #items - listH))
sel = clamp(sel, 1, math.max(1, #items))
end
end
end
-- Find a modem (optionally from arg)
local argName = ({...})[1]
local modemName
if argName and peripheral.isPresent(argName) and peripheral.getType(argName) == "modem" then
modemName = argName
else
-- collect all modems
local all = {}
for _, n in ipairs(peripheral.getNames()) do
if peripheral.getType(n) == "modem" then table.insert(all, n) end
end
if #all == 0 then
print("No modem peripheral found.")
return
end
modemName = pickFromList("Select a modem (Enter to confirm, Q to cancel)", all)
if not modemName then return end
end
local modem = peripheral.wrap(modemName)
if not modem then
print("Failed to wrap modem: "..modemName)
return
end
-- Check wired vs wireless
local isWireless = false
if modem.isWireless then
-- wired modems also have isWireless() (returns false); wireless returns true
local ok, res = pcall(modem.isWireless)
if ok then isWireless = res and true or false end
end
if isWireless then
print(("'%s' is a wireless modem: no cabled peripherals to inspect."):format(modemName))
print("Tip: Use a WIRED modem connected to a peripheral via modem cable.")
return
end
-- Enumerate peripherals on the wired network via this modem
local remotes = {}
do
local ok, names = pcall(modem.getNamesRemote)
if not ok or type(names) ~= "table" then
print("This modem does not support remote peripherals (is it wired and enabled?).")
return
end
table.sort(names)
for _, n in ipairs(names) do table.insert(remotes, n) end
end
if #remotes == 0 then
print("No peripherals are connected/enabled on the wired network for modem '"..modemName.."'.")
print("Right-click the wired modem on each device to toggle its connection, then try again.")
return
end
local target = pickFromList("Select a device on the wired network", remotes)
if not target then return end
-- Fetch and show methods of the selected remote device
local methods = {}
do
local ok, m = pcall(modem.getMethodsRemote, target)
if not ok or type(m) ~= "table" then
print("Failed to get methods for "..target)
return
end
table.sort(m)
table.insert(methods, ("Remote device: %s (%s)"):format(
target, (modem.getTypeRemote and (modem.getTypeRemote(target) or "unknown") or "unknown")
))
table.insert(methods, string.rep("-", 40))
for _, name in ipairs(m) do table.insert(methods, name) end
end
pager("Methods of "..target.." (Enter/Q to exit, arrows to scroll)", methods)