2026-02-18 20:18:40 +01:00
|
|
|
local url = "http://justus.l--n.de:3000/JUFS/cc_housebuild/raw/branch/main/src/main.lua"
|
2026-02-14 22:07:35 +01:00
|
|
|
|
|
|
|
|
if not _G["turtle"] then
|
|
|
|
|
error("This program only runs on turtles!")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local turtle = _G["turtle"]
|
|
|
|
|
|
2026-02-14 22:24:37 +01:00
|
|
|
print("House building system")
|
|
|
|
|
print("JUFS Technologies (c) 2026 (Justus Wolff)")
|
|
|
|
|
|
2026-02-14 22:07:35 +01:00
|
|
|
print("fuel: "..tostring(turtle.getFuelLevel()).."/"..tostring(turtle.getFuelLimit()))
|
2026-02-15 12:31:55 +01:00
|
|
|
os.sleep(0.1)
|
2026-02-14 22:07:35 +01:00
|
|
|
|
2026-02-14 22:27:16 +01:00
|
|
|
function term.setcol(fc, bc)
|
|
|
|
|
term.setTextColor(fc)
|
|
|
|
|
term.setBackgroundColor(bc)
|
|
|
|
|
end
|
2026-02-14 22:24:37 +01:00
|
|
|
local function reset()
|
2026-02-14 22:28:25 +01:00
|
|
|
term.setcol(colors.white, colors.black)
|
2026-02-14 22:24:37 +01:00
|
|
|
term.clear()
|
|
|
|
|
term.setCursorPos(1,1)
|
|
|
|
|
end
|
|
|
|
|
local function incline()
|
2026-02-14 22:25:53 +01:00
|
|
|
local _,y = term.getCursorPos()
|
|
|
|
|
term.setCursorPos(1,y+1)
|
2026-02-14 22:24:37 +01:00
|
|
|
end
|
|
|
|
|
local function selopt(options, title)
|
|
|
|
|
local selected = 1
|
|
|
|
|
|
|
|
|
|
while true do
|
2026-02-14 22:26:20 +01:00
|
|
|
reset()
|
|
|
|
|
term.setcol(colors.black, colors.white)
|
|
|
|
|
term.write(title)
|
2026-02-14 22:24:37 +01:00
|
|
|
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
|
2026-02-15 10:58:55 +01:00
|
|
|
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
|
2026-02-15 12:31:55 +01:00
|
|
|
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
|
2026-02-17 21:51:11 +01:00
|
|
|
local function bufistype(buf, x,y,z, targettype)
|
2026-02-17 22:07:54 +01:00
|
|
|
if buf[posasstring(x,y,z)] == targettype then
|
|
|
|
|
return true
|
2026-02-17 22:04:52 +01:00
|
|
|
else
|
2026-02-17 22:07:54 +01:00
|
|
|
return targettype == 0 and buf[posasstring(x,y,z)] == nil
|
2026-02-17 22:04:52 +01:00
|
|
|
end
|
2026-02-17 21:51:11 +01:00
|
|
|
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)]
|
2026-02-17 22:07:54 +01:00
|
|
|
if inittype == ntype then return end -- no work needs to be done
|
2026-02-17 21:51:11 +01:00
|
|
|
|
|
|
|
|
local neighbors = fill_getneighbors(x,y,z, sx,sz, inittype,buf)
|
|
|
|
|
buf[posasstring(x,y,z)] = ntype
|
2026-02-17 21:58:22 +01:00
|
|
|
local processed = 0
|
|
|
|
|
local totalneighbors = #neighbors
|
|
|
|
|
term.setcol(colors.white, colors.black)
|
2026-02-17 21:51:11 +01:00
|
|
|
while #neighbors > 0 do
|
2026-02-17 21:58:22 +01:00
|
|
|
term.setCursorPos(1,1)
|
2026-02-17 21:58:58 +01:00
|
|
|
term.write(tostring(processed).."/"..tostring(totalneighbors))
|
2026-02-17 21:51:11 +01:00
|
|
|
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
|
2026-02-17 21:53:15 +01:00
|
|
|
table.insert(neighbors, v)
|
2026-02-17 22:01:43 +01:00
|
|
|
buf[posasstring(v[1],y,v[2])] = ntype
|
2026-02-17 21:58:22 +01:00
|
|
|
totalneighbors = totalneighbors + 1
|
2026-02-17 21:51:11 +01:00
|
|
|
end
|
2026-02-17 21:54:58 +01:00
|
|
|
buf[posasstring(cx,y,cz)] = ntype
|
2026-02-17 21:58:22 +01:00
|
|
|
processed = processed + 1
|
2026-02-17 21:51:11 +01:00
|
|
|
end
|
|
|
|
|
end
|
2026-02-15 10:58:55 +01:00
|
|
|
local function newdesign()
|
|
|
|
|
local buf = {}
|
|
|
|
|
local dimensions = {
|
|
|
|
|
x = 8,
|
|
|
|
|
z = 8,
|
|
|
|
|
y = 1
|
|
|
|
|
}
|
|
|
|
|
local currentfloor = 1
|
2026-02-15 11:29:23 +01:00
|
|
|
local camx,camy = 0,0
|
2026-02-16 20:36:34 +01:00
|
|
|
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
|
2026-02-17 21:51:11 +01:00
|
|
|
local shift = false
|
|
|
|
|
|
2026-02-15 10:58:55 +01:00
|
|
|
while true do
|
|
|
|
|
-- render buf
|
|
|
|
|
reset()
|
2026-02-15 11:29:23 +01:00
|
|
|
for x=1+camx,dimensions["x"]+camx,1 do
|
|
|
|
|
for z=1+camy,dimensions["z"]+camy,1 do
|
2026-02-15 11:39:21 +01:00
|
|
|
local currentbuf = buf[posasstring(x-camx, currentfloor, z-camy)]
|
2026-02-15 11:37:00 +01:00
|
|
|
term.setCursorPos(x, z)
|
2026-02-15 18:27:45 +01:00
|
|
|
if currentbuf == 1 then -- wall
|
2026-02-15 10:58:55 +01:00
|
|
|
term.blit(" ", colors.toBlit(colors.white), colors.toBlit(colors.white))
|
2026-02-16 20:37:52 +01:00
|
|
|
elseif currentbuf and currentbuf > 1 then -- blocks
|
2026-02-16 20:36:34 +01:00
|
|
|
renderblock(currentbuf-1)
|
|
|
|
|
--term.blit("C", colors.toBlit(colors.black), colors.toBlit(colors.red))
|
2026-02-15 18:29:12 +01:00
|
|
|
elseif currentbuf == 0 or currentbuf == nil then -- nothing
|
2026-02-17 15:00:56 +01:00
|
|
|
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
|
2026-02-15 10:58:55 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2026-02-15 11:16:07 +01:00
|
|
|
term.setcol(colors.yellow, colors.black)
|
|
|
|
|
local _,y = term.getSize()
|
2026-02-15 11:40:57 +01:00
|
|
|
term.setCursorPos(1,y-1)
|
2026-02-15 11:40:26 +01:00
|
|
|
term.write("Press Ctrl for menu. ")
|
2026-02-15 11:40:57 +01:00
|
|
|
term.setCursorPos(1,y)
|
2026-02-15 11:40:26 +01:00
|
|
|
term.write("x: "..tostring(camx))
|
|
|
|
|
term.write(" z: "..tostring(camy))
|
|
|
|
|
term.write(" floor: "..tostring(currentfloor))
|
2026-02-16 20:36:34 +01:00
|
|
|
term.write(" Block: ")
|
|
|
|
|
renderblock(blockindex)
|
2026-02-14 22:24:37 +01:00
|
|
|
|
2026-02-15 10:58:55 +01:00
|
|
|
-- user input
|
|
|
|
|
local event = table.pack(os.pullEvent())
|
2026-02-15 11:16:07 +01:00
|
|
|
if event[1] == "mouse_click" or event[1] == "mouse_drag" then
|
2026-02-17 00:50:24 +01:00
|
|
|
event[3] = event[3]-camx
|
|
|
|
|
event[4] = event[4]-camy
|
2026-02-15 11:16:07 +01:00
|
|
|
if event[3] <= dimensions["x"] and event[4] <= dimensions["z"] then
|
|
|
|
|
if event[2] == 1 then -- left button, set
|
2026-02-17 21:51:11 +01:00
|
|
|
if shift then
|
|
|
|
|
fill(1, event[3],currentfloor,event[4], buf,dimensions["x"],dimensions["z"])
|
|
|
|
|
end
|
2026-02-15 18:27:45 +01:00
|
|
|
buf[posasstring(event[3], currentfloor, event[4])] = 1
|
|
|
|
|
end
|
2026-02-16 20:36:34 +01:00
|
|
|
if event[2] == 3 then -- middle button, set special block
|
2026-02-17 21:51:11 +01:00
|
|
|
if shift then
|
|
|
|
|
fill(currentblock, event[3],currentfloor,event[4], buf,dimensions["x"],dimensions["z"])
|
|
|
|
|
end
|
2026-02-16 20:36:34 +01:00
|
|
|
buf[posasstring(event[3], currentfloor, event[4])] = currentblock
|
2026-02-15 11:16:07 +01:00
|
|
|
end
|
|
|
|
|
if event[2] == 2 then -- right button, erase
|
2026-02-17 21:51:11 +01:00
|
|
|
if shift then
|
|
|
|
|
fill(0, event[3],currentfloor,event[4], buf,dimensions["x"],dimensions["z"])
|
|
|
|
|
end
|
2026-02-15 18:27:45 +01:00
|
|
|
buf[posasstring(event[3], currentfloor, event[4])] = 0
|
2026-02-15 11:16:07 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2026-02-16 20:36:34 +01:00
|
|
|
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
|
2026-02-15 11:29:23 +01:00
|
|
|
if event[1] == "key" then
|
2026-02-17 21:51:11 +01:00
|
|
|
if keys.getName(event[2]) == "leftShift" then
|
|
|
|
|
shift = true
|
|
|
|
|
end
|
2026-02-15 11:29:23 +01:00
|
|
|
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()
|
2026-02-15 11:18:03 +01:00
|
|
|
end
|
2026-02-15 11:29:23 +01:00
|
|
|
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
|
2026-02-15 12:31:55 +01:00
|
|
|
buf,dimensions = load(name)
|
2026-02-15 11:44:07 +01:00
|
|
|
camx,camy,currentfloor = 0,0,1
|
2026-02-15 11:29:23 +01:00
|
|
|
end
|
2026-02-15 11:18:03 +01:00
|
|
|
end
|
2026-02-15 11:29:23 +01:00
|
|
|
if action == 4 then -- change X size
|
|
|
|
|
reset()
|
|
|
|
|
write("Enter new X size: ")
|
|
|
|
|
local xsize = tonumber(read())
|
|
|
|
|
dimensions["x"] = xsize
|
2026-02-15 11:16:07 +01:00
|
|
|
end
|
2026-02-15 11:29:23 +01:00
|
|
|
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
|
2026-02-15 11:34:16 +01:00
|
|
|
if keys.getName(event[2]) == "w" and camy < dimensions["z"] then -- pan up
|
2026-02-15 11:29:23 +01:00
|
|
|
camy = camy + 1
|
2026-02-15 11:21:01 +01:00
|
|
|
end
|
2026-02-15 11:41:52 +01:00
|
|
|
if keys.getName(event[2]) == "s" and camy > -dimensions["z"] then -- pan down
|
2026-02-15 11:31:05 +01:00
|
|
|
camy = camy - 1
|
2026-02-15 11:21:01 +01:00
|
|
|
end
|
2026-02-15 11:37:00 +01:00
|
|
|
if keys.getName(event[2]) == "a" and camx < dimensions["x"] then -- pan left
|
2026-02-15 11:29:23 +01:00
|
|
|
camx = camx + 1
|
2026-02-15 11:21:01 +01:00
|
|
|
end
|
2026-02-15 11:41:52 +01:00
|
|
|
if keys.getName(event[2]) == "d" and camx > -dimensions["z"] then -- pan right
|
2026-02-15 11:31:05 +01:00
|
|
|
camx = camx - 1
|
|
|
|
|
end
|
2026-02-15 10:58:55 +01:00
|
|
|
end
|
2026-02-17 21:51:11 +01:00
|
|
|
if event[1] == "key_up" then
|
|
|
|
|
if keys.getName(event[2]) == "leftShift" then shift = false end
|
|
|
|
|
end
|
2026-02-15 10:58:55 +01:00
|
|
|
end
|
|
|
|
|
end
|
2026-02-18 20:02:40 +01:00
|
|
|
local function move(direction, continousattempt)
|
2026-02-15 12:31:55 +01:00
|
|
|
if direction == "left" then
|
|
|
|
|
turtle.turnLeft()
|
2026-02-15 12:34:15 +01:00
|
|
|
return
|
2026-02-15 12:31:55 +01:00
|
|
|
end
|
|
|
|
|
if direction == "right" then
|
|
|
|
|
turtle.turnRight()
|
2026-02-15 12:34:15 +01:00
|
|
|
return
|
2026-02-15 12:31:55 +01:00
|
|
|
end
|
|
|
|
|
while true do
|
|
|
|
|
if turtle.getFuelLevel() == 0 then
|
|
|
|
|
reset()
|
|
|
|
|
print("Out of fuel! Please insert fuel into current slot.")
|
|
|
|
|
while true do
|
|
|
|
|
local suc = turtle.refuel(64)
|
|
|
|
|
if suc then
|
|
|
|
|
print("Refuelled. Press enter to continue.")
|
|
|
|
|
read("")
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
os.sleep(1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
local suc,reason = turtle[direction]()
|
2026-02-18 20:02:40 +01:00
|
|
|
if not suc and not continousattempt then
|
2026-02-15 12:31:55 +01:00
|
|
|
printError(reason)
|
|
|
|
|
print("Resolve the error and press enter to continue.")
|
|
|
|
|
read("")
|
2026-02-18 20:02:40 +01:00
|
|
|
elseif suc then
|
2026-02-15 12:31:55 +01:00
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
local function place(direction)
|
|
|
|
|
local func = turtle.place
|
2026-02-15 19:38:34 +01:00
|
|
|
local cfunc = turtle.compare
|
2026-02-15 12:31:55 +01:00
|
|
|
if direction == "down" then
|
|
|
|
|
func = turtle.placeDown
|
2026-02-15 19:38:34 +01:00
|
|
|
cfunc = turtle.compareDown
|
2026-02-15 12:31:55 +01:00
|
|
|
end
|
|
|
|
|
if direction == "up" then
|
|
|
|
|
func = turtle.placeUp
|
2026-02-15 19:38:34 +01:00
|
|
|
cfunc = turtle.compareUp
|
2026-02-15 12:31:55 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
while true do
|
|
|
|
|
local suc = func()
|
|
|
|
|
if not suc then -- next slot
|
2026-02-15 20:00:35 +01:00
|
|
|
if cfunc() and turtle.getItemDetail(turtle.getSelectedSlot()) ~= nil then return end
|
2026-02-15 12:31:55 +01:00
|
|
|
local current = turtle.getSelectedSlot()
|
|
|
|
|
if current == 16 then
|
|
|
|
|
turtle.select(1)
|
|
|
|
|
else
|
|
|
|
|
turtle.select(current+1)
|
|
|
|
|
end
|
2026-02-15 12:33:17 +01:00
|
|
|
else break end
|
2026-02-15 12:31:55 +01:00
|
|
|
os.sleep(0) -- yield
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
local function placebuf(buf, x, y, z)
|
2026-02-15 18:27:45 +01:00
|
|
|
if buf[posasstring(x,y,z)] == 1 then
|
2026-02-15 12:31:55 +01:00
|
|
|
place("down")
|
|
|
|
|
end
|
|
|
|
|
end
|
2026-02-17 22:25:20 +01:00
|
|
|
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
|
2026-02-18 18:52:49 +01:00
|
|
|
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
|
2026-02-17 22:25:20 +01:00
|
|
|
local function getnearestunplaced(buf, pbuf, cx,cy,cz,clayer, sx,sz, direction)
|
2026-02-15 19:32:16 +01:00
|
|
|
local distance = math.huge
|
|
|
|
|
local selected = nil
|
|
|
|
|
|
|
|
|
|
for x=1,sx,1 do
|
|
|
|
|
for y=1,sz,1 do
|
2026-02-17 22:25:20 +01:00
|
|
|
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
|
|
|
|
|
|
2026-02-15 19:32:16 +01:00
|
|
|
local needplace = buf[posasstring(x,cy,y)]
|
|
|
|
|
if pbuf[posasstring(x,cy,y)] then needplace = 0 end -- already placed
|
2026-02-18 18:52:49 +01:00
|
|
|
needplace = needstobeplaced(needplace, clayer)
|
2026-02-15 19:32:16 +01:00
|
|
|
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)
|
2026-02-17 22:25:20 +01:00
|
|
|
cd = cd + extracost
|
2026-02-15 19:32:16 +01:00
|
|
|
if cd < distance then
|
|
|
|
|
distance = cd
|
|
|
|
|
selected = {x,y}
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return selected
|
|
|
|
|
end
|
2026-02-15 19:43:14 +01:00
|
|
|
local function center(direction, wanted)
|
2026-02-15 19:48:45 +01:00
|
|
|
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
|
2026-02-15 19:43:14 +01:00
|
|
|
end
|
|
|
|
|
local function moveto(x,y,cx,cz,direction)
|
2026-02-15 20:08:23 +01:00
|
|
|
while x ~= cx do
|
2026-02-15 19:56:58 +01:00
|
|
|
if cx < x then -- x
|
2026-02-15 19:43:14 +01:00
|
|
|
center(direction)
|
2026-02-15 19:58:12 +01:00
|
|
|
direction = 0
|
2026-02-15 19:32:16 +01:00
|
|
|
cx = cx + 1
|
|
|
|
|
move("forward")
|
|
|
|
|
end
|
2026-02-15 19:56:58 +01:00
|
|
|
if cx > x then
|
2026-02-15 19:43:14 +01:00
|
|
|
center(direction)
|
2026-02-15 19:58:12 +01:00
|
|
|
direction = 0
|
2026-02-15 19:32:16 +01:00
|
|
|
cx = cx - 1
|
|
|
|
|
move("back")
|
|
|
|
|
end
|
2026-02-15 20:08:23 +01:00
|
|
|
end
|
|
|
|
|
while y ~= cz do
|
2026-02-15 19:32:16 +01:00
|
|
|
if y > cz then -- z
|
2026-02-15 19:48:45 +01:00
|
|
|
if center(direction, 1) then move("right") end
|
2026-02-15 19:32:16 +01:00
|
|
|
cz = cz + 1
|
|
|
|
|
move("forward")
|
|
|
|
|
direction = 1
|
|
|
|
|
end
|
|
|
|
|
if y < cz then
|
2026-02-15 19:48:45 +01:00
|
|
|
if center(direction, -1) then move("left") end
|
2026-02-15 19:32:16 +01:00
|
|
|
cz = cz - 1
|
|
|
|
|
move("forward")
|
|
|
|
|
direction = -1
|
|
|
|
|
end
|
|
|
|
|
end
|
2026-02-15 19:43:14 +01:00
|
|
|
return cx,cz,direction
|
2026-02-15 19:32:16 +01:00
|
|
|
end
|
2026-02-16 19:37:25 +01:00
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-17 01:11:27 +01:00
|
|
|
local tsx,tsy = term.getSize()
|
2026-02-17 02:08:27 +01:00
|
|
|
local camx,camy = cx-(tsx/2),cz-(tsy/2)
|
2026-02-17 01:11:27 +01:00
|
|
|
|
2026-02-16 19:37:25 +01:00
|
|
|
reset()
|
2026-02-17 02:07:19 +01:00
|
|
|
for x=1,sx,1 do
|
|
|
|
|
for z=1,sz,1 do
|
2026-02-17 02:12:38 +01:00
|
|
|
local currentbuf = pbuf[posasstring(x, cy, z)]
|
2026-02-17 02:10:00 +01:00
|
|
|
term.setCursorPos(x-camx, z-camy)
|
2026-02-16 19:37:25 +01:00
|
|
|
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
|
2026-02-17 02:10:00 +01:00
|
|
|
term.setCursorPos(cx-camx,cz-camy)
|
2026-02-16 19:37:25 +01:00
|
|
|
term.blit(" ", colors.toBlit(colors.red), colors.toBlit(colors.red))
|
2026-02-17 02:10:00 +01:00
|
|
|
term.setCursorPos(tx-camx,tz-camy)
|
2026-02-16 19:37:25 +01:00
|
|
|
term.blit(" ", colors.toBlit(colors.lime), colors.toBlit(colors.lime))
|
|
|
|
|
end
|
2026-02-15 12:31:55 +01:00
|
|
|
local function printdes(buf, dimensions)
|
|
|
|
|
move("up")
|
|
|
|
|
move("forward")
|
|
|
|
|
|
2026-02-15 19:32:16 +01:00
|
|
|
local cx = 1
|
|
|
|
|
local cz = 1
|
2026-02-15 19:43:14 +01:00
|
|
|
local direction = 0
|
2026-02-15 12:31:55 +01:00
|
|
|
for cy=1,dimensions["y"],1 do
|
2026-02-16 20:47:21 +01:00
|
|
|
local setlists = {
|
|
|
|
|
{1,4},
|
|
|
|
|
{1},
|
|
|
|
|
{1,3,4},
|
|
|
|
|
}
|
2026-02-16 20:36:34 +01:00
|
|
|
for clayer=1,3,1 do -- build walls
|
2026-02-15 19:32:16 +01:00
|
|
|
local pbuf = {}
|
|
|
|
|
while true do
|
2026-02-17 22:26:11 +01:00
|
|
|
local target = getnearestunplaced(buf, pbuf, cx,cy,cz,clayer, dimensions["x"],dimensions["z"], direction)
|
2026-02-15 19:32:16 +01:00
|
|
|
if not target then break end
|
2026-02-15 19:56:58 +01:00
|
|
|
|
2026-02-16 20:47:21 +01:00
|
|
|
render(buf, pbuf, cx,cy,cz, target[1],target[2], dimensions["x"],dimensions["z"], setlists[clayer])
|
2026-02-15 19:56:58 +01:00
|
|
|
|
2026-02-15 19:58:44 +01:00
|
|
|
--read("")
|
2026-02-15 19:56:58 +01:00
|
|
|
|
2026-02-15 19:44:25 +01:00
|
|
|
cx,cz,direction = moveto(target[1],target[2],cx,cz,direction)
|
2026-02-15 19:32:16 +01:00
|
|
|
place("down")
|
|
|
|
|
pbuf[posasstring(cx,cy,cz)] = true
|
|
|
|
|
end
|
|
|
|
|
move("up")
|
2026-02-15 12:40:44 +01:00
|
|
|
end
|
|
|
|
|
-- build ceiling/floor
|
2026-02-15 20:08:23 +01:00
|
|
|
local pbuf = {}
|
|
|
|
|
local cbuf = {}
|
2026-02-15 19:32:16 +01:00
|
|
|
for _cz=1,dimensions["z"],1 do
|
|
|
|
|
for _cx=1,dimensions["x"],1 do
|
|
|
|
|
if buf[posasstring(_cx,cy,_cz)] ~= 2 then
|
2026-02-15 20:08:23 +01:00
|
|
|
cbuf[posasstring(_cx,0,_cz)] = 1
|
|
|
|
|
else
|
|
|
|
|
cbuf[posasstring(_cx,0,_cz)] = 0
|
2026-02-15 18:27:45 +01:00
|
|
|
end
|
2026-02-15 12:31:55 +01:00
|
|
|
end
|
|
|
|
|
end
|
2026-02-15 20:08:23 +01:00
|
|
|
while true do
|
2026-02-17 22:26:11 +01:00
|
|
|
local target = getnearestunplaced(cbuf, pbuf, cx,0,cz,0, dimensions["x"],dimensions["z"], direction)
|
2026-02-15 20:08:23 +01:00
|
|
|
if not target then break end
|
|
|
|
|
|
2026-02-16 19:37:25 +01:00
|
|
|
render(cbuf, pbuf, cx,0,cz, target[1],target[2], dimensions["x"],dimensions["z"], {1})
|
2026-02-15 20:08:23 +01:00
|
|
|
|
|
|
|
|
cx,cz,direction = moveto(target[1],target[2],cx,cz,direction)
|
|
|
|
|
place("down")
|
2026-02-15 20:11:07 +01:00
|
|
|
pbuf[posasstring(cx,0,cz)] = true
|
2026-02-15 20:08:23 +01:00
|
|
|
end
|
2026-02-15 12:31:55 +01:00
|
|
|
-- return to standard pos but +1 to y
|
2026-02-15 19:44:25 +01:00
|
|
|
cx,cz,direction = moveto(1,1,cx,cz,direction)
|
2026-02-15 12:31:55 +01:00
|
|
|
move("up")
|
|
|
|
|
end
|
2026-02-16 20:54:42 +01:00
|
|
|
cx,cz,direction = moveto(0,1, cx,cz, direction)
|
2026-02-16 20:49:36 +01:00
|
|
|
for _=1,dimensions["y"]*(4)+1,1 do -- go back to starting position
|
|
|
|
|
move("down")
|
|
|
|
|
end
|
2026-02-15 19:43:14 +01:00
|
|
|
center(direction)
|
2026-02-15 12:31:55 +01:00
|
|
|
end
|
2026-02-15 10:58:55 +01:00
|
|
|
|
2026-02-18 18:52:49 +01:00
|
|
|
-- vertical stack printing
|
2026-02-18 20:02:40 +01:00
|
|
|
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
|
2026-02-18 20:09:20 +01:00
|
|
|
while z ~= cz do
|
|
|
|
|
if z > cz then -- z
|
2026-02-18 20:02:40 +01:00
|
|
|
if center(direction, 1) then move("right") end
|
|
|
|
|
y = VP_movetoy(y, 3)
|
|
|
|
|
cz = cz + 1
|
|
|
|
|
move("forward", true)
|
|
|
|
|
direction = 1
|
|
|
|
|
end
|
2026-02-18 20:09:20 +01:00
|
|
|
if z < cz then
|
2026-02-18 20:02:40 +01:00
|
|
|
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
|
2026-02-22 20:16:58 +01:00
|
|
|
local function VP_optimizestack(target)
|
2026-02-18 18:52:49 +01:00
|
|
|
-- go from top to bottom and erase false entries until we encounter a true one.
|
|
|
|
|
local index = #target
|
|
|
|
|
while #target > 0 do
|
|
|
|
|
if target[index] then break else
|
|
|
|
|
table.remove(target, index)
|
|
|
|
|
index = index - 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 = {}
|
2026-02-22 20:19:54 +01:00
|
|
|
for y=1,dimensions["y"],1 do -- for each y dimension
|
2026-02-18 18:52:49 +01:00
|
|
|
local placecode = buf[posasstring(x,y,z)]
|
|
|
|
|
for layer=1,3,1 do -- layers
|
|
|
|
|
table.insert(tempbuf, needstobeplaced(placecode, layer))
|
|
|
|
|
end
|
|
|
|
|
-- ceiling
|
2026-02-22 20:16:58 +01:00
|
|
|
table.insert(tempbuf, buf[posasstring(x,y,z)] ~= 2)
|
2026-02-18 18:52:49 +01:00
|
|
|
end
|
2026-02-22 20:16:58 +01:00
|
|
|
VP_optimizestack(tempbuf)
|
2026-02-18 18:52:49 +01:00
|
|
|
|
2026-02-22 20:23:39 +01:00
|
|
|
if #tempbuf > 0 then
|
|
|
|
|
out[posasstring(x,z)] = tempbuf
|
|
|
|
|
end
|
2026-02-18 18:52:49 +01:00
|
|
|
end
|
|
|
|
|
end
|
2026-02-22 20:23:39 +01:00
|
|
|
|
|
|
|
|
|
2026-02-18 18:52:49 +01:00
|
|
|
fout["stacks"] = out
|
|
|
|
|
return fout
|
|
|
|
|
end
|
2026-02-22 20:23:39 +01:00
|
|
|
local function VP_lengthofdict(target)
|
|
|
|
|
local out = 0
|
|
|
|
|
for _,v in pairs(target) do out = out + 1 end
|
|
|
|
|
return out
|
|
|
|
|
end
|
2026-02-18 18:52:49 +01:00
|
|
|
local function VP_splitstack(_stack, x)
|
|
|
|
|
local stack = _stack["stacks"]
|
|
|
|
|
local dimensions = _stack["dimensions"]
|
2026-02-22 20:24:31 +01:00
|
|
|
local sx = dimensions["x"]
|
|
|
|
|
local sz = dimensions["z"]
|
2026-02-18 18:52:49 +01:00
|
|
|
local height = _stack["height"]
|
|
|
|
|
local stacks = {}
|
2026-02-22 20:57:59 +01:00
|
|
|
local spliteverx = math.floor(VP_lengthofdict(stack)/x)
|
|
|
|
|
local ind = 0
|
|
|
|
|
local buf = {}
|
|
|
|
|
for i,v in pairs(stack) do
|
|
|
|
|
if ind == spliteverx then
|
2026-02-22 21:11:53 +01:00
|
|
|
ind = 0
|
2026-02-18 18:52:49 +01:00
|
|
|
table.insert(stacks, buf)
|
2026-02-22 20:57:59 +01:00
|
|
|
buf = {}
|
2026-02-18 18:52:49 +01:00
|
|
|
end
|
2026-02-22 20:57:59 +01:00
|
|
|
buf[i] = v
|
|
|
|
|
ind = ind + 1
|
2026-02-18 18:52:49 +01:00
|
|
|
end
|
2026-02-22 21:00:34 +01:00
|
|
|
if #buf > 0 then table.insert(stacks, buf) end
|
2026-02-18 18:52:49 +01:00
|
|
|
|
2026-02-19 19:56:23 +01:00
|
|
|
local out = {
|
2026-02-19 20:03:27 +01:00
|
|
|
height=height,
|
|
|
|
|
stacks={}
|
2026-02-19 19:56:23 +01:00
|
|
|
}
|
2026-02-18 18:52:49 +01:00
|
|
|
for _,v in pairs(stacks) do
|
2026-02-19 20:03:27 +01:00
|
|
|
table.insert(out["stacks"],v)
|
2026-02-18 18:52:49 +01:00
|
|
|
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]]
|
2026-02-19 19:56:23 +01:00
|
|
|
local function VP_printstack(buf, dimensions, cx,cy,cz,direction)
|
2026-02-18 20:02:40 +01:00
|
|
|
reset()
|
|
|
|
|
move("up")
|
2026-02-22 20:41:06 +01:00
|
|
|
for _=1,buf["height"]-cy,1 do
|
|
|
|
|
move("up")
|
2026-02-18 20:02:40 +01:00
|
|
|
end
|
2026-02-18 20:15:57 +01:00
|
|
|
local ox,oz = cx,cz
|
2026-02-18 20:22:06 +01:00
|
|
|
cx,cz,direction = VP_moveto(cx+1,cz, cx,cz,direction)
|
2026-02-18 18:52:49 +01:00
|
|
|
|
2026-02-18 20:02:40 +01:00
|
|
|
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,buf["height"],1 do
|
|
|
|
|
move("down")
|
|
|
|
|
end
|
|
|
|
|
for _,v in pairs(tempbuf) do
|
|
|
|
|
if v then
|
|
|
|
|
place("down")
|
|
|
|
|
end
|
|
|
|
|
move("up")
|
|
|
|
|
end
|
2026-02-18 20:12:23 +01:00
|
|
|
move("up")
|
2026-02-18 20:02:40 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2026-02-18 20:18:40 +01:00
|
|
|
VP_moveto(ox,oz, cx,cz,direction)
|
2026-02-18 20:02:40 +01:00
|
|
|
for _=1,buf["height"],1 do
|
|
|
|
|
move("down")
|
|
|
|
|
end
|
2026-02-22 20:57:59 +01:00
|
|
|
center(direction, 0)
|
2026-02-18 20:02:40 +01:00
|
|
|
return cx,cz,direction
|
2026-02-18 18:52:49 +01:00
|
|
|
end
|
2026-02-19 19:56:23 +01:00
|
|
|
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
|
2026-02-18 18:52:49 +01:00
|
|
|
|
2026-02-15 10:58:55 +01:00
|
|
|
while true do
|
|
|
|
|
integritycheck()
|
|
|
|
|
local action = selopt({
|
|
|
|
|
"New Design",
|
2026-02-18 20:02:40 +01:00
|
|
|
"Print Design",
|
|
|
|
|
"VPrint Design",
|
2026-02-19 19:56:23 +01:00
|
|
|
"Join VPrint",
|
2026-02-19 19:57:53 +01:00
|
|
|
"Update",
|
2026-02-15 10:58:55 +01:00
|
|
|
}, "Select Action")
|
|
|
|
|
|
|
|
|
|
if action == 1 then
|
|
|
|
|
newdesign()
|
|
|
|
|
end
|
2026-02-15 12:31:55 +01:00
|
|
|
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
|
2026-02-18 20:02:40 +01:00
|
|
|
if action == 3 then
|
2026-02-19 19:56:23 +01:00
|
|
|
expwarn()
|
2026-02-18 20:02:40 +01:00
|
|
|
|
2026-02-19 20:00:05 +01:00
|
|
|
peripheral.find("modem", rednet.open)
|
2026-02-18 20:02:40 +01:00
|
|
|
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)
|
2026-02-22 20:30:47 +01:00
|
|
|
local height = stacks["height"]
|
2026-02-19 19:56:23 +01:00
|
|
|
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...")
|
2026-02-19 20:06:18 +01:00
|
|
|
stacks = VP_splitstack(stacks, #accepted+1) -- plus 1 because we also build as the master turtle.
|
|
|
|
|
if #stacks["stacks"] ~= #accepted+1 then
|
2026-02-19 20:07:54 +01:00
|
|
|
printError("Internal error with VP_splitstack. It returned "..#stacks["stacks"].." stacks.")
|
2026-02-19 20:06:18 +01:00
|
|
|
return
|
|
|
|
|
end
|
2026-02-19 19:56:23 +01:00
|
|
|
for i,v in pairs(accepted) do
|
|
|
|
|
reset()
|
2026-02-19 20:03:27 +01:00
|
|
|
print("ID "..tostring(v).." needs "..VP_calccost(stacks["stacks"][i], stacks["height"],dimensions["x"],dimensions["z"]).." blocks.")
|
2026-02-19 19:56:23 +01:00
|
|
|
print("Please ensure that turtle has that many blocks and press enter to continue.")
|
|
|
|
|
read("")
|
|
|
|
|
rednet.send(v, {
|
2026-02-19 20:03:27 +01:00
|
|
|
stack=stacks["stacks"][i],
|
2026-02-22 20:35:26 +01:00
|
|
|
dimensions=dimensions,
|
|
|
|
|
height=height
|
2026-02-19 19:56:23 +01:00
|
|
|
}, "HB_vprint_pairacknowledge")
|
|
|
|
|
end
|
2026-02-22 20:33:43 +01:00
|
|
|
|
2026-02-22 20:38:25 +01:00
|
|
|
print("This turtle needs "..tostring(VP_calccost(stacks["stacks"][expam+1], stacks["height"],dimensions["x"],dimensions["z"])).." blocks.")
|
2026-02-22 20:33:43 +01:00
|
|
|
print("Please ensure that turtle has that many blocks and press enter to continue.")
|
|
|
|
|
read("")
|
|
|
|
|
|
2026-02-19 19:56:23 +01:00
|
|
|
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,
|
2026-02-22 20:41:06 +01:00
|
|
|
cz=y,
|
2026-02-19 19:56:23 +01:00
|
|
|
}, "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
|
2026-02-18 20:09:20 +01:00
|
|
|
|
2026-02-22 20:30:47 +01:00
|
|
|
local ownstack = {
|
2026-02-22 20:37:07 +01:00
|
|
|
stacks=stacks["stacks"][expam+1],
|
2026-02-22 20:30:47 +01:00
|
|
|
dimensions=dimensions,
|
|
|
|
|
height=height
|
|
|
|
|
}
|
2026-02-22 20:47:47 +01:00
|
|
|
VP_printstack(ownstack,dimensions, 0,0,1,0)
|
2026-02-19 19:56:23 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if action == 4 then
|
|
|
|
|
expwarn()
|
|
|
|
|
|
2026-02-19 20:00:05 +01:00
|
|
|
peripheral.find("modem", rednet.open)
|
2026-02-19 19:56:23 +01:00
|
|
|
reset()
|
|
|
|
|
term.write("Enter the code: ")
|
|
|
|
|
local code = read()
|
|
|
|
|
local masterid = 0
|
|
|
|
|
local buf = {}
|
|
|
|
|
local dimensions = {}
|
2026-02-22 20:30:47 +01:00
|
|
|
local height = 0
|
2026-02-19 19:56:23 +01:00
|
|
|
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")
|
2026-02-22 20:27:36 +01:00
|
|
|
print("Waiting for response... ID: "..tostring(os.getComputerID()))
|
2026-02-19 19:56:23 +01:00
|
|
|
local id,msg = -1,{}
|
|
|
|
|
repeat
|
|
|
|
|
id,msg = rednet.receive("HB_vprint_pairacknowledge")
|
|
|
|
|
until id == masterid
|
|
|
|
|
buf = msg["stack"]
|
|
|
|
|
dimensions = msg["dimensions"]
|
2026-02-22 20:30:47 +01:00
|
|
|
height = msg["height"]
|
2026-02-19 19:56:23 +01:00
|
|
|
break
|
|
|
|
|
end
|
2026-02-18 20:02:40 +01:00
|
|
|
end
|
2026-02-19 19:56:23 +01:00
|
|
|
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
|
2026-02-22 20:30:47 +01:00
|
|
|
|
|
|
|
|
local ownstack = {
|
|
|
|
|
stacks=buf,
|
|
|
|
|
dimensions=dimensions,
|
|
|
|
|
height=height
|
|
|
|
|
}
|
2026-02-22 20:41:06 +01:00
|
|
|
VP_printstack(ownstack,dimensions, cx,0,cz,0)
|
2026-02-18 20:02:40 +01:00
|
|
|
end
|
2026-02-19 19:57:53 +01:00
|
|
|
if action == 5 then
|
|
|
|
|
shell.run("rm", "main.lua")
|
|
|
|
|
shell.run("wget", url)
|
|
|
|
|
return
|
|
|
|
|
end
|
2026-02-15 10:58:55 +01:00
|
|
|
end
|
2026-02-14 22:24:37 +01:00
|
|
|
|