Files
cc_housebuild/src/main.lua
2026-02-23 00:42:54 +01:00

995 lines
31 KiB
Lua

local url = "http://justus.l--n.de:3000/JUFS/cc_housebuild/raw/branch/main/src/main.lua"
if not _G["turtle"] then
error("This program only runs on turtles!")
end
local turtle = _G["turtle"]
print("House building system")
print("JUFS Technologies (c) 2026 (Justus Wolff)")
print("fuel: "..tostring(turtle.getFuelLevel()).."/"..tostring(turtle.getFuelLimit()))
os.sleep(0.1)
function term.setcol(fc, bc)
term.setTextColor(fc)
term.setBackgroundColor(bc)
end
local function reset()
term.setcol(colors.white, colors.black)
term.clear()
term.setCursorPos(1,1)
end
local function incline()
local _,y = term.getCursorPos()
term.setCursorPos(1,y+1)
end
local function selopt(options, title)
local selected = 1
while true do
reset()
term.setcol(colors.black, colors.white)
term.write(title)
for i,v in pairs(options) do
incline()
if i == selected then
term.setcol(colors.black, colors.blue)
else
term.setcol(colors.white, colors.black)
end
term.write(v)
end
local event,key = os.pullEvent("key")
if keys.getName(key) == "w" and selected ~= 1 then
selected = selected - 1
end
if keys.getName(key) == "s" and selected ~= #options then
selected = selected + 1
end
if keys.getName(key) == "enter" then
return selected
end
end
end
local function integritycheck()
if not fs.exists("designs") then
fs.makeDir("designs")
end
end
local function posasstring(...)
local positions = {...}
local out = ""
for _,v in pairs(positions) do
out = out .. tostring(v) .. ":"
end
return out
end
local function load(name)
local file = fs.open("designs/"..name, "r")
local content = file.readAll()
file.close()
content = textutils.unserialiseJSON(content)
return content["buf"],content["dimensions"]
end
local function bufistype(buf, x,y,z, targettype)
if buf[posasstring(x,y,z)] == targettype then
return true
else
return targettype == 0 and buf[posasstring(x,y,z)] == nil
end
end
local function fill_getneighbors(x,y,z, sx,sz, seltype,buf)
local out = {}
if x ~= sx and bufistype(buf, x+1,y,z, seltype) then table.insert(out, {x+1,z}) end
if x ~= 1 and bufistype(buf, x-1,y,z, seltype) then table.insert(out, {x-1,z}) end
if z ~= sz and bufistype(buf, x,y,z+1, seltype) then table.insert(out, {x,z+1}) end
if z ~= 1 and bufistype(buf, x,y,z-1, seltype) then table.insert(out, {x,z-1}) end
return out
end
local function fill(ntype, x,y,z, buf, sx,sz)
local inittype = buf[posasstring(x,y,z)]
if inittype == ntype then return end -- no work needs to be done
local neighbors = fill_getneighbors(x,y,z, sx,sz, inittype,buf)
buf[posasstring(x,y,z)] = ntype
local processed = 0
local totalneighbors = #neighbors
term.setcol(colors.white, colors.black)
while #neighbors > 0 do
term.setCursorPos(1,1)
term.write(tostring(processed).."/"..tostring(totalneighbors))
local cn = table.remove(neighbors, 1)
local cx,cz = cn[1],cn[2]
local newneigh = fill_getneighbors(cx,y,cz, sx,sz, inittype,buf)
for _,v in pairs(newneigh) do
table.insert(neighbors, v)
buf[posasstring(v[1],y,v[2])] = ntype
totalneighbors = totalneighbors + 1
end
buf[posasstring(cx,y,cz)] = ntype
processed = processed + 1
end
end
local function newdesign()
local buf = {}
local dimensions = {
x = 8,
z = 8,
y = 1
}
local currentfloor = 1
local camx,camy = 0,0
local currentblock = 2
local blockindex = 1
local blocks = {
2, -- no ceiling
3, -- doorway
4, -- glass
}
local function renderblock(index)
local block = blocks[index]
if block == 2 then -- no ceiling
term.blit("C", colors.toBlit(colors.black), colors.toBlit(colors.red))
end
if block == 3 then -- doorway
term.blit("D", colors.toBlit(colors.black), colors.toBlit(colors.brown))
end
if block == 4 then -- glass
term.blit("W", colors.toBlit(colors.black), colors.toBlit(colors.white))
end
end
local shift = false
while true do
-- render buf
reset()
for x=1+camx,dimensions["x"]+camx,1 do
for z=1+camy,dimensions["z"]+camy,1 do
local currentbuf = buf[posasstring(x-camx, currentfloor, z-camy)]
term.setCursorPos(x, z)
if currentbuf == 1 then -- wall
term.blit(" ", colors.toBlit(colors.white), colors.toBlit(colors.white))
elseif currentbuf and currentbuf > 1 then -- blocks
renderblock(currentbuf-1)
--term.blit("C", colors.toBlit(colors.black), colors.toBlit(colors.red))
elseif currentbuf == 0 or currentbuf == nil then -- nothing
if buf[posasstring(x-camx, currentfloor-1, z-camy)] == 2 then
term.blit("\127", colors.toBlit(colors.red), colors.toBlit(colors.black))
else
term.blit("\127", colors.toBlit(colors.gray), colors.toBlit(colors.black))
end
end
end
end
term.setcol(colors.yellow, colors.black)
local _,y = term.getSize()
term.setCursorPos(1,y-1)
term.write("Press Ctrl for menu. ")
term.setCursorPos(1,y)
term.write("x: "..tostring(camx))
term.write(" z: "..tostring(camy))
term.write(" floor: "..tostring(currentfloor))
term.write(" Block: ")
renderblock(blockindex)
-- user input
local event = table.pack(os.pullEvent())
if event[1] == "mouse_click" or event[1] == "mouse_drag" then
event[3] = event[3]-camx
event[4] = event[4]-camy
if event[3] <= dimensions["x"] and event[4] <= dimensions["z"] then
if event[2] == 1 then -- left button, set
if shift then
fill(1, event[3],currentfloor,event[4], buf,dimensions["x"],dimensions["z"])
end
buf[posasstring(event[3], currentfloor, event[4])] = 1
end
if event[2] == 3 then -- middle button, set special block
if shift then
fill(currentblock, event[3],currentfloor,event[4], buf,dimensions["x"],dimensions["z"])
end
buf[posasstring(event[3], currentfloor, event[4])] = currentblock
end
if event[2] == 2 then -- right button, erase
if shift then
fill(0, event[3],currentfloor,event[4], buf,dimensions["x"],dimensions["z"])
end
buf[posasstring(event[3], currentfloor, event[4])] = 0
end
end
end
if event[1] == "mouse_scroll" then
if event[2] == 1 then -- down
if blockindex == #blocks then blockindex = 1 else blockindex = blockindex + 1 end
end
if event[2] == -1 then -- up
if blockindex == 1 then blockindex = #blocks else blockindex = blockindex - 1 end
end
currentblock = blocks[blockindex]
end
if event[1] == "key" then
if keys.getName(event[2]) == "leftShift" then
shift = true
end
if keys.getName(event[2]) == "leftCtrl" then -- menu
local action = selopt({
"Save",
"Load",
"Exit",
"Change X size",
"Change floor amount",
"Change Z size"
}, "menu")
if action == 3 then return end -- exit
if action == 1 then -- save
reset()
for _,v in pairs(fs.list("designs")) do
term.write(v)
incline()
end
write("Enter name: ")
local name = read()
local file = fs.open("designs/"..name, "w")
file.write(textutils.serialiseJSON({
["dimensions"] = dimensions,
["buf"] = buf
}))
file.close()
end
if action == 2 then -- load
reset()
for _,v in pairs(fs.list("designs")) do
term.write(v)
incline()
end
write("Enter name: ")
local name = read()
if not fs.exists("designs/"..name) or name == "" then
printError("Design not found!")
else
buf,dimensions = load(name)
camx,camy,currentfloor = 0,0,1
end
end
if action == 4 then -- change X size
reset()
write("Enter new X size: ")
local xsize = tonumber(read())
dimensions["x"] = xsize
end
if action == 5 then -- change floor amount
reset()
write("Enter new floor amount: ")
local ysize = tonumber(read())
dimensions["y"] = ysize
end
if action == 6 then -- change Z size
reset()
write("Enter new Z size: ")
local zsize = tonumber(read())
dimensions["z"] = zsize
end
end
if keys.getName(event[2]) == "q" and currentfloor < dimensions["y"] then -- go up
currentfloor = currentfloor + 1
end
if keys.getName(event[2]) == "e" and currentfloor > 1 then -- go down
currentfloor = currentfloor - 1
end
if keys.getName(event[2]) == "w" and camy < dimensions["z"] then -- pan up
camy = camy + 1
end
if keys.getName(event[2]) == "s" and camy > -dimensions["z"] then -- pan down
camy = camy - 1
end
if keys.getName(event[2]) == "a" and camx < dimensions["x"] then -- pan left
camx = camx + 1
end
if keys.getName(event[2]) == "d" and camx > -dimensions["z"] then -- pan right
camx = camx - 1
end
end
if event[1] == "key_up" then
if keys.getName(event[2]) == "leftShift" then shift = false end
end
end
end
local function move(direction, continousattempt)
if direction == "left" then
turtle.turnLeft()
return
end
if direction == "right" then
turtle.turnRight()
return
end
while true do
if turtle.getFuelLevel() == 0 then
reset()
print("Out of fuel! Trying to refuel.")
while true do
local suc = turtle.refuel(64)
if suc then
break
end
local current = turtle.getSelectedSlot()
if current == 16 then
turtle.select(1)
else
turtle.select(current+1)
end
os.sleep(1)
end
end
local suc,reason = turtle[direction]()
if not suc and not continousattempt then
printError(reason)
print("Resolve the error and press enter to continue.")
read("")
elseif not suc and continousattempt then
reset()
printError("Failure moving "..direction.." Continous attempt true.")
elseif suc then
break
end
end
end
local function place(direction)
local func = turtle.place
local cfunc = turtle.compare
if direction == "down" then
func = turtle.placeDown
cfunc = turtle.compareDown
end
if direction == "up" then
func = turtle.placeUp
cfunc = turtle.compareUp
end
while true do
local suc = func()
if not suc then -- next slot
if cfunc() and turtle.getItemDetail(turtle.getSelectedSlot()) ~= nil then return end
local current = turtle.getSelectedSlot()
if current == 16 then
turtle.select(1)
else
turtle.select(current+1)
end
else break end
os.sleep(0) -- yield
end
end
local function placebuf(buf, x, y, z)
if buf[posasstring(x,y,z)] == 1 then
place("down")
end
end
local function directiondist(direction, wanted)
if direction == 0 then return 1 end
if direction == 1 and wanted == -1 then return 2 end
if direction == -1 and wanted == 1 then return 2 end
if direction ~= wanted then return 1 end -- failsafes
if direction == wanted then return 0 end
end
local function needstobeplaced(placecode, clayer)
if clayer == 0 or clayer == 2 then
return placecode == 1
end
if clayer == 1 then
return placecode == 1 or placecode == 4
end
if clayer == 3 then
return placecode == 1 or placecode == 4 or placecode == 3
end
end
local function getnearestunplaced(buf, pbuf, cx,cy,cz,clayer, sx,sz, direction)
local distance = math.huge
local selected = nil
for x=1,sx,1 do
for y=1,sz,1 do
local extracost = 0
if x ~= cx and direction ~= 0 then
extracost = extracost + 1
end
if y > cz and direction ~= 1 then
extracost = extracost + directiondist(direction, 1)
end
if y < cz and direction ~= -1 then
extracost = extracost + directiondist(direction, -1)
end
local needplace = buf[posasstring(x,cy,y)]
if pbuf[posasstring(x,cy,y)] then needplace = 0 end -- already placed
needplace = needstobeplaced(needplace, clayer)
if needplace then -- needs to be placed, calculate distance
local cd = math.abs(y-cz)+math.abs(x-cx) -- raw distance (amount of blocks between)
cd = cd + extracost
if cd < distance then
distance = cd
selected = {x,y}
end
end
end
end
return selected
end
local function center(direction, wanted)
if direction == 1 and wanted ~= 1 then
move("left")
return true
end
if direction == -1 and wanted ~= -1 then
move("right")
return true
end
if direction == 0 then return true end
return false
end
local function moveto(x,y,cx,cz,direction)
while x ~= cx do
if cx < x then -- x
center(direction)
direction = 0
cx = cx + 1
move("forward")
end
if cx > x then
center(direction)
direction = 0
cx = cx - 1
move("back")
end
end
while y ~= cz do
if y > cz then -- z
if center(direction, 1) then move("right") end
cz = cz + 1
move("forward")
direction = 1
end
if y < cz then
if center(direction, -1) then move("left") end
cz = cz - 1
move("forward")
direction = -1
end
end
return cx,cz,direction
end
local function tcontains(x, y)
for _,v in pairs(x) do
if v == y then return true end
end
return false
end
local function render(buf, pbuf, cx,cy,cz, tx,tz, sx,sz, shouldsetlist,invertslist)
shouldsetlist = shouldsetlist or {
1,
}
local tsx,tsy = term.getSize()
local camx,camy = cx-(tsx/2),cz-(tsy/2)
reset()
for x=1,sx,1 do
for z=1,sz,1 do
local currentbuf = pbuf[posasstring(x, cy, z)]
term.setCursorPos(x-camx, z-camy)
if currentbuf then -- wall
term.blit(" ", colors.toBlit(colors.white), colors.toBlit(colors.white))
elseif (currentbuf == false or currentbuf == nil) and (invertslist and not tcontains(shouldsetlist, buf[posasstring(x, cy, z)]) or tcontains(shouldsetlist, buf[posasstring(x, cy, z)])) then -- nothing
term.blit("\127", colors.toBlit(colors.gray), colors.toBlit(colors.black))
end
end
end
term.setCursorPos(cx-camx,cz-camy)
term.blit(" ", colors.toBlit(colors.red), colors.toBlit(colors.red))
term.setCursorPos(tx-camx,tz-camy)
term.blit(" ", colors.toBlit(colors.lime), colors.toBlit(colors.lime))
end
local function printdes(buf, dimensions)
move("up")
move("forward")
local cx = 1
local cz = 1
local direction = 0
for cy=1,dimensions["y"],1 do
local setlists = {
{1,4},
{1},
{1,3,4},
}
for clayer=1,3,1 do -- build walls
local pbuf = {}
while true do
local target = getnearestunplaced(buf, pbuf, cx,cy,cz,clayer, dimensions["x"],dimensions["z"], direction)
if not target then break end
render(buf, pbuf, cx,cy,cz, target[1],target[2], dimensions["x"],dimensions["z"], setlists[clayer])
--read("")
cx,cz,direction = moveto(target[1],target[2],cx,cz,direction)
place("down")
pbuf[posasstring(cx,cy,cz)] = true
end
move("up")
end
-- build ceiling/floor
local pbuf = {}
local cbuf = {}
for _cz=1,dimensions["z"],1 do
for _cx=1,dimensions["x"],1 do
if buf[posasstring(_cx,cy,_cz)] ~= 2 then
cbuf[posasstring(_cx,0,_cz)] = 1
else
cbuf[posasstring(_cx,0,_cz)] = 0
end
end
end
while true do
local target = getnearestunplaced(cbuf, pbuf, cx,0,cz,0, dimensions["x"],dimensions["z"], direction)
if not target then break end
render(cbuf, pbuf, cx,0,cz, target[1],target[2], dimensions["x"],dimensions["z"], {1})
cx,cz,direction = moveto(target[1],target[2],cx,cz,direction)
place("down")
pbuf[posasstring(cx,0,cz)] = true
end
-- return to standard pos but +1 to y
cx,cz,direction = moveto(1,1,cx,cz,direction)
move("up")
end
cx,cz,direction = moveto(0,1, cx,cz, direction)
for _=1,dimensions["y"]*(4)+1,1 do -- go back to starting position
move("down")
end
center(direction)
end
-- vertical stack printing
local function VP_movetoy(y, target)
while y > target do
move("down", true)
y = y - 1
end
while y < target do
move("up", true)
y = y + 1
end
return target
end
local function VP_moveto(x,z, cx,cz,direction)
local y = 0
--[[
y lanes for directions:
1: +x
2: -x
3: +z
4: -z
]]--
while x ~= cx do
if cx < x then -- x
center(direction)
direction = 0
y = VP_movetoy(y, 1)
cx = cx + 1
move("forward", true)
end
if cx > x then
center(direction)
direction = 0
y = VP_movetoy(y, 2)
cx = cx - 1
move("back", true)
end
end
while z ~= cz do
if z > cz then -- z
if center(direction, 1) then move("right") end
y = VP_movetoy(y, 3)
cz = cz + 1
move("forward", true)
direction = 1
end
if z < cz then
if center(direction, -1) then move("left") end
y = VP_movetoy(y, 4)
cz = cz - 1
move("forward", true)
direction = -1
end
end
VP_movetoy(y, 0)
return cx,cz,direction
end
local function VP_optimizestack(target)
-- go from bottom to top and erase false entries until we encounter a true one.
while #target > 0 do
if target[1] then break else
table.remove(target, 1)
end
end
return target
end
local function VP_createstack(buf, dimensions)
local fout = {
["height"] = dimensions["y"]*(4)+1,
["dimensions"] = dimensions,
}
local out = {}
for x=1,dimensions["x"],1 do
for z=1,dimensions["z"],1 do
local tempbuf = {}
for y=1,dimensions["y"],1 do -- for each y dimension
local placecode = buf[posasstring(x,y,z)]
for layer=1,3,1 do -- layers
table.insert(tempbuf, needstobeplaced(placecode, layer))
end
-- ceiling
table.insert(tempbuf, buf[posasstring(x,y,z)] ~= 2)
end
VP_optimizestack(tempbuf)
if #tempbuf > 0 then
out[posasstring(x,z)] = tempbuf
end
end
end
fout["stacks"] = out
return fout
end
local function VP_lengthofdict(target)
local out = 0
for _,v in pairs(target) do out = out + 1 end
return out
end
local function VP_splitstack(_stack, x)
local stack = _stack["stacks"]
local height = _stack["height"]
local stacks = {}
local spliteverx = math.floor(VP_lengthofdict(stack)/x)
local ind = 0
local buf = {}
for i,v in pairs(stack) do
if ind == spliteverx then
ind = 0
table.insert(stacks, buf)
buf = {}
end
buf[i] = v
ind = ind + 1
end
table.insert(stacks, buf)
local out = {
height=height,
stacks={}
}
for _,v in pairs(stacks) do
table.insert(out["stacks"],v)
end
return out
end
--[[local function VP_inspectsplitted(stacks, dimensions) -- I will probably never finish this.
local currentselected = 1
while true do
reset() -- render
local _,y = term.getSize()
term.setCursorPos(1,y)
term.setcol(colors.yellow, colors.black)
term.write("Currentlayer: ")
term.write(tostring(currentselected))
local event = table.pack(os.pullEvent())
if event[1] == "key" then
end
end
end]]
local function VP_printstack(buf, dimensions, cx,cy,cz,direction)
reset()
move("up")
for _=1,buf["height"]-cy,1 do
move("up")
end
local ox,oz = cx,cz
cx,cz,direction = VP_moveto(cx+1,cz, cx,cz,direction)
for x=1,dimensions["x"],1 do
for z=1,dimensions["z"],1 do
local tempbuf = buf["stacks"][posasstring(x,z)]
if tempbuf then
cx,cz,direction = VP_moveto(x,z, cx,cz,direction)
for _=1,#tempbuf,1 do
move("down", true)
end
for _,v in pairs(tempbuf) do
if v then
place("down")
end
move("up", true)
end
move("up", true)
end
end
end
VP_moveto(ox,oz, cx,cz,direction)
for _=1,buf["height"]+1,1 do
move("down")
end
center(direction, 0)
return cx,cz,direction
end
local function VP_calccost(stacks, height,sx,sz) -- calculate needed blocks
local cost = 0
for cx=1,sx,1 do
for cz=1,sz,1 do
local tempbuf = stacks[posasstring(cx,cz)]
if tempbuf then
for ind=1,height,1 do
if tempbuf[ind] then cost = cost + 1 end
end
end
end
end
return cost
end
local function VP_selectpos(design,dimensions,msg, cx,cz)
cx,cz = cx or 0, cz or 0
local camx,camz = cx,cz
while true do
render(design,{}, camx,1,camz, camx,camz, dimensions["x"],dimensions["z"], {1,4})
term.setCursorPos(1,1)
term.write(msg)
local _,y = term.getSize()
term.setCursorPos(1,y)
term.write("x: ")
term.write(tostring(camx))
term.write(" z: ")
term.write(tostring(camz))
local _,key = os.pullEvent("key")
key = keys.getName(key)
if key == "w" then
camz = camz - 1
end
if key == "s" then
camz = camz + 1
end
if key == "a" then
camx = camx - 1
end
if key == "d" then
camx = camx + 1
end
if key == "enter" then
break
end
end
return camx,camz
end
local function expwarn()
reset()
term.write("This mode is experimental! Be cautious!")
incline()
term.write("Enter to continue.")
read("")
end
local function randomstr(length)
local possible = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
local out = ""
for _=1,length,1 do
local ind = math.random(#possible)
out = out .. string.sub(possible, ind, ind)
end
return out
end
while true do
integritycheck()
local action = selopt({
"New Design",
"Print Design",
"VPrint Design",
"Join VPrint",
"Update",
}, "Select Action")
if action == 1 then
newdesign()
end
if action == 2 then
reset()
for _,v in pairs(fs.list("designs")) do
term.write(v)
incline()
end
write("Enter name: ")
local name = read()
if not fs.exists("designs/"..name) or name == "" then
printError("Design not found!")
else
local buf,dimensions = load(name)
write("Calculating fuel cost...")
local cost = dimensions["x"]*dimensions["z"]*(dimensions["y"]*4-1)
print(tostring(turtle.getFuelLevel()).."/"..tostring(cost))
if turtle.getFuelLevel() < cost then
write("WARNING: Not enough fuel! Continue anyway? y/n: ")
while true do
local ans = read("")
if ans == "y" then
printdes(buf, dimensions)
break
elseif ans == "n" then break end
end
else
printdes(buf, dimensions)
end
end
end
if action == 3 then
expwarn()
peripheral.find("modem", rednet.open)
reset()
for _,v in pairs(fs.list("designs")) do
term.write(v)
incline()
end
write("Enter name: ")
local name = read()
if not fs.exists("designs/"..name) or name == "" then
printError("Design not found!")
else
local buf,dimensions = load(name)
local stacks = VP_createstack(buf, dimensions)
local height = stacks["height"]
print("Stacks created.")
local code = randomstr(5)
print("Pair code: '"..code.."'")
write("Enter amount of partaking turtles: ")
local expam = tonumber(read())
write("Press enter to send pair request.")
read("")
rednet.broadcast({
code=code,
}, "HB_vprint_pair")
print("Sent. awaiting pair accepts.")
local accepted = {}
while #accepted < expam do
local id,msg = rednet.receive("HB_vprint_pairespond")
if msg["code"] == code then
table.insert(accepted, id)
reset()
term.write(tostring(#accepted).."/"..tostring(expam))
end
end
reset()
print("Paired. Splitting stacks and sending out...")
stacks = VP_splitstack(stacks, #accepted+1) -- plus 1 because we also build as the master turtle.
if #stacks["stacks"] ~= #accepted+1 then
printError("Internal error with VP_splitstack. It returned "..#stacks["stacks"].." stacks.")
return
end
for i,v in pairs(accepted) do
reset()
print("ID "..tostring(v).." needs "..VP_calccost(stacks["stacks"][i], stacks["height"],dimensions["x"],dimensions["z"]).." blocks.")
print("Please ensure that turtle has that many blocks and press enter to continue.")
read("")
rednet.send(v, {
stack=stacks["stacks"][i],
dimensions=dimensions,
height=height
}, "HB_vprint_pairacknowledge")
end
print("This turtle needs "..tostring(VP_calccost(stacks["stacks"][expam+1], stacks["height"],dimensions["x"],dimensions["z"])).." blocks.")
print("Please ensure that turtle has that many blocks and press enter to continue.")
read("")
local x,y = 0,0
for _,v in pairs(accepted) do
x,y = VP_selectpos(buf,dimensions,"Select position of turtle "..tostring(v), x,y)
rednet.send(v, {
cx=x,
cz=y,
}, "HB_vprint_pairpossend")
end
reset()
write("Ready to begin, press enter to continue")
read("")
print("Sending begin signal.")
for _,v in pairs(accepted) do
rednet.send(v, {}, "HB_vprint_begin")
end
local ownstack = {
stacks=stacks["stacks"][expam+1],
dimensions=dimensions,
height=height
}
VP_printstack(ownstack,dimensions, 0,0,1,0)
end
end
if action == 4 then
expwarn()
peripheral.find("modem", rednet.open)
reset()
term.write("Enter the code: ")
local code = read()
local masterid = 0
local buf = {}
local dimensions = {}
local height = 0
local cx,cz = 0,0
while true do -- await pairing request and respond
local id,request = rednet.receive("HB_vprint_pair")
if request["code"] == code then
masterid = id
print("Detected master: "..tostring(masterid))
print("Responding...")
rednet.send(masterid, {
code=code,
}, "HB_vprint_pairespond")
print("Waiting for response... ID: "..tostring(os.getComputerID()))
local id,msg = -1,{}
repeat
id,msg = rednet.receive("HB_vprint_pairacknowledge")
until id == masterid
buf = msg["stack"]
dimensions = msg["dimensions"]
height = msg["height"]
break
end
end
print("Received stacks and dimensions. ID: "..tostring(os.getComputerID()))
local id,msg = -1,"" -- wait until we get our current position
repeat
id,msg = rednet.receive("HB_vprint_pairpossend")
until id == masterid
cx,cz = msg["cx"],msg["cz"]
repeat -- wait until we can begin
id = rednet.receive("HB_vprint_begin")
until id == masterid
local ownstack = {
stacks=buf,
dimensions=dimensions,
height=height
}
VP_printstack(ownstack,dimensions, cx,0,cz,0)
end
if action == 5 then
shell.run("rm", "main.lua")
shell.run("wget", url)
return
end
end