-- ===== CONFIG =====
local CENTRAL_ID = nil -- set with :cid <id>
local PROTO_CMD = "central_cmd" -- protocol for sending commands to central
local TIMEOUT_S = 2
-- ==================
-- open wireless modem
rednet.close()
for _,s in ipairs(rs.getSides()) do if peripheral.getType(s)=="modem" then rednet.open(s) end end
assert(rednet.isOpen(), "No wireless modem. Use an Advanced Wireless Pocket Computer.")
-- ui state
local W,H = term.getSize()
local log = {}
local input = ""
local cursor = 1
local running = true
local function push(msg)
log[#log+1] = msg
if #log > 100 then table.remove(log,1) end
end
local function redraw()
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
W,H = term.getSize()
-- header
term.setCursorPos(1,1)
term.setTextColor(colors.yellow)
local hdr = ("central:%s proto:%s"):format(CENTRAL_ID and tostring(CENTRAL_ID) or "none", PROTO_CMD)
term.write(hdr)
-- log
term.setTextColor(colors.white)
local maxLines = math.max(0, H-3)
local start = math.max(1, #log - maxLines + 1)
local y = 2
for i=start,#log do
term.setCursorPos(1,y)
term.write(("%-"..W.."s"):format(tostring(log[i]):sub(1,W)))
y=y+1
end
-- input line
term.setCursorPos(1,H)
term.setBackgroundColor(colors.blue)
term.setTextColor(colors.white)
term.write((":%s"):format(input))
term.setBackgroundColor(colors.black)
term.setCursorPos(2+cursor, H)
end
local function send_line(line)
if not CENTRAL_ID then push("ERR: set central id with :cid <id>"); return end
local ok = rednet.send(CENTRAL_ID, {type="cmd", line=line}, PROTO_CMD)
if not ok then push("ERR: rednet.send failed") else push("> "..line) end
end
local function ping()
if not CENTRAL_ID then push("ERR: no central id") return end
rednet.send(CENTRAL_ID, {type="ping"}, PROTO_CMD)
local id,msg,proto = rednet.receive(PROTO_CMD, TIMEOUT_S)
if id==CENTRAL_ID and type(msg)=="table" and msg.type=="pong" then
push("pong:"..(msg.note or "ok"))
else
push("no pong")
end
end
local function help()
push("Commands:")
push(":cid <id> set central computer ID")
push(":ping test connection")
push(":proto <name> set protocol (default central_cmd)")
push(":send <text> send raw line")
push(":help show this help")
push("Shortcuts (mapped to central commands):")
push(" cam yaw <deg> | cam pitch <deg> | cam dist <n>")
push(" track on|off | highlight x y z [r] | clear highlights")
push(" center x y z | tid <id> | tfind")
push(" fwd/back/up/down <n> | left/right | halt | goto x y z")
end
local function parse_local(cmdline)
local args = {}
for w in tostring(cmdline):gmatch("%S+") do args[#args+1]=w end
if #args==0 then return end
local c = args[1]:lower()
if c=="cid" and args[2] then CENTRAL_ID = tonumber(args[2]); push("central id="..tostring(CENTRAL_ID)); return
elseif c=="ping" then ping(); return
elseif c=="proto" and args[2] then PROTO_CMD = args[2]; push("proto="..PROTO_CMD); return
elseif c=="send" then table.remove(args,1); send_line(table.concat(args, " ")); return
elseif c=="help" or c=="?" then help(); return end
-- otherwise treat whole line as central command
send_line(table.concat(args, " "))
end
-- receive loop (acks or server help)
local function net_loop()
while running do
local id,msg,proto = rednet.receive(PROTO_CMD, 0.2)
if id and type(msg)=="table" then
if msg.type=="ack" then push("ack:"..tostring(msg.note or msg.line or "ok"))
elseif msg.type=="err" then push("err:"..tostring(msg.note or ""))
elseif msg.type=="info" then push(tostring(msg.text or ""))
elseif msg.type=="pong" then push("pong")
end
end
end
end
-- input loop
local function input_loop()
redraw()
while running do
local e = {os.pullEvent()}
if e[1]=="char" then
input = input .. e[2]
cursor = #input
redraw()
elseif e[1]=="key" then
local k=e[2]
if k==keys.enter then
local line = input
input=""; cursor=0
redraw()
parse_local(line)
redraw()
elseif k==keys.backspace then
input = input:sub(1, math.max(0,#input-1))
cursor = #input
redraw()
elseif k==keys.q then
running=false
end
elseif e[1]=="term_resize" then
redraw()
end
end
end
parallel.waitForAny(net_loop, input_loop)
term.setBackgroundColor(colors.black); term.setTextColor(colors.white); term.clear()
print("Console closed.")
Comments