-- pocket_startup.lua
-- Pocket controller for CC:Tweaked. REPL to drive miners via the base controller.
-- Requires: pocket with Ender (wireless) modem upgrade.
-- Protocols (match your controller)
local PROTOCOL = "minesys:v1" -- miner heartbeats (read-only here)
local CTL_PROTO = "minesys:ctl" -- controller RPC (goto, clear, face, fwd, up, dn)
-- ---- init ----
local modem = peripheral.find("modem", function(_,p) return p.isWireless() end)
if not modem then error("No wireless modem on pocket") end
rednet.open(peripheral.getName(modem))
pcall(function() rednet.host("minesys:pocket", "pocket_"..(os.getComputerLabel() or os.getComputerID())) end)
-- ---- state ----
local function now() return os.epoch("utc") end
local turtles = {} -- by label or id: {id,label,pos,fuel,freePct,status,seen}
local function upsertStatus(m)
local key = m.label or m.id
if not key then return end
local t = turtles[key] or {}
t.id = m.id or t.id
t.label = m.label or t.label or ("t"..tostring(m.id or ""))
t.pos = m.pos or t.pos
t.fuel = m.fuel or t.fuel
t.status = m.status or t.status
if m.extra and m.extra.inv then t.freePct = m.extra.inv.freePct end
t.seen = now()
turtles[key] = t
end
-- ---- UI helpers ----
local function listTurtles()
term.clear(); term.setCursorPos(1,1)
print("Turtles (label fuel free% x,y,z status):")
for _,t in pairs(turtles) do
local pos = t.pos and (t.pos.x..","..t.pos.y..","..t.pos.z) or "?, ?, ?"
local free = t.freePct and string.format("%d", math.floor(t.freePct+0.5)) or "--"
print(string.format("%-14s %-6s %-4s %s [%s]",
t.label or "?", tostring(t.fuel or "?"), free, pos, t.status or "?"))
end
end
local function help()
print("list")
print("fac <label> <N|E|S|W>")
print("fwd <label> <n>")
print("up <label> <n>")
print("dn <label> <n>")
print("clear <label> <L> <W> <H> <N|E|S|W>")
print("goto <label> <x> <y> <z> [order yxz|xyz|...]\n")
end
-- ---- controller RPC ----
local function ctlReq(payload)
payload.op = "req"
payload.ref = math.random(1,1e9)
rednet.broadcast(payload, CTL_PROTO)
local tm = os.startTimer(4)
while true do
local ev,a,b,c = os.pullEvent()
if ev=="rednet_message" then
local sid,msg,proto = a,b,c
if proto==CTL_PROTO and type(msg)=="table" and msg.op=="resp" and msg.ref==payload.ref then
return msg.ok, msg.err
end
elseif ev=="timer" and a==tm then
return false, "timeout"
end
end
end
-- ---- REPL command wrappers ----
local function cmd_face(lab, dir)
if dir=="" then print("need dir"); return end
local ok,err = ctlReq({act="face", label=lab, dir=dir})
print(ok and "ok" or ("err: "..tostring(err)))
end
local function cmd_fwd(lab, n)
local ok,err = ctlReq({act="fwd", label=lab, n=tonumber(n) or 1})
print(ok and "ok" or ("err: "..tostring(err)))
end
local function cmd_up(lab, n)
local ok,err = ctlReq({act="up", label=lab, n=tonumber(n) or 1})
print(ok and "ok" or ("err: "..tostring(err)))
end
local function cmd_dn(lab, n)
local ok,err = ctlReq({act="dn", label=lab, n=tonumber(n) or 1})
print(ok and "ok" or ("err: "..tostring(err)))
end
local function cmd_clear(lab, L, W, H, dir)
local ok,err = ctlReq({
act="clear", label=lab,
L=tonumber(L), W=tonumber(W), H=tonumber(H), dir=dir
})
print(ok and "ok" or ("err: "..tostring(err)))
end
local function parseOrder(ord)
if ord and #ord==3 then return {ord:sub(1,1), ord:sub(2,2), ord:sub(3,3)} end
return nil
end
local function cmd_goto(lab,x,y,z,ord)
local function parseOrder(o) return (o and #o==3) and {o:sub(1,1),o:sub(2,2),o:sub(3,3)} or nil end
local ok,err = ctlReq({act="goto", label=lab, x=tonumber(x), y=tonumber(y), z=tonumber(z), order=parseOrder(ord)})
print(ok and "ok" or ("err: "..tostring(err)))
end
-- ---- threads ----
local function inputThread()
term.clear(); term.setCursorPos(1,1)
print("Pocket miner controller. type 'help'.")
while true do
io.write("> ")
local line = read()
local a,b,c,d,e,f = line:match("^(%S+)%s*(%S*)%s*(%S*)%s*(%S*)%s*(%S*)%s*(%S*)")
if a=="help" then help()
elseif a=="list" then listTurtles()
elseif a=="fac" then cmd_face(b,c)
elseif a=="fwd" then cmd_fwd(b,c)
elseif a=="up" then cmd_up(b,c)
elseif a=="dn" then cmd_dn(b,c)
elseif a=="clear" then cmd_clear(b,c,d,e,f)
elseif a=="goto" then cmd_goto(b,c,d,e,f)
elseif a=="" then
else print("unknown") end
end
end
local function netThread()
while true do
local id,msg,proto = rednet.receive(PROTOCOL, 5)
if id and proto==PROTOCOL and type(msg)=="table" and msg.op=="status" then
upsertStatus(msg)
end
end
end
parallel.waitForAny(inputThread, netThread)
Comments