Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- miner_startup.lua
- -- Ultra-dumb miner. Verbose local console + heartbeats.
- -- Requires: wireless (ender) modem; label set via: label set miner_alpha
- local PROTOCOL = "minesys:v1"
- local HEARTBEAT_SEC = 2
- local modem = peripheral.find("modem", function(_, p) return p.isWireless() end)
- if not modem then error("No wireless modem") end
- if not turtle then error("Run on a turtle") end
- rednet.open(peripheral.getName(modem))
- -- ---------------- console/status ----------------
- local state = {
- status = "waiting",
- extra = nil,
- facing = "N",
- pos = nil,
- fuel = turtle.getFuelLevel(),
- lastDraw = 0,
- }
- local function invStats()
- local empty = 0
- for i=1,16 do if turtle.getItemCount(i)==0 then empty = empty + 1 end end
- local pct = (empty/16)*100
- return { freeSlots = empty, freePct = pct }
- end
- local function now() return os.epoch("utc") end
- local function gpsPos()
- local x, y, z = gps.locate(1)
- if x then state.pos = {x=x,y=y,z=z} end
- return x, y, z
- end
- local function setStatus(s, extra)
- state.status = s or state.status
- state.extra = extra or nil
- end
- local function drawConsole(force)
- local t = now()
- if not force and (t - state.lastDraw) < 100 then return end -- 0.1s throttle
- state.lastDraw = t
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1,1)
- local lbl = os.getComputerLabel() or ("id"..os.getComputerID())
- print(("Miner %s"):format(lbl))
- print(("Fuel: %s"):format(tostring(state.fuel)))
- local p = state.pos
- print(("Pos: %s"):format(p and ("("..p.x..","..p.y..","..p.z..")") or "unknown"))
- print(("Facing: %s"):format(state.facing))
- print(("Status: %s"):format(state.status))
- if state.extra then
- -- Render compact progress lines
- if state.extra.kind=="move" then
- print(("- Move %s: %d/%d"):format(state.extra.axis, state.extra.step, state.extra.total))
- elseif state.extra.kind=="clear" then
- print(("- Clear LxWxH: %d×%d×%d"):format(state.extra.L, state.extra.W, state.extra.H))
- print((" Layer: %d/%d Row: %d/%d Step: %d/%d"):format(
- state.extra.layer, state.extra.H,
- state.extra.row, state.extra.W,
- state.extra.step, state.extra.L
- ))
- elseif state.extra.kind=="face" then
- print(("- Face: %s"):format(state.extra.dir))
- elseif state.extra.kind=="note" and state.extra.msg then
- print(("- Note: %s"):format(state.extra.msg))
- end
- end
- end
- local function hb()
- state.fuel = turtle.getFuelLevel()
- gpsPos()
- local msg = {
- t = now(),
- op = "status",
- id = os.getComputerID(),
- label = os.getComputerLabel(),
- pos = state.pos,
- fuel = state.fuel,
- facing = state.facing,
- status = state.status,
- extra = state.extra,
- inv = invStats(),
- }
- rednet.broadcast(msg, PROTOCOL)
- end
- local function report(s, extra, forceDraw)
- setStatus(s, extra)
- drawConsole(forceDraw)
- hb()
- end
- -- ---------------- motion primitives ----------------
- local DIRS = {N=0, E=1, S=2, W=3}
- local dirNames = {"N","E","S","W"}
- local function setFacing(newDir)
- if not DIRS[newDir] then return false, "bad dir" end
- if state.facing == newDir then
- report("waiting", {kind="face", dir=newDir})
- return true
- end
- local idx = DIRS[state.facing]; local tgt = DIRS[newDir]
- local diff = (tgt - idx) % 4
- report("waiting", {kind="face", dir=newDir}, true)
- if diff == 1 then turtle.turnRight()
- elseif diff == 2 then turtle.turnRight(); turtle.turnRight()
- elseif diff == 3 then turtle.turnLeft()
- end
- state.facing = newDir
- report("waiting", {kind="face", dir=newDir})
- return true
- end
- local function digForward()
- while turtle.detect() do
- turtle.dig()
- sleep(0.15)
- end
- end
- local function forward(n)
- n = math.max(0, n or 1)
- for i=1, n do
- report("moving to", {kind="move", axis="fwd", step=i, total=n})
- digForward()
- local tries=0
- while not turtle.forward() do
- digForward()
- tries=tries+1
- if tries>50 then
- report("waiting", {kind="note", msg="blocked fwd"})
- return false, "blocked"
- end
- sleep(0.15)
- end
- end
- report("waiting")
- return true
- end
- local function up(n)
- n = math.max(0, n or 1)
- for i=1, n do
- report("moving to", {kind="move", axis="up", step=i, total=n})
- while turtle.detectUp() do turtle.digUp(); sleep(0.15) end
- local tries=0
- while not turtle.up() do
- while turtle.detectUp() do turtle.digUp(); sleep(0.15) end
- tries=tries+1
- if tries>50 then
- report("waiting", {kind="note", msg="blocked up"})
- return false, "blocked"
- end
- sleep(0.15)
- end
- end
- report("waiting")
- return true
- end
- local function down(n)
- n = math.max(0, n or 1)
- for i=1, n do
- report("moving to", {kind="move", axis="down", step=i, total=n})
- while turtle.detectDown() do turtle.digDown(); sleep(0.15) end
- local tries=0
- while not turtle.down() do
- while turtle.detectDown() do turtle.digDown(); sleep(0.15) end
- tries=tries+1
- if tries>50 then
- report("waiting", {kind="note", msg="blocked down"})
- return false, "blocked"
- end
- sleep(0.15)
- end
- end
- report("waiting")
- return true
- end
- -- ---------------- clear area ----------------
- local function clearArea(length, width, height, startDir)
- local L = math.max(1, length or 1)
- local W = math.max(1, width or 1)
- local H = math.max(1, height or 1)
- setFacing(startDir or state.facing)
- local function sweepRow(len, layerIdx, rowIdx)
- for i=1,len do
- report("clearing area", {
- kind="clear", L=L, W=W, H=H,
- layer=layerIdx, row=rowIdx, step=i
- })
- digForward()
- if i<len then assert(forward(1)) end
- end
- end
- for h=1,H do
- setFacing(startDir or state.facing)
- for w=1,W do
- sweepRow(L, h, w)
- if w<W then
- if (w % 2 == 1) then
- turtle.turnRight(); digForward(); assert(forward(1)); turtle.turnRight()
- -- update facing tag
- if state.facing=="N" then state.facing="E"
- elseif state.facing=="E" then state.facing="S"
- elseif state.facing=="S" then state.facing="W"
- elseif state.facing=="W" then state.facing="N" end
- else
- turtle.turnLeft(); digForward(); assert(forward(1)); turtle.turnLeft()
- if state.facing=="N" then state.facing="W"
- elseif state.facing=="W" then state.facing="S"
- elseif state.facing=="S" then state.facing="E"
- elseif state.facing=="E" then state.facing="N" end
- end
- end
- end
- if h<H then assert(up(1)) end
- end
- report("waiting")
- return true
- end
- -- ---------------- heartbeat + loop ----------------
- report("waiting", {kind="note", msg="boot"}, true)
- parallel.waitForAny(
- function()
- -- command loop
- while true do
- local sender, msg, proto = rednet.receive(PROTOCOL, HEARTBEAT_SEC)
- if sender and proto==PROTOCOL and type(msg)=="table" and msg.op=="cmd" then
- local ok, err
- if msg.act=="face" then
- ok, err = setFacing(msg.dir)
- elseif msg.act=="forward" then
- ok, err = forward(msg.n or 1)
- elseif msg.act=="up" then
- ok, err = up(msg.n or 1)
- elseif msg.act=="down" then
- ok, err = down(msg.n or 1)
- elseif msg.act=="clear_area" then
- ok, err = clearArea(msg.length or 1, msg.width or 1, msg.height or 1, msg.dir or state.facing)
- elseif msg.act=="set_facing_tag" then
- state.facing = msg.dir or state.facing
- report("waiting", {kind="face", dir=state.facing})
- ok = true
- else
- ok, err = false, "unknown act"
- report("waiting", {kind="note", msg="unknown act"})
- end
- rednet.send(sender, {op="ack", ok=ok, err=err, ref=msg.ref}, PROTOCOL)
- else
- report("waiting") -- idle tick keeps console fresh
- end
- end
- end,
- function()
- while true do
- sleep(HEARTBEAT_SEC)
- report("waiting")
- end
- end
- )
Advertisement
Add Comment
Please, Sign In to add comment