Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- --------------------------------------------------------------------------------------------------------------
- | Turtle Architect |
- | by CometWolf |
- --------------------------------------------------------------------------------------------------------------
- --------------------------------------------------------------------------------------------------------------
- | Program tables |
- --------------------------------------------------------------------------------------------------------------
- --]]
- local env = { --new enviroment
- ["tFile"] = {
- --file path table
- ["program"] = shell.getRunningProgram(), --must be done prior to changing enviroment
- ["cTurtle"] = "/cTurtle", --cTurtle API,downloaded automatically if missing
- ["ongoingBuild"] = "/ArchitectOngoingBuild" --Info file for the currently ongoing build
- }
- }
- setmetatable(env, {__index = getfenv()}) --inherit global
- setfenv(1, env) --set it
- local tArg = {...} --store program arguments
- local tTimer = {
- --timer settings table, change timers here
- ["rednet"] = 60, --time before sending location info over rednet when in need of materials
- ["enderChest"] = 120 --time between ender chest checks when out of materials
- }
- local tColors = {
- --color table, change color settings here
- ["menuBar"] = colors.blue, --top menu bar
- ["menuButton"] = colors.lightBlue, -- menu button on the left
- ["menuText"] = colors.white, -- text on the menu button
- ["menuDropDownPri"] = colors.lightBlue, --primary drop down menu color
- ["menuDropDownSec"] = colors.cyan, --secondary drop down menu color
- ["contextMenuText"] = colors.white, -- right click menu text
- ["contextMenuPri"] = colors.lightBlue, --right click menu primary
- ["contextMenuSec"] = colors.cyan, -- right click menu secondary
- ["box"] = colors.blue, -- info, choice and input boxes color
- ["boxBorder"] = colors.lightBlue, -- box borders
- ["boxText"] = colors.yellow, --box text
- ["boxButton"] = colors.cyan, -- box buttons
- ["boxButtonText"] = colors.yellow, -- buttons text in boxes
- ["inputText"] = colors.white, --input text
- ["inputBackground"] = colors.black, --input field
- ["infoText"] = colors.white, --box text
- ["gridBorder"] = colors.blue, --gridMode bottm and right borde ron screen
- ["gridBorderText"] = colors.white, -- grideMode border text
- ["gridBackground"] = colors.white, -- grid mode background
- ["gridBackgroundText"] = colors.blue, -- grid markers
- ["backgroundLayer"] = colors.gray, -- background layer
- ["selector"] = colors.lightGray, -- selector tool selection color
- ["builtMark"] = colors.white, -- built render mode mark
- }
- --numerical color table for rendering canvas colors
- tColorNums = {
- a = 2 ^ 1,
- b = 2 ^ 2,
- c = 2 ^ 3,
- d = 2 ^ 4,
- e = 2 ^ 5,
- f = 2 ^ 6,
- g = 2 ^ 7,
- h = 2 ^ 8,
- i = 2 ^ 9,
- j = 2 ^ 10,
- k = 2 ^ 11,
- l = 2 ^ 12,
- m = 2 ^ 13,
- n = 2 ^ 14,
- o = 2 ^ 15,
- }
- tColorNumsRev = {}
- for k,v in pairs(tColorNums) do
- tColorNumsRev[v] = k
- end
- for k,v in pairs(tColorNums) do
- tColorNums[k:upper()] = v
- end
- tColorNums[" "] = 1 --blank
- tColorNumsRev[1] = " "
- tColorNums.x = 1 --break
- tColorNums.X = 1
- local built = "%u" --uppercase pattern, marks built blocks
- local unbuilt = "%l" --lowercase pattern, marks unbuilt blocks
- -- color strings indexed by color values, reverse of the colors table pretty much
- local tColorString = {}
- --contains what slots to use for what colors when building
- local tColorSlots = {}
- --somewhat relevant bits of strings, for simplified changes
- local tText = {
- ["menuButton"] = "Menu"
- }
- --blueprint table, holds current blueprint
- local tBlueprint = {}
- --contains ongoing build data
- local tOngoing = {}
- --contains build starting point
- local tOrigin = {}
- tPaste = {
- --pastebin codes and functions
- ["program"] = "Kt4D8uyE",
- ["cTurtle"] = "JRPN0P8x",
- ["key"] = "0ec2eb25b6166c0c27a394ae118ad829", -- pastbin dev key, cc default
- ["get"] = function(code,file,blueprint) --downloads files pastebin
- local response = http.get("http://pastebin.com/raw.php?i="..code)
- local paste, tRetBlueprint,tRetColorSlots,tRetOrigin
- if response then
- --sucesss
- if blueprint then
- if response.readLine() == "Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program then
- tRetBlueprint = {}
- local line = response.readLine()
- while line:match"Layer %d+" do
- local layer = tonumber(line:match"%d+")
- tRetBlueprint[layer] = {}
- line = response.readLine()
- while line:match"X%d+" do
- local x = tonumber(line:match"X(%d+)")
- tRetBlueprint[layer][x] = {}
- for block in line:gmatch" (%d+)" do
- table.insert(tRetBlueprint[layer][x],tonumber(block))
- end
- line = response.readLine()
- end
- end
- if line:match"Color slots table:" then
- tRetColors = textutils.unserialize(response.readLine())
- line = response.readLine() or ""
- end
- if line:match"Build origin data:" then
- tRetOrigin = textutils.unserialize(response.readLine())
- end
- return tRetBlueprint, tRetColors or {},tRetOrigin or {}
- else
- return false
- end
- end
- paste = response.readAll()
- response.close()
- if file then
- --save to file
- local file = fs.open(file,"w")
- file.writeLine(paste)
- file.close()
- return true
- end
- --save to variable
- return paste
- else
- --failure
- return false
- end
- end,
- --note that the put function is just a slightly modified version of the original.
- ["put"] = function(file,name) --uploads files to pastebin
- local upload
- name = name or "Untitled"
- if type(file) == "string" then
- --local file
- file = fs.open("file","r")
- upload = file.readAll()
- file.close()
- elseif type(file) == "table" then
- --current blueprint
- upload = "Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program
- for layer=1,#tBlueprint do
- upload = upload.."\nLayer "..layer.." :"
- for x=1,#tBlueprint[layer] do
- local line = "X"..x..string.rep(" ",#string.format(#tBlueprint[layer])-#string.format(x))..": "
- for z=1,#tBlueprint[layer][x] do
- local block = tBlueprint[layer][x][z] or "0"
- line = line..block..string.rep(" ",3-#string.format(block))
- end
- upload = upload.."\n"..line
- end
- end
- if tColorSlots then
- upload = upload.."\nColor slots table:\n"..textutils.serialize(tColorSlots)
- end
- if tOrigin then
- upload = upload.."\nBuild origin data:\n"..textutils.serialize(tOrigin)
- end
- end
- local key = tPaste.key
- local response = http.post(
- "http://pastebin.com/api/api_post.php",
- "api_option=paste&"..
- "api_dev_key="..key.."&"..
- "api_paste_format=text&"..
- "api_paste_name="..textutils.urlEncode(name).."&"..
- "api_paste_code="..textutils.urlEncode(upload)
- )
- if response then
- --sucess
- local sResponse = response.readAll()
- response.close()
- local sCode = string.match( sResponse, "[^/]+$" )
- return sResponse, sCode
- else
- --failure
- return false
- end
- end
- }
- local tTool = {
- --tool table, tool info for the respective mouse buttons
- [1] = { --left mouse tool
- ["tool"] = "Brush",
- ["size"] = 1,
- ["color"] = "o" --black
- },
- [2] = { --right mouse tool
- ["tool"] = "Brush",
- ["size"] = 1,
- ["color"] = " " --white
- },
- ["overwrite"] = true, --overwrite mode
- ["built"] = false, --built mode
- ["selector"] = { --selector tool info
- ["enabled"] = false --wether to render the selection or not
- },
- ["circle"] = {
- [1] = {},
- [2] = {}
- }
- }
- local tScroll = {
- --scroll table, holds current veiwing area info
- ["x"] = { --left right
- ["value"] = 0
- },
- ["y"] = { --up down
- ["value"] = 0
- },
- ["layer"] = 1, --layer
- }
- local tTerm = {}
- --terminal sizes table, to make my life easier
- tTerm.x,tTerm.y = term.getSize()
- tTerm.xMid = math.ceil(tTerm.x/2)
- tTerm.yMid = math.ceil(tTerm.y/2)
- tTerm.xCanvas = tTerm.x --total x veiwing area
- tTerm.zCanvas = tTerm.y-1 --total y veiwing area, accounts for the menubar on top
- tTerm.grid = false --grid mode
- tTerm.built = false -- built render mode
- tTerm.isColor = term.isColor() --color support
- tMon = "" -- monitor table
- local paintutils = {
- -- custom paintutils, to simplify monitor usage
- ["drawPixel"] = function(xPos,yPos,color,monitor)
- if monitor then
- --monitors
- for i=1,#tMon do
- if color then
- tMon[i]["setBackgroundColor"](color)
- end
- tMon[i]["setCursorPos"](xPos,yPos)
- tMon[i]["write"](" ")
- end
- else
- --terminal
- if color then
- term.setBackgroundColor(color)
- end
- term.setCursorPos(xPos,yPos)
- term.write" "
- end
- end,
- ["drawLine"] = function(startX,startY,endX,endY,color,monitor)
- if color then
- term.setBackgroundColor(color)
- if monitor then
- for i=1,#tMon do
- tMon[i]["setBackgroundColor"](color)
- end
- end
- end
- startX = math.floor(startX)
- startY = math.floor(startY)
- endX = math.floor(endX)
- endY = math.floor(endY)
- if startX == endX and startY == endY then
- paintutils.drawPixel(startX,startY,monitor)
- return
- end
- local minX = math.min(startX,endX)
- if minX == startX then
- minY = startY
- maxX = endX
- maxY = endY
- else
- minY = endY
- maxX = startX
- maxY = startY
- end
- local xDiff = maxX-minX
- local yDiff = maxY-minY
- if xDiff > math.abs(yDiff) then
- local y = minY
- local dy = yDiff/xDiff
- for x=minX,maxX do
- paintutils.drawPixel(x,math.floor(y+0.5),monitor)
- y = y+dy
- end
- else
- local x = minX
- local dx = xDiff/yDiff
- if maxY >= minY then
- for y=minY,maxY do
- paintutils.drawPixel(math.floor(x+0.5),y,monitor)
- x = x+dx
- end
- else
- for y=minY,maxY,-1 do
- paintutils.drawPixel(math.floor(x+0.5),y,monitor)
- x = x-dx
- end
- end
- end
- end
- }
- tInput = {
- --table for input fields
- ["cursX"] = 1, --cursor location
- ["enabled"] = false, --input enabled
- ["render"] = function(num,startX,endX,lineY,fieldName,text)
- --creates/clears and renders the given (num) inputfield, from (startX) to (endX) at (lineY)
- --optionally puts (fieldName) infront of the input area and renders (text) on the input area
- fieldName = string.format(fieldName or "")
- tInput[num] = {
- ["scrollX"] = 0,
- ["startX"] = startX+#fieldName,
- ["endX"] = endX,
- ["lineY"] = lineY,
- ["fieldName"] = fieldName or "",
- ["text"] = string.format(text or "")
- }
- paintutils.drawLine(startX,lineY,endX,lineY,tColors.inputBackground)
- term.setTextColor(tColors.inputText)
- term.setBackgroundColor(tColors.inputBackground)
- term.setCursorPos(startX,lineY)
- term.write(tInput[num]["fieldName"]..tInput[num]["text"]:sub(tInput[num]["scrollX"],endX+tInput[num]["scrollX"]))
- tInput.cursX = #tInput[num]["text"]+1
- term.setCursorPos(tInput[num]["startX"]+tInput.cursX,lineY)
- end,
- ["reRender"] = function(num)
- --updates the given (num) input field
- if not tInput[num] then
- error("ERROR: input field "..num.." does not exist!")
- end
- paintutils.drawLine(tInput[num]["startX"],tInput[num]["lineY"],tInput[num]["endX"],tInput[num]["lineY"],tColors.inputBackground)
- term.setTextColor(tColors.inputText)
- term.setBackgroundColor(tColors.inputBackground)
- term.setCursorPos(tInput[num]["startX"],tInput[num]["lineY"])
- term.write(tInput[num]["text"]:sub(tInput[num]["scrollX"],tInput[num]["endX"]-tInput[num]["startX"]+tInput[num]["scrollX"]))
- term.setCursorPos(tInput[num]["startX"]+tInput.cursX-1,tInput[num]["lineY"])
- end
- }
- tBox = {
- --box table, holds functions and values related to pop-up boxes
- ["render"] = function(startX,endX,message,buttons,textInputs,acceptedInput,...)
- --creates a pop-up box in the given (startX) (endX) area
- --Height is calculated automatically
- --message is rendered below the borders
- --then renders the given (button) of buttons,
- --if (textInputs) is given then textFields will be added aswell
- --which only accepts (acceptedInput), use "." to accept anything
- --every value afterwards is the name of each inputField, this will appear infront of the input area
- local tArgs = {...}
- local tFieldName = {}
- local tFieldText = {}
- buttons = buttons or 1
- textInputs = textInputs or 0
- acceptedInput = acceptedInput or "."
- for i=1+buttons,buttons+textInputs do
- tFieldName[i-buttons] = tArgs[i] or ""
- tFieldText[i-buttons] = tArgs[i+textInputs] or ""
- end
- local tLines = {}
- local lineLength = (endX-startX-1)
- if type(message) == "table" then
- --converts message to string if it's a table
- message = table.concat(message,"|")
- end
- while #message > 0 do
- local line = message:sub(1,lineLength)
- local newLine = string.find(line.."","|") --check for new line character
- if newLine then
- line = line:sub(1,newLine-1)
- message = message:sub(#line+2,#message)
- elseif #line == lineLength then
- local endSpace = string.find(line.."","%s$") or string.find(line.."","%s%S-$") or lineLength
- line = line:sub(1,endSpace)
- message = message:sub(#line+1,#message)
- else
- message = ""
- end
- table.insert(tLines,line)
- end
- local totY = #tLines+2+textInputs
- tBox.startX = startX
- tBox.endX = endX
- tBox.startY = tTerm.yMid-math.floor(totY/2)
- tBox.endY = tBox.startY+totY
- tBox.midX = math.ceil((endX-startX)/2)+startX
- for i=tBox.startY+1,tBox.endY-1 do
- --draws box
- paintutils.drawLine(startX+1,i,endX-1,i,tColors.box)
- end
- --draws border
- paintutils.drawLine(startX,tBox.startY,endX,tBox.startY,tColors.boxBorder)
- paintutils.drawLine(endX,tBox.startY,endX,tBox.endY,tColors.boxBorder)
- paintutils.drawLine(endX,tBox.endY,startX,tBox.endY,tColors.boxBorder)
- paintutils.drawLine(startX,tBox.endY,startX,tBox.startY,tColors.boxBorder)
- --renders message
- term.setBackgroundColor(tColors.box)
- term.setTextColor(tColors.boxText)
- for i=1,#tLines do
- term.setCursorPos(math.ceil(tBox.midX-(#tLines[i]/2)),tBox.startY+i)
- term.write(tLines[i])
- end
- --draws button
- tBox.button = {}
- local totalButtonSpace = 0
- for i=1,buttons do
- tBox.button[i] = {}
- tBox.button[i]["name"] = tArgs[i] or "Ok"
- tBox.button[i]["size"] = #tBox.button[i]["name"]+2
- totalButtonSpace = totalButtonSpace+tBox.button[i]["size"]+2
- end
- local nextButton = tBox.midX-math.ceil(totalButtonSpace/2)+tBox.startX
- for i=1,#tBox.button do
- tBox.button[i]["startX"] = nextButton
- tBox.button[i]["endX"] = nextButton+tBox.button[i]["size"]
- tBox.button[i]["lineY"] = tBox.endY-1
- term.setCursorPos(tBox.button[i]["startX"],tBox.button[i]["lineY"])
- term.setBackgroundColor(tColors.boxButton)
- term.setTextColor(tColors.boxButtonText)
- term.write(" "..tBox.button[i]["name"].." ") --add spaces for appearances
- nextButton = nextButton+tBox.button[i]["size"]+2
- end
- --renders input boxes
- if textInputs > 0 then
- for i=1,#tInput do
- tInput[i] = nil
- end
- for i=textInputs,1,-1 do
- tInput[i] = {}
- tInput.render(i,3,tTerm.x-2,tBox.endY-2-textInputs+i,tFieldName[i] or "",tFieldText[i] or "")
- end
- term.setCursorBlink(true)
- tInput.enabled = 1
- tInput.cursX = #tInput[tInput.enabled]["text"]+1
- term.setCursorPos(tInput[1]["startX"]+tInput.cursX-1,tInput[1]["lineY"])
- else
- tInput.enabled = false
- end
- --user events
- while true do
- local tEvent = {os.pullEvent()}
- if tEvent[1] == "monitor_touch" then
- tEvent[1] = "mouse_click"
- tEvent[2] = 1
- end
- if tEvent[1] == "mouse_click" then
- --clicks
- if tEvent[2] == 1 then
- --left clicks
- local input = tInput[tEvent[4]-(tBox.endY-#tInput-2)] or false --clicked input bar
- local button = tBox.click(tEvent[3],tEvent[4]) or false
- if input and tInput.enabled
- and tEvent[3] <= input["endX"] and tEvent[3] >= input["startX"] --x
- and #input["text"] > 0 then --text
- --input bar click
- tInput.enabled = tEvent[4]-(tBox.endY-#tInput-2)
- tInput.cursX = math.min(tEvent[3]-input["startX"],#input["text"]-input.scrollX)
- term.setCursorPos(input["startX"]+tInput.cursX,tEvent[4])
- elseif button then
- if tInput.enabled then
- local tRet = {button}
- for i=1,#tInput do
- if string.match(tInput[i]["text"],"^%d+$") then
- tInput[i]["text"] = tonumber(tInput[i]["text"])
- end
- tRet[#tRet+1] = tInput[i]["text"]
- end
- tInput.enabled = false
- tMenuBar.render()
- term.setCursorBlink(false)
- return unpack(tRet)
- else
- tMenuBar.render()
- term.setCursorBlink(false)
- return button
- end
- end
- end
- elseif tEvent[1] == "char" then
- --letter input
- if tEvent[2] == "%"
- or tEvent[2] == "["
- or not tEvent[2]:match(acceptedInput) then
- --skip to avoid crashes
- elseif tInput.enabled then
- tInput[tInput.enabled]["text"] = string.format(tInput[tInput.enabled]["text"]:sub(1,tInput.cursX+tInput[tInput.enabled]["scrollX"]-1)..tEvent[2]..tInput[tInput.enabled]["text"]:sub(tInput.cursX+tInput[tInput.enabled]["scrollX"],#tInput[tInput.enabled]["text"]))
- tInput.cursX = tInput.cursX+1
- if tInput.cursX > tInput[tInput.enabled]["endX"]-tInput[tInput.enabled]["startX"] then
- tInput[tInput.enabled]["scrollX"] = tInput[tInput.enabled]["scrollX"]+1
- tInput.cursX = tInput[tInput.enabled]["endX"]-tInput[tInput.enabled]["startX"]
- end
- tInput.reRender(tInput.enabled)
- end
- elseif tEvent[1] == "key" then
- --special keyes input
- local key = tEvent[2]
- if tInput.enabled then
- --input box
- if key == 14
- and (tInput.cursX > 1 or tInput[tInput.enabled]["scrollX"] > 0) then
- --backspace
- tInput[tInput.enabled]["text"] = string.format(tInput[tInput.enabled]["text"]:sub(1,tInput.cursX+tInput[tInput.enabled]["scrollX"]-2)..tInput[tInput.enabled]["text"]:sub(tInput.cursX+tInput[tInput.enabled]["scrollX"],#tInput[tInput.enabled]["text"]))
- if tInput[tInput.enabled]["scrollX"] > 0 then
- tInput[tInput.enabled]["scrollX"] = tInput[tInput.enabled]["scrollX"]-1
- else
- tInput.cursX = tInput.cursX-1
- end
- elseif key == 205 then --right arrow
- tInput.cursX = tInput.cursX+1
- elseif key == 203 then --left arrow
- tInput.cursX = tInput.cursX-1
- elseif key == 200 then --up arrow
- tInput.enabled = math.max(1,tInput.enabled-1)
- elseif key == 208 then --down arrow
- tInput.enabled = math.min(#tInput,tInput.enabled+1)
- elseif key == 211 then --delete
- if #tInput[tInput.enabled]["text"] <= 1 and tInput.cursX == 1 then
- tInput[tInput.enabled]["text"] = ""
- else
- tInput[tInput.enabled]["text"] = string.format(tInput[tInput.enabled]["text"]:sub(1,tInput.cursX+tInput[tInput.enabled]["scrollX"])..tInput[tInput.enabled]["text"]:sub(tInput.cursX+tInput[tInput.enabled]["scrollX"]+2,#tInput[tInput.enabled]["text"]))
- end
- elseif key == 207 then --end
- tInput.cursX = #tInput[tInput.enabled]["text"]+1
- tInput[tInput.enabled]["scrollX"] = math.max(0,#tInput[tInput.enabled]["text"]-tInput[tInput.enabled]["endX"])
- elseif key == 199 then --home
- tInput.cursX = 1
- tInput[tInput.enabled]["scrollX"] = 0
- elseif key == 28 then --enter
- if tInput.enabled >= #tInput then
- local tRet = {(tBox.button[2] or tBox.button[1])["name"]} --prefer right button
- for i=1,#tInput do
- if string.match(tInput[i]["text"],"^%d+$") then
- tInput[i]["text"] = tonumber(tInput[i]["text"])
- end
- tRet[#tRet+1] = tInput[i]["text"]
- end
- tInput.enabled = false
- term.setCursorBlink(false)
- tMenuBar.render()
- return unpack(tRet)
- else
- tInput.enabled = math.min(#tInput,tInput.enabled+1)
- end
- end
- if tInput.cursX < 1 then
- tInput.cursX = 1
- if tInput[tInput.enabled]["scrollX"] > 0 then
- tInput[tInput.enabled]["scrollX"] = tInput[tInput.enabled]["scrollX"]-1
- end
- elseif tInput.cursX > tInput[tInput.enabled]["endX"]-tInput[tInput.enabled]["startX"] then
- tInput.cursX = tInput[tInput.enabled]["endX"]-tInput[tInput.enabled]["startX"]
- if #tInput[tInput.enabled]["text"] > tInput.cursX+tInput[tInput.enabled]["scrollX"] then
- tInput[tInput.enabled]["scrollX"] = tInput[tInput.enabled]["scrollX"]+1
- end
- elseif tInput.cursX+tInput[tInput.enabled]["scrollX"] > #string.format(tInput[tInput.enabled]["text"])+1 then
- if tInput[tInput.enabled]["scrollX"] > 0 then
- tInput[tInput.enabled]["scrollX"] = tInput[tInput.enabled]["scrollX"]-1
- else
- tInput.cursX = math.min(#string.format(tInput[tInput.enabled]["text"])+1,tInput[tInput.enabled]["endX"]-1-tInput[tInput.enabled]["startX"])
- end
- end
- tInput.reRender(tInput.enabled)
- else
- --message box
- if key == 28 then --enter
- tMenuBar.render()
- renderLayer(tScroll.layer)
- return (tBox.button[2] or tBox.button[1])["name"]
- end
- end
- end
- end
- end,
- ["click"] = function(clickX,clickY)
- for i=1,#tBox.button do
- if clickY == tBox.button[i]["lineY"]
- and clickX >= tBox.button[i]["startX"]
- and clickX <= tBox.button[i]["endX"] then
- return tBox.button[i]["name"]
- end
- end
- end
- }
- tContextMenu = {
- [1] = {
- ["item"] = "Select",
- ["func"] = function()
- if tTool.selector[1] then
- tTool.selector.selection = true
- tContextMenu.open = false
- renderLayer(tScroll.layer)
- end
- end
- },
- [2] = {
- ["item"] = "Clear sel",
- ["func"] = function()
- if tTool.selector[1] or tTool.selector[2] or tTool.selector.copy then
- tTool.selector = {
- ["enabled"] = true
- }
- tContextMenu.open = false
- renderLayer(tScroll.layer)
- end
- end
- },
- [3] = {
- ["item"] = "Cut",
- ["func"] = function()
- if tTool.selector[1] and not tTool.selector.copy then
- local t1 = tTool.selector[1]
- local t2 = tTool.selector[2] or t1
- tTool.selector.copy = selectorCopy(t1.x,t1.z,t2.x,t2.z,t1.layer,true)
- tTool.selector.selection = true
- tContextMenu.open = false
- renderLayer(tScroll.layer)
- end
- end
- },
- [4] = {
- ["item"] = "Copy",
- ["func"] = function()
- if tTool.selector[1] and not tTool.selector.copy then
- local t1 = tTool.selector[1]
- local t2 = tTool.selector[2] or t1
- tTool.selector.copy = selectorCopy(t1.x,t1.z,t2.x,t2.z,t1.layer,false)
- tTool.selector.selection = true
- tContextMenu.open = false
- renderLayer(tScroll.layer)
- end
- end
- },
- [5] = {
- ["item"] = "Paste",
- ["func"] = function()
- if tTool.selector.copy then
- selectorPaste(tTool.selector[1]["x"],tTool.selector[1]["z"],tTool.selector.copy)
- tContextMenu.open = false
- renderLayer(tScroll.layer)
- end
- end
- },
- [6] = {
- ["item"] = "Delete",
- ["func"] = function()
- if tTool.selector[1] and not tTool.selector.copy then
- local t1 = tTool.selector[1]
- local t2 = tTool.selector[2] or t1
- selectorCopy(t1.x,t1.z,t2.x,t2.z,t1.layer,true)
- tContextMenu.open = false
- renderLayer(tScroll.layer)
- end
- end
- },
- [7] = {
- ["item"] = "Recolor",
- ["func"] = function()
- if tTool.selector[1] then
- tContextMenu.open = false
- tMenuBar.render"Recolor"
- end
- end
- },
- [8] = {
- ["item"] = "Flip hori",
- ["func"] = function()
- if tTool.selector.copy then
- tTool.selector.copy = flipLayer(tTool.selector.copy,"x")
- renderLayer(tScroll.layer)
- elseif tTool.selector[1] then
- local t1 = tTool.selector[1]
- local t2 = tTool.selector[2] or t1
- selectorPaste(t1.x,t1.z,flipLayer(selectorCopy(t1.x,t1.z,t2.x,t2.z,tScroll.layer,true),"x"),tScroll.layer)
- renderLayer(tScroll.layer)
- end
- end
- },
- [9] = {
- ["item"] = "Flip vert",
- ["func"] = function()
- if tTool.selector.copy then
- tTool.selector.copy = flipLayer(tTool.selector.copy,"z")
- renderLayer(tScroll.layer)
- elseif tTool.selector[1] then
- local t1 = tTool.selector[1]
- local t2 = tTool.selector[2] or t1
- selectorPaste(t1.x,t1.z,flipLayer(selectorCopy(t1.x,t1.z,t2.x,t2.z,tScroll.layer,true),"z"),tScroll.layer)
- renderLayer(tScroll.layer)
- end
- end
- },
- ["open"] = false
- }
- for i=1,#tContextMenu do
- --find longest drop down selection for rendering purposes
- tContextMenu.length = math.max(tContextMenu.length or 0,#tContextMenu[i].item)
- end
- for i=1,#tContextMenu do
- --equalize length of the dropdown menu names by adding spaces
- local item = tContextMenu[i]["item"]
- tContextMenu[i]["item"] = " "..item..string.rep(" ",math.max(0,tContextMenu.length-#string.format(item)))
- end
- tMenuBar = {
- --top menu table, biggest godamn table i've ever made.
- --Holds menu names and their respective functions
- --it's execution is handled in the event handler
- ["Turtle"] = {
- --general turtle functions
- [1] = {
- ["item"] = "Move to...",
- ["func"] = function()
- local button,coords,axis = tBox.render(1,tTerm.x,"Move turtle to Coords(-999999-999999) on Axis(x/y/z)",2,2,".","Cancel","Ok","Coords:","Axis:")
- if button == "Cancel" then
- --cancel button
- return
- elseif not string.match(coords,"^%-?%d+$") or not axis:match"^[xyzXYZ]$" then
- tBox.render(1,tTerm.x,"Faulty parameters given!")
- else
- cTurtle.moveTo(coords,axis)
- tMenuBar.render()
- renderLayer(tScroll.layer)
- end
- end
- },
- [2] = {
- ["item"] = "Turn...",
- ["func"] = function()
- local button,dir = tBox.render(1,tTerm.x,"Turn turtle, accepts north, x+, right, back, etc.",2,1,".","Cancel","Ok")
- if button == "Cancel" then
- --cancel button
- return
- elseif cTurtle.dirStandardize(dir) then
- cTurtle.renderMove = false
- cTurtle.turn(dir)
- cTurtle.renderMove = true
- tBox.render(1,tTerm.x,"Turned turtle "..dir)
- else
- tBox.render(1,tTerm.x,dir.." is not a valid direction!")
- end
- end
- },
- [3] = {
- ["item"] = "Scan layer...",
- ["func"] = function()
- local button,layer,x,z = tBox.render(1,tTerm.x,"Input new layer number and layer sizes. The color on tool 1 will be used to render.",2,3,"%d","Cancel","Ok","Layer:","X:","Z:",#tBlueprint+1,tTerm.xCanvas,tTerm.zCanvas)
- if button == "Cancel" then
- return
- end
- layer = layer or #tBlueprint+1
- x = x or tTerm.x-1
- z = z or tTerm.y-2
- scan(x,z,layer)
- tBox.render(1,tTerm.x,"Layer("..layer..") scan complete.")
- end
- },
- [4] = {
- ["item"] = "Build layer",
- ["func"] = function()
- local path,button = tFile.curBlueprint
- if path then
- saveBlueprint(path)
- else
- button,path = tBox.render(1,tTerm.x,"Blueprint must be saved locally prior to building! Input file path:",2,1,".","Cancel","Ok","/")
- if button == "Cancel" then
- --cancel
- return
- else
- path = "/"..path
- local dir = ""
- for directory in path:gmatch"/.-/" do
- dir = dir..directory
- if not fs.exists(dir) then
- fs.makeDir(dir)
- end
- end
- saveBlueprint(path)
- end
- end
- tBox.render(1,tTerm.x,"Saved file: "..path)
- tFile.curBlueprint = path
- buildBlueprint(tScroll.layer,tScroll.layer)
- end
- },
- [5] = {
- ["item"] = "Build blueprint",
- ["func"] = function()
- local path,button = tFile.curBlueprint
- if path then
- saveBlueprint(path)
- else
- button,path = tBox.render(1,tTerm.x,"Blueprint must be saved locally prior to building! Input file path:",2,1,".","Cancel","Ok","/")
- if button == "Cancel" then
- --cancel
- return
- else
- path = "/"..path
- local dir = ""
- for directory in path:gmatch"/.-/" do
- dir = dir..directory
- if not fs.exists(dir) then
- fs.makeDir(dir)
- end
- end
- saveBlueprint(path)
- end
- end
- tBox.render(1,tTerm.x,"Saved file: "..path)
- tFile.curBlueprint = path
- buildBlueprint(1,#tBlueprint)
- end
- },
- [6] = {
- ["item"] = "Configure enderchest",
- ["func"] = function()
- local button,slot
- if tOngoing.enderChest then
- button,slot = tBox.render(1,tTerm.x,"Use an enderchest for automatic restocking of materials, note that the same slot numbers apply to the chest.",3,1,"%d","Cancel","Change","Disable","Slot:",tOngoing.enderChest)
- else
- button,slot = tBox.render(1,tTerm.x,"Use an enderchest for automatic restocking of materials, note that the same slot numbers used by the turtle apply to the chest as well.",2,1,"%d","Cancel","Enable","Slot:",16)
- end
- if button == "Cancel" then
- return
- elseif button == "Disable" then
- tOngoing.enderChest = false
- cTurtle.tSettings.enderFuel = false
- else
- if not slot or slot > 16 or slot < 1 then
- tBox.render(1,tTerm.x,"Faulty slot number given!")
- return
- else
- tOngoing.enderChest = slot
- cTurtle.tSettings.enderFuel = slot
- end
- end
- end
- },
- [7] = {
- ["item"] = "Configure break mode",
- ["func"] = function()
- local button,slot
- if tOngoing.breakMode then
- button,slot = tBox.render(1,tTerm.x,"The turtle will break all blocks in it's path, and always keep a minimum of 1 block in each slot, to avoid picking up new blocks.|Current mode: ON",2,0,".","Cancel","Disable")
- else
- button,slot = tBox.render(1,tTerm.x,"The turtle will break all blocks in it's path, and always keep a minimum of 1 block in each slot, to avoid picking up new blocks.|Current mode: OFF",2,0,".","Cancel","Enable")
- end
- if button == "Cancel" then
- return
- elseif button == "Disable" then
- tOngoing.breakMode = false
- else
- tOngoing.breakMode = true
- end
- end
- },
- [8] = {
- ["item"] = "Edit GPS data...",
- ["func"] = function()
- cTurtle.input()
- renderLayer(tScroll.layer)
- tMenuBar.render()
- end
- },
- [9] = {
- ["item"] = "Edit Origin point...",
- ["func"] = function()
- local path,button = tFile.curBlueprint
- if not path then
- button,path = tBox.render(1,tTerm.x,"Blueprint must be saved locally prior to editing origin point! Input file path:",2,1,".","Cancel","Ok","/")
- if button == "Cancel" then
- --cancel
- return
- else
- path = "/"..path
- local dir = ""
- for directory in path:gmatch"/.-/" do
- dir = dir..directory
- if not fs.exists(dir) then
- fs.makeDir(dir)
- end
- end
- end
- end
- tFile.curBlueprint = path
- local button,x,y,z,xDir,zDir,yDir = tBox.render(1,tTerm.x,"Edit current build starting point",2,6,"[0-9%+%-]","Cancel","Ok","X:","Y:","Z:","X dir:","Z dir:","Y dir:",tOrigin.x or cTurtle.tPos.x, tOrigin.y or cTurtle.tPos.y, tOrigin.z or cTurtle.tPos.z,tOrigin.xDir or "+",tOrigin.zDir or "+",tOrigin.yDir or "+")
- if button == "Cancel" then
- return --cancel
- end
- tOrigin.x = x or cTurtle.tPos.x
- tOrigin.y = y or cTurtle.tPos.y
- tOrigin.z = z or cTurtle.tPos.z
- tOrigin.xDir = xDir or "+"
- tOrigin.zDir = zDir or "+"
- tOrigin.yDir = yDir or "+"
- saveBlueprint(path)
- end
- }
- },
- ["Blueprint"] = {
- --creation of new blueprints, loading, saving etc...
- [1] = {
- ["item"] = "New...",
- ["func"] = function()
- local button = tBox.render(1,tTerm.x,"All unsaved work will be lost, continue?",2,0,".","Cancel","Ok")
- if button == "Cancel" then
- --cancel
- return
- end
- tBlueprint = {}
- createLayer(tTerm.xCanvas,tTerm.zCanvas,1)
- tFile.curBlueprint = false
- tScroll.layer = 1
- tScroll.x.value = 0
- tScroll.y.value = 0
- renderLayer(1)
- tBox.render(1,tTerm.x,"New file creation complete.")
- end
- },
- [2] = {
- ["item"] = "Load...",
- ["func"] = function()
- local newBlueprint,newColorSlots,newOrigins
- local button, path = tBox.render(1,tTerm.x,"Load blueprint from file path:",3,1,".","Cancel","Ok","Pastebin","/",tFile.curBlueprint or "")
- if button == "Cancel" then
- return
- elseif button == "Pastebin" then
- newBlueprint,newColorSlots,newOrigin = tPaste.get(path,false,true)
- if not newBlueprint then
- tBox.render(1,tTerm.x,"Pastebin download "..path.." failed!")
- return
- end
- elseif not fs.exists("/"..path) then
- tBox.render(1,tTerm.x,"/"..path.." does not exist!")
- return
- else
- newBlueprint,newColorSlots,newOrigin = loadBlueprint("/"..path)
- if not newBlueprint then
- tBox.render(1,tTerm.x,"/"..path.." is not a Turtle Architect file!")
- return
- else
- tFile.curBlueprint = "/"..path
- end
- end
- tOrigin = newOrigin or {}
- tColorSlots = newColorSlots or {}
- tBlueprint = {}
- for k,v in pairs(newBlueprint) do
- tBlueprint[k] = {}
- for k2,v2 in pairs(newBlueprint[k]) do
- tBlueprint[k][k2] = v2
- end
- end
- tScroll.x.value = 0
- tScroll.y.value = 0
- tScroll.layer = 1
- renderLayer(tScroll.layer)
- tBox.render(1,tTerm.x,"/"..path.." loaded")
- end
- },
- [3] = {
- ["item"] = "Save",
- ["func"] = function()
- local path,button = tFile.curBlueprint
- if not path then
- button,path = tBox.render(1,tTerm.x,"Input save path:",2,1,".","Cancel","Ok","/")
- if button == "Cancel" then
- --cancel
- return
- else
- tFile.curBlueprint = path
- path = "/"..path
- local dir = ""
- for directory in path:gmatch"/.-/" do
- dir = dir..directory
- if not fs.exists(dir) then
- fs.makeDir(dir)
- end
- end
- end
- end
- saveBlueprint(path)
- tBox.render(1,tTerm.x,"Saved file: "..path)
- end,
- },
- [4] = {
- ["item"] = "Save as...",
- ["func"] = function()
- local button,path = tBox.render(1,tTerm.x,"Save as:",3,1,".","Cancel","Local","Pastebin","/",tFile.curBlueprint or "")
- if button == "Cancel" then
- --cancel
- return
- elseif button == "Local" then
- path = "/"..path
- local dir = ""
- for directory in path:gmatch"/.-/" do
- dir = dir..directory
- if not fs.exists(dir) then
- local button = tBox.render(1,tTerm.x,"The directory "..dir.." does not exist! Create?",2,0,".","Cancel","Create")
- if button == "Create" then
- fs.makeDir(dir)
- else
- tBox.render(1,tTerm.x,"Saving "..path.." failed!")
- return
- end
- end
- end
- saveBlueprint(path)
- tBox.render(1,tTerm.x,"Saved as: "..path)
- tFile.curBlueprint = path
- elseif button == "Pastebin" then
- trimBlueprint(tBlueprint)
- local url, code = tPaste.put(tBlueprint,path)
- if not url then
- tBox.render(1,tTerm.x,"Pastebin upload "..path.." failed!")
- return
- end
- tBox.render(1,tTerm.x,"Pastebin upload sucesssfull! "..url..".")
- end
- end
- },
- [5] = {
- ["item"] = "Flip...",
- ["func"] = function()
- local button = tBox.render(1,tTerm.x,"Flip blueprint Horizontinal or Vertical?",3,0,".","Cancel","Hori","Vert")
- if button == "Cancel" then
- return --cancel
- elseif button == "Hori" then
- button = "x"
- else
- button = "z"
- end
- fattenBlueprint(tBlueprint)
- for i=1,#tBlueprint do
- layerPaste(flipLayer(tBlueprint[i],button),i,true)
- end
- renderLayer(tScroll.layer)
- end
- },
- [6] = {
- ["item"] = "Edit slot data...",
- ["func"] = function()
- tMenuBar.render("SlotColors")
- end
- },
- [7] = {
- ["item"] = "Mark as built",
- ["func"] = function()
- local button = tBox.render(1,tTerm.x,"This will mark the entire blueprint as built, so the turtle will skip it.",2,0,".","Cancel","Ok")
- if button == "Cancel" then
- return --cancel
- end
- for il=1,#tBlueprint do
- for ix=1,#tBlueprint[il] do
- for iz=1,#tBlueprint[il][ix] do
- local block = tBlueprint[il][ix][iz] or " "
- if block ~= " "
- and block:match(unbuilt) then
- tBlueprint[il][ix][iz] = block:upper()
- end
- end
- end
- end
- end
- },
- [8] = {
- ["item"] = "Mark as not built",
- ["func"] = function()
- local button = tBox.render(1,tTerm.x,"This will mark the entire blueprint as not built, so the turtle will build it.",2,0,".","Cancel","Ok")
- if button == "Cancel" then
- return --cancel
- end
- for il=1,#tBlueprint do
- for ix=1,#tBlueprint[il] do
- for iz=1,#tBlueprint[il][ix] do
- local block = tBlueprint[il][ix][iz] or " "
- tBlueprint[il][ix][iz] = block:upper()
- end
- end
- end
- end
- },
- [9] = {
- ["item"] = "Check usage",
- ["func"] = function()
- local button,from,to = tBox.render(1,tTerm.x,"Input layer range to check for fuel and block usage",2,2,".","Cancel","Ok","From:","To:",1,#tBlueprint)
- if button == "Cancel" then
- return --cancel
- elseif from > to
- or to > #tBlueprint
- or from < 1 then
- tBox.render(1,tTerm.x,"Faulty layer range "..from.."-"..to.." given!")
- return
- end
- local fuelUsage,tBlockUsage = checkUsage(from,to)
- tBox.render(1,tTerm.x,"Required fuel: "..fuelUsage..".")
- local tUsageLines = {[1] = "Blocks required:"}
- local tUsageLines2 = {}
- for k,v in pairs(tBlockUsage) do
- if k:match(built) then
- --skip
- else
- table.insert(tUsageLines,tColorString[tColorNums[k]]..": "..v..".")
- end
- end
- while #tUsageLines >= tTerm.y-3 do
- table.insert(tUsageLines2,table.remove(tUsageLines,#tUsageLines))
- end
- tBox.render(1,tTerm.x,tUsageLines)
- if #tUsageLines2 > 0 then
- tBox.render(1,tTerm.x,tUsageLines2)
- end
- end
- },
- },
- ["Layer"] = {
- --layer actions, duplicating, moving and what have you
- [1] = {
- ["item"] = "New...",
- ["func"] = function()
- local button,layerNum = tBox.render(1,tTerm.x,"Input new layer number:",2,1,"%d","Cancel","Ok","",#tBlueprint+1)
- if button == "Cancel" then
- --cancel
- return
- end
- if layerNum <= #tBlueprint then
- local button = tBox.render(1,tTerm.x,"Layer "..layerNum.." already exists! Overwrite or insert?",3,0,".","Cancel","Insert","Overwrite")
- if button == "Cancel" then
- return
- elseif button == "Insert" then
- createLayer(tTerm.xCanvas,tTerm.zCanvas,layerNum)
- elseif button == "Overwrite" then
- createLayer(tTerm.xCanvas,tTerm.zCanvas,layerNum,true)
- end
- else
- for i=#tBlueprint+1,layerNum do
- createLayer(tTerm.xCanvas,tTerm.zCanvas,i,true)
- end
- end
- tScroll.x.value = 0
- tScroll.y.value = 0
- tScroll.layer = layerNum
- renderLayer(tScroll.layer)
- end
- },
- [2] = {
- ["item"] = "Import...",
- ["func"] = function()
- local importBlueprint
- local button, path,from,to,layer = tBox.render(1,tTerm.x,"Import layers from local path or pastebin code:",3,4,".","Cancel","Ok","Pastebin","/","From layer:","To:","Import to:","","","",#tBlueprint+1)
- if button == "Cancel" then
- return
- elseif button == "Pastebin" then
- local paste = tPaste.get(path)
- if not paste then
- tBox.render(1,tTerm.x,"Pastebin download "..path.." failed!")
- return
- elseif not paste:match("Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program) then
- tBox.render(1,tTerm.x,path.." is not a Turtle Architect file!")
- return
- end
- importBlueprint = textutils.unserialize(paste:sub(#("Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program)+1,#paste))
- elseif not fs.exists("/"..path) then
- tBox.render(1,tTerm.x,"/"..path.." does not exist!")
- return
- else
- importBlueprint = loadBlueprint("/"..path)
- if not importBlueprint then
- tBox.render(1,tTerm.x,"/"..path.." is not a Turtle Architect file!")
- return
- end
- end
- if #importBlueprint < to then
- tBox.render(1,tTerm.x,"The specified layers "..from.."-"..to.." do not exist in the given blueprint("..path..")")
- return
- elseif layer <= #tBlueprint then
- local button = tBox.render(1,tTerm.x,"Layers already exist in the range "..layer.."-"..(layer+(to-from)).."! Overwrite or insert?",3,0,".","Cancel","Insert","Overwrite")
- if button == "Cancel" then
- return
- elseif button == "Insert" then
- for i=from,to do
- layerPaste(importBlueprint[i],layer+(i-from),false)
- end
- elseif button == "Overwrite" then
- for i=from,to do
- layerPaste(importBlueprint[i],layer+(i-from),true)
- end
- end
- else
- for i=#tBlueprint+1,layer-1 do
- createLayer(tTerm.xCanvas,tTerm.zCanvas,i,true)
- end
- for i=from,to do
- layerPaste(importBlueprint[i],layer+(i-from),true)
- end
- end
- tScroll.x.value = math.min(tScroll.x.value,math.max(0,#tBlueprint[tScroll.layer]-tTerm.xCanvas))
- tScroll.y.value = math.min(tScroll.y.value,math.max(0,#tBlueprint[tScroll.layer][1]-tTerm.zCanvas))
- renderLayer(tScroll.layer)
- tBox.render(1,tTerm.x,"Layers "..from.."-"..to.." Imported from "..path.." to "..layer.."-"..(layer+(to-from))..".")
- end
- },
- [3] = {
- ["item"] = "Delete current layer",
- ["func"] = function()
- local delLayer = tScroll.layer
- local button = tBox.render(1,tTerm.x,"Are you sure you wish to delete "..delLayer.."?",2,0,".","Cancel","Ok")
- if button == "Cancel" then
- return --cancel
- end
- if #tBlueprint <= 1 then
- createLayer(tTerm.xCanvas,tTerm.zCanvas,1,true)
- else
- table.remove(tBlueprint,delLayer)
- end
- tScroll.layer = math.min(math.max(1,tScroll.layer-1),#tBlueprint)
- tScroll.x.value = math.min(tScroll.x.value,#tBlueprint[tScroll.layer]-tTerm.xCanvas)
- tScroll.y.value = math.min(tScroll.y.value,#tBlueprint[tScroll.layer][1]-tTerm.zCanvas)
- renderLayer(tScroll.layer)
- tBox.render(1,tTerm.x,"Deleted layer "..delLayer..".")
- end
- },
- [4] = {
- ["item"] = "Delete layer range",
- ["func"] = function()
- local button,from,to = tBox.render(1,tTerm.x,"Delete layers",2,2,"%d","Cancel","Ok","From:","To:",tScroll.layer,#tBlueprint)
- if button == "Cancel" then
- return --cancel
- end
- if #tBlueprint <= 1 then
- createLayer(tTerm.xCanvas,tTerm.zCanvas,1,true)
- else
- for i=math.max(to,from),math.min(from,to),-1 do
- table.remove(tBlueprint,i)
- end
- end
- tScroll.layer = math.min(math.max(1,tScroll.layer-1),#tBlueprint)
- tScroll.x.value = math.min(tScroll.x.value,#tBlueprint[tScroll.layer]-tTerm.xCanvas)
- tScroll.y.value = math.min(tScroll.y.value,#tBlueprint[tScroll.layer][1]-tTerm.zCanvas)
- renderLayer(tScroll.layer)
- tBox.render(1,tTerm.x,"Deleted layers "..from.."-"..to..".")
- end
- },
- [5] = {
- ["item"] = "Move to...",
- ["func"] = function()
- local button,layerNum = tBox.render(1,tTerm.x,"Move current layer("..tScroll.layer..") to...",2,1,"%d","Cancel","Ok","",#tBlueprint+1)
- if button == "Cancel" then
- return --cancel
- end
- if layerNum <= #tBlueprint then
- local button = tBox.render(1,tTerm.x,"A layer already exists at"..layerNum.."! Overwrite or insert?",3,0,".","Cancel","Insert","Overwrite")
- if button == "Cancel" then
- return
- elseif button == "Insert" then
- layerPaste(copyLayer(tScroll.layer),layerNum,false)
- elseif button == "Overwrite" then
- layerPaste(copyLayer(tScroll.layer),layerNum,true)
- end
- else
- for i=#tBlueprint+1,layerNum-1 do
- createLayer(tTerm.xCanvas,tTerm.zCanvas,i,true)
- end
- layerPaste(copyLayer(tScroll.layer),layerNum,true)
- end
- createLayer(tTerm.xCanvas,tTerm.zCanvas,tScroll.layer,true)
- tBox.render(1,tTerm.x,"Moved layer "..tScroll.layer.." to "..layerNum..".")
- tScroll.layer = layerNum
- renderLayer(tScroll.layer)
- end
- },
- [6] = {
- ["item"] = "Copy to...",
- ["func"] = function()
- local button,layerNum = tBox.render(1,tTerm.x,"Copy current layer("..tScroll.layer..") to...",2,1,"%d","Cancel","Ok","",#tBlueprint+1)
- if button == "Cancel" then
- --cancel
- return
- elseif layerNum <= #tBlueprint then
- local button = tBox.render(1,tTerm.x,"A layer already exists at"..layerNum.."! Overwrite or insert?",3,0,"Cancel","Insert","Overwrite")
- if button == "Cancel" then
- return
- elseif button == "Insert" then
- layerPaste(copyLayer(tScroll.layer),layerNum,false)
- elseif button == "Overwrite" then
- layerPaste(copyLayer(tScroll.layer),layerNum,true)
- end
- else
- for i=#tBlueprint+1,layerNum-1 do
- createLayer(tTerm.xCanvas,tTerm.zCanvas,i)
- end
- layerPaste(copyLayer(tScroll.layer),layerNum,true)
- end
- tBox.render(1,tTerm.x,"Copied layer "..tScroll.layer.." to "..layerNum..".")
- end
- },
- [7] = {
- ["item"] = "Stretch copy...",
- ["func"] = function()
- local button,from,to = tBox.render(1,tTerm.x,"Stretch current layer("..tScroll.layer..") ...",2,2,"%d","Cancel","Ok","From:","To:",tScroll.layer+1)
- to = to or from or 0
- if button == "Cancel" or to <= 0 then
- --cancel button
- return
- end
- local layerCopy = copyLayer(tScroll.layer)
- if from <= #tBlueprint
- or to <= #tBlueprint then
- local button = tBox.render(1,tTerm.x,"Layers already exist between the range "..from.."-"..to.."! Overwrite or insert?",3,0,".","Cancel","Insert","Overwrite")
- if button == "Cancel" then
- return
- elseif button == "Insert" then
- for i=from,to do
- layerPaste(layerCopy,i)
- end
- elseif button == "Overwrite" then
- for i=from,to do
- layerPaste(layerCopy,i,true)
- end
- end
- else
- for i=#tBlueprint+1,from-1 do
- createLayer(tTerm.xCanvas,tTerm.zCanvas,i)
- end
- for i=from,to do
- layerPaste(layerCopy,i,true)
- end
- end
- tBox.render(1,tTerm.x,"stretched "..tScroll.layer.." from "..from.." to "..to..".")
- end
- },
- [8] = {
- ["item"] = "Copy range...",
- ["func"] = function()
- local button,from,to,layer = tBox.render(1,tTerm.x,"Copy the given range of layers to:",2,3,"%d","Cancel","Ok","From layer:","To:","Paste to:",tScroll.layer,#tBlueprint,#tBlueprint+1)
- if button == "Cancel" then
- return
- elseif layer <= #tBlueprint then
- local button = tBox.render(1,tTerm.x,"Layers already exist in the range "..layer.."-"..(layer+(to-from)).."! Overwrite or insert?",3,0,".","Cancel","Insert","Overwrite")
- if button == "Cancel" then
- return
- elseif button == "Insert" then
- for i=math.max(to,from),math.min(from,to),-1 do
- layerPaste(tBlueprint[i],layer+(i-from),false)
- end
- elseif button == "Overwrite" then
- for i=math.min(from,to),math.max(to,from) do
- layerPaste(tBlueprint[i],layer+(i-from),true)
- end
- end
- else
- for i=#tBlueprint+1,layer-1 do
- createLayer(tTerm.xCanvas,tTerm.zCanvas,i,true)
- end
- for i=math.min(from,to),math.max(to,from) do
- layerPaste(tBlueprint[i],layer+(i-from),true)
- end
- end
- tScroll.x.value = math.min(tScroll.x.value,#tBlueprint[tScroll.layer]-tTerm.xCanvas)
- tScroll.y.value = math.min(tScroll.y.value,#tBlueprint[tScroll.layer][1]-tTerm.zCanvas)
- renderLayer(tScroll.layer)
- tBox.render(1,tTerm.x,"Layers "..from.."-"..to.." copied to "..layer.."-"..(layer+(to-from))..".")
- end
- },
- [9] = {
- ["item"] = "Merge...",
- ["func"] = function()
- local button,from,to = tBox.render(1,tTerm.x,"Merge the layer range...",2,2,"%d","Cancel","Ok","From:","To:",tScroll.layer)
- if button == "Cancel" then
- return --cancel
- elseif not from or not to or to < from then
- tBox.render(1,tTerm.x,"Unable to merge those layers")
- return
- end
- local button = tBox.render(1,tTerm.x,"Merging the layer range "..from.."-"..to..". Keep original colors?",2,0,".","No","Yes")
- if button == "Yes" then
- layerPaste(layerCombine(from,to),from,true)
- else
- layerPaste(layerCombine(from,to,true),from,true)
- end
- for i=to,from+1,-1 do
- table.remove(tBlueprint,i)
- end
- tScroll.layer = math.min(#tBlueprint,tScroll.layer)
- tScroll.x.value = math.min(tScroll.x.value,#tBlueprint[tScroll.layer]-tTerm.xCanvas)
- tScroll.y.value = math.min(tScroll.y.value,#tBlueprint[tScroll.layer][1]-tTerm.zCanvas)
- renderLayer(tScroll.layer)
- end
- },
- [10] = {
- ["item"] = "Flip...",
- ["func"] = function()
- local button = tBox.render(1,tTerm.x,"Flip current layer("..tScroll.layer..") Horizontally or Vertically?",3,0,".","Cancel","Hori","Vert")
- if button == "Cancel" then
- return --cancel
- end
- if button == "Hori" then
- button = "x"
- else
- button = "z"
- end
- layerPaste(flipLayer(tBlueprint[tScroll.layer],button),tScroll.layer,true)
- renderLayer(tScroll.layer)
- end
- },
- [11] = {
- ["item"] = "Mark as built",
- ["func"] = function()
- local button = tBox.render(1,tTerm.x,"This will mark the current layer("..tScroll.layer..") as built, so the turtle will skip it.",2,0,".","Cancel","Ok")
- if button == "Cancel" then
- return --cancel
- end
- for ix=1,#tBlueprint[tScroll.layer] do
- for iz=1,#tBlueprint[tScroll.layer][ix] do
- local block = tBlueprint[tScroll.layer][ix][iz] or " "
- if block ~= " "
- and not block:match(built) then
- tBlueprint[tScroll.layer][ix][iz] = block:upper()
- end
- end
- end
- end
- },
- [12] = {
- ["item"] = "Mark as not built",
- ["func"] = function()
- local button = tBox.render(1,tTerm.x,"This will mark the current layer("..tScroll.layer..") as not built, so the turtle will build it.",2,0,".","Cancel","Ok")
- if button == "Cancel" then
- return --cancel
- end
- for ix=1,#tBlueprint[tScroll.layer] do
- for iz=1,#tBlueprint[tScroll.layer][ix] do
- local block = tBlueprint[tScroll.layer][ix][iz] or " "
- tBlueprint[tScroll.layer][ix][iz] = block:lower()
- end
- end
- end
- },
- [13] = {
- ["item"] = "Goto...",
- ["func"] = function()
- local button,layer,x,z = tBox.render(1,tTerm.x,"Goto layer, X, Z...",4,3,"%d","Cancel","Ok","Top","Bottom","Layer:","X:","Z:",tScroll.layer,tScroll.x.value,tScroll.y.value)
- if button == "Cancel" then
- return --cancel
- elseif button == "Top" then
- layer = #tBlueprint
- elseif button == "Bottom" then
- layer = 1
- elseif layer > #tBlueprint then
- local button = tBox.render(1,tTerm.x,"That layer does not exist! The top layer is "..#tBlueprint..". Go there?",2,0,".","Cancel","Ok")
- if button == "Cancel" then
- return
- else
- layer = #tBlueprint
- end
- end
- tScroll.layer = layer or tScroll.layer
- tScroll.x.value = x
- tScroll.y.value = z
- renderLayer(tScroll.layer)
- end
- },
- [14] = {
- ["item"] = "Go up 1",
- ["func"] = function()
- if tScroll.layer >= #tBlueprint then
- local button = tBox.render(1,tTerm.x,"Last layer reached! Create new?",2,0,".","Cancel","Ok")
- if button == "Cancel" then
- return --cancel
- else
- createLayer(tTerm.xCanvas,tTerm.zCanvas,#tBlueprint+1)
- tScroll.x.value = 0
- tScroll.y.value = 0
- end
- end
- tScroll.layer = tScroll.layer+1
- renderLayer(tScroll.layer)
- end
- },
- [15] = {
- ["item"] = "Go down 1",
- ["func"] = function()
- if tScroll.layer <= 1 then
- local button,layer = tBox.render(1,tTerm.x,"Unable to go below layer 1!")
- return
- end
- tScroll.layer = math.max(tScroll.layer-1,1)
- renderLayer(tScroll.layer)
- end
- }
- },
- ["Settings"] = {
- --program settings, for whatever modes i can come up with and other random bits and bobs
- [1] = {
- ["item"] = "Update",
- ["func"] = function()
- fs.delete(tFile.program)
- if tPaste.get(tPaste.program,tFile.program) then
- tBox.render(1,tTerm.x,"Update sucessful! Rebooting...")
- os.reboot()
- else
- tBox.render(1,tTerm.x,"Update failed. Returning to program")
- return
- end
- end
- },
- [2] = {
- ["item"] = "About",
- ["func"] = function()
- tBox.render(1,tTerm.x,"Turtle Architect is a turtle blueprint drawing and building program. Created by CometWolf.")
- end
- },
- [3] = {
- ["item"] = "Overwrite mode",
- ["func"] = function()
- local mode,buttonText
- if tTool.overwrite == true then
- mode = "on"
- buttonText = "Off"
- else
- mode = "off"
- buttonText = "On"
- end
- local button = tBox.render(1,tTerm.x,"Overwrite mode allowes any color to be painted onto any color. If it is off, all colors may be painted on white, but only white may be painted on any other color. Current mode: "..mode..".",2,0,".","Cancel",buttonText)
- if button == "On" then
- tTool.overwrite = true
- elseif button == "Off" then
- tTool.overwrite = false
- end
- end
- },
- [4] = {
- ["item"] = "Draw built mode",
- ["func"] = function()
- local mode,buttonText
- if tTool.built == true then
- mode = "on"
- buttonText = "Off"
- else
- mode = "off"
- buttonText = "On"
- end
- local button = tBox.render(1,tTerm.x,"This mode will allow you to draw blocks the turtle will consider already built, thus skipping them. Current mode: "..mode..".",2,0,".","Cancel",buttonText)
- if button == "On" then
- tTool.built = true
- elseif button == "Off" then
- tTool.built = false
- end
- end
- },
- [5] = {
- ["item"] = "Render built mode",
- ["func"] = function()
- local mode,buttonText
- if tTerm.built == true then
- mode = "on"
- buttonText = "Off"
- else
- mode = "off"
- buttonText = "On"
- end
- local button = tBox.render(1,tTerm.x,'This mode will render any blocks marked as built with a "B". These blocks will be skipped when a turtle builds the blueprint. Current mode: '..mode..".",2,0,".","Cancel",buttonText)
- if button == "On" then
- tTerm.built = true
- elseif button == "Off" then
- tTerm.built = false
- else
- return --cancel
- end
- renderLayer(tScroll.layer)
- end
- },
- [6] = {
- ["item"] = "Grid mode",
- ["func"] = function()
- local mode,buttonText
- if tTerm.grid == true then
- mode = "on"
- buttonText = "Off"
- else
- mode = "off"
- buttonText = "On"
- end
- local button = tBox.render(1,tTerm.x,"This mode draws a grid overlay on the canvas. Current mode: "..mode..".",2,0,".","Cancel",buttonText)
- if button == "On" then
- tTerm.grid = true
- renderLayer(tScroll.layer)
- elseif button == "Off" then
- tTerm.grid = false
- renderLayer(tScroll.layer)
- end
- end
- },
- [7] = {
- ["item"] = "Monitor mode",
- ["func"] = function()
- local mode,buttonText
- if #tMon > 0 then
- mode = "on"
- buttonText = "Off"
- else
- mode = "off"
- buttonText = "On"
- end
- local button = tBox.render(1,tTerm.x,"This mode displays the canvas on connected monitors aswell as the terminal, thus allowing input on both. Current mode: "..mode..".",2,0,".","Cancel",buttonText)
- if button == "On" then
- local tSides = rs.getSides()
- tMon = {}
- for is=1,#tSides do
- if peripheral.getType(tSides[is]) == "monitor" and peripheral.call(tSides[is],"isColor") then
- local button = tBox.render(1,tTerm.x,"Monitor on "..tSides[is].." found! Connect?",2,0,".","No","Yes")
- if button == "Yes" then
- tMon[#tMon+1] = peripheral.wrap(tSides[is])
- tMon[#tMon]["side"] = tSides[is]
- tMon[#tMon]["x"],tMon[#tMon]["y"] = tMon[#tMon]["getSize"]()
- tMon[#tMon]["xMid"] = math.ceil(tMon[#tMon]["x"]/2)
- tMon[#tMon]["yMid"] = math.ceil(tMon[#tMon]["y"]/2)
- tMon[#tMon]["xCanvas"] = tMon[#tMon]["x"] --total x veiwing area
- tMon[#tMon]["zCanvas"] = tMon[#tMon]["y"] --total y veiwing area
- end
- elseif peripheral.getType(tSides[is]) == "modem"
- and not peripheral.call(tSides[is],"isWireless") then
- local tPeripherals = peripheral.call(tSides[is],"getNamesRemote")
- for ip=1,#tPeripherals do
- if string.match(tPeripherals[ip],"monitor")
- and peripheral.call(tPeripherals[ip],"isColor") then
- local button = tBox.render(1,tTerm.x,"Monitor "..tPeripherals[ip].." found! Connect?",2,0,".","No","Yes")
- if button == "Yes" then
- tMon[#tMon+1] = peripheral.wrap(tPeripherals[ip])
- tMon[#tMon]["side"] = tPeripherals[ip]
- tMon[#tMon]["x"],tMon[#tMon]["y"] = tMon[#tMon]["getSize"]()
- tMon[#tMon]["xMid"] = math.ceil(tMon[#tMon]["x"]/2)
- tMon[#tMon]["yMid"] = math.ceil(tMon[#tMon]["y"]/2)
- tMon[#tMon]["xCanvas"] = tMon[#tMon]["x"] --total x veiwing area
- tMon[#tMon]["zCanvas"] = tMon[#tMon]["y"] --total y veiwing area
- end
- end
- end
- end
- end
- if #tMon < 1 then
- tBox.render(1,tTerm.x,"No monitor connected!")
- tMon = ""
- return
- end
- tMenuBar.render()
- renderLayer(tScroll.layer)
- elseif button == "Off" then
- for i=1,#tMon do
- tMon[i]["setBackgroundColor"](colors.black)
- tMon[i]["clear"]()
- end
- tMon = ""
- tMenuBar.render()
- renderLayer(tScroll.layer)
- end
- end
- },
- [8] = {
- ["item"] = "Background layer",
- ["func"] = function()
- local button,layerNum
- if tTerm.bgLayer then
- button,layerNum = tBox.render(1,tTerm.x,"This mode renders the selected layer below the one currently displayed, for easier visualization. Current mode: on, layer "..tTerm.bgNum..".",3,1,"%d","Cancel","Change","Off","Layer:",tTerm.bgNum)
- else
- button,layerNum = tBox.render(1,tTerm.x,"This mode renders the selected layer below the one currently displayed, for easier visualization. Current mode: Off.",2,1,"%d","Cancel","On","Layer:",math.max(tScroll.layer-1,1))
- end
- if button == "On" or button == "Change" then
- if layerNum > #tBlueprint then
- tBox.render(1,tTerm.x,"Layer "..layerNum.." does not exist!")
- return
- end
- tTerm.bgLayer = tBlueprint[layerNum]
- tTerm.bgNum = layerNum
- else
- tTerm.bgLayer = nil
- tTerm.bgNum = nil
- end
- renderLayer(tScroll.layer)
- end
- },
- [9] = {
- ["item"] = "Quit",
- ["func"] = function()
- local button = tBox.render(1,tTerm.x,"Are you sure you wish to quite? All unsaved work will be lost!",2,0,".","Cancel","Quit")
- if button == "Cancel" then
- return --cancel
- else
- for i=1,#tMon do
- tMon[i]["setBackgroundColor"](colors.black)
- tMon[i]["clear"]()
- end
- term.setBackgroundColor(colors.black)
- term.clear()
- term.setCursorPos(1,1)
- error()
- end
- end
- }
- },
- ["Tools"] = {
- --Tools menu, for chosing tools and colors
- [1] = {
- ["item"] = "Brush",
- ["func"] = function(button)
- tTool[button]["tool"] = "Brush"
- tTool.selector = {["enabled"] = disabled}
- tMenuBar.render("Size")
- end
- },
- [2] = {
- ["item"] = "Dragger",
- ["func"] = function(button)
- tTool[button]["tool"] = "Dragger"
- tTool.selector = {["enabled"] = disabled}
- tMenuBar.render()
- end
- },
- [3] = {
- ["item"] = "Fill",
- ["func"] = function(button)
- tTool[button]["tool"] = "Fill"
- tTool.selector = {["enabled"] = disabled}
- tMenuBar.render("Color")
- end
- },
- [4] = {
- ["item"] = "Square",
- ["func"] = function(button)
- tTool[button]["tool"] = "Square"
- tTool.selector = {["enabled"] = disabled}
- tMenuBar.render("Size")
- end
- },
- [5] = {
- ["item"] = "Circle",
- ["func"] = function(button)
- tTool[button]["tool"] = "Circle"
- tTool.selector = {["enabled"] = disabled}
- tTool.circle = {
- [1] = {},
- [2] = {}
- }
- tMenuBar.render("Color")
- end
- },
- [6] = {
- ["item"] = "Selector",
- ["func"] = function(button)
- tTool.selector = {["enabled"] = true}
- tTool[1]["tool"] = "Selector"
- tTool[2]["tool"] = "None"
- tMenuBar.render()
- end
- },
- },
- ["open"] = false, --currently open dropdown menu
- ["mainButton"] = " "..tText.menuButton.." ", --main menu button text
- ["Main"] = {},
- ["Size"] = {}
- }
- for i=1,9 do
- tMenuBar.Size[i] = {
- ["item"] = string.format(i),
- ["func"] = function(button)
- tTool[button]["size"] = i
- tMenuBar.render("Color")
- end
- }
- end
- tMenuBar.Color = {}
- tMenuBar.SlotColors = {}
- tMenuBar.Recolor = {}
- for k,v in pairs(colors) do
- if type(v) == "number" then
- tMenuBar.Color[#tMenuBar.Color+1] = {
- ["item"] = k:gsub("(^.)(%u)", function(l) if l:match"%u" then return " "..l:lower() else return l:upper() end end),
- ["func"] = function(button)
- tTool[button]["color"] = tColorNumsRev[v]
- tMenuBar.render()
- end,
- ["color"] = v,
- ["textColor"] = tColors.menuText,
- ["num"] = tColorNumsRev[v]
- }
- tColorString[v] = k
- tMenuBar.SlotColors[#tMenuBar.SlotColors+1] = {
- ["item"] = tMenuBar.Color[#tMenuBar.Color]["item"],
- ["textColor"] = tColors.menuText,
- ["color"] = v,
- ["func"] = function()
- colorSlots(tColorNumsRev[v])
- end
- }
- tMenuBar.Recolor[#tMenuBar.Recolor+1] = {
- ["item"] = tMenuBar.Color[#tMenuBar.Color]["item"],
- ["textColor"] = tColors.menuText,
- ["color"] = v,
- ["func"] = function()
- local t1 = tTool.selector[1]
- local t2 = tTool.selector[2] or t1
- selectorRecolor(tColorNumsRev[v],t1.x,t1.z,t2.x,t2.z,tScroll.layer)
- end
- }
- if k == "white" or k == "yellow" then
- tMenuBar.Color[#tMenuBar.Color]["textColor"] = colors.black
- tMenuBar.SlotColors[#tMenuBar.SlotColors]["textColor"] = colors.black
- tMenuBar.Recolor[#tMenuBar.Recolor]["textColor"] = colors.black
- end
- end
- end
- tMenuBar.Color[#tMenuBar.Color+1] = {
- ["item"] = "Break",
- ["func"] = function(button)
- tTool[button]["color"] = "x"
- tMenuBar.render()
- end,
- ["color"] = colors.lightGray,
- ["textColor"] = colors.red,
- ["num"] = "x"
- }
- tColorString.x = "break"
- tMenuBar.SlotColors[#tMenuBar.SlotColors+1] = {
- ["item"] = tMenuBar.Color[#tMenuBar.Color]["item"],
- ["textColor"] = tMenuBar.Color[#tMenuBar.Color]["textColor"],
- ["color"] = tMenuBar.Color[#tMenuBar.Color]["color"],
- ["func"] = function()
- colorSlots"x"
- end
- }
- tMenuBar.Recolor[#tMenuBar.Recolor+1] = {
- ["item"] = tMenuBar.Color[#tMenuBar.Color]["item"],
- ["textColor"] = tMenuBar.Color[#tMenuBar.Color]["textColor"],
- ["color"] = tMenuBar.Color[#tMenuBar.Color]["color"],
- ["func"] = function()
- local t1 = tTool.selector[1]
- local t2 = tTool.selector[2] or t1
- selectorRecolor("x",t1.x,t1.z,t2.x,t2.z,tScroll.layer)
- end
- }
- for k,v in pairs(tMenuBar) do
- --automatically makes rendering info for menus
- if k == "open"
- or k == "Main"
- or k == "mainButton"
- or type(v) == "function"
- or k == "Turtle" and not turtle then
- --skip string, open, and function keyes
- --will also skip turtle keyes if not running on a turtle
- else
- local longest = 0
- for i=1,#tMenuBar[k] do
- --find longest drop down selection for rendering purposes
- longest = math.max(longest,#tMenuBar[k][i]["item"])
- end
- tMenuBar[k]["length"] = math.max(longest,#k)+1
- tMenuBar[k]["startX"] = 1
- tMenuBar.Main.length = math.max(#k+1,tMenuBar.Main.length or 0)
- for i=1,#tMenuBar[k] do
- --equalize length of the dropdown menu names by adding spaces
- local item = tMenuBar[k][i]["item"]
- tMenuBar[k][i]["item"] = " "..item..string.rep(" ",math.max(0,tMenuBar[k]["length"]-#string.format(item)))
- end
- if k ~= "Size" and not k:lower():match"color" then
- table.insert(tMenuBar.Main,{
- ["item"] = " "..k,
- ["func"] = function()
- tMenuBar.render(k)
- end
- })
- end
- end
- end
- tMenuBar.Main.startX = 1
- tMenuBar.Size.startX = 1
- for i=1,#tMenuBar.Main do
- tMenuBar.Main[i]["item"] = tMenuBar.Main[i]["item"]..string.rep(" ",math.max(0,tMenuBar.Main.length-#tMenuBar.Main[i]["item"])).." >"
- end
- --[[
- --------------------------------------------------------------------------------------------------------------
- | Program functions |
- --------------------------------------------------------------------------------------------------------------
- --]]
- function debug(tVar,time)
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1,1)
- for k,v in pairs(tVar or {}) do
- print(k..": "..v)
- end
- local timer = os.startTimer(time or 5)
- while true do
- local event = os.pullEventRaw()
- if event == "key" or event == "timer" then
- return
- end
- end
- end
- function trimBlueprint(blueprint)
- --cleans blueprint files prior to saving, by removing empty x lines and trailing white spaces
- blueprint = blueprint or tBlueprint
- for layer = 1,#blueprint do
- for x = #blueprint[layer],1,-1 do
- local lastColor = 0
- for z = 1,#blueprint[layer][x] do
- local block = blueprint[layer][x][z] or " "
- if block ~= " " then
- lastColor = z+1
- end
- end
- if lastColor == 0 and #blueprint[layer] <= x then
- blueprint[layer][x] = nil
- else
- for i=lastColor,#blueprint[layer][x] do
- blueprint[layer][x][i] = nil
- end
- end
- end
- end
- end
- function fattenBlueprint(blueprint)
- --readds empty sapces to blueprint for flipping
- blueprint = blueprint or tBlueprint
- local largeX = 0
- local largeZ = 0
- for layer = 1,#blueprint do
- largeX = math.max(largeX,#blueprint[layer])
- for x = 1,#blueprint[layer] do
- largeZ = math.max(largeZ,#blueprint[layer][x])
- end
- end
- for layer=1,#blueprint do
- for x = 1,largeX do
- blueprint[layer][x] = blueprint[layer][x] or {}
- for z = 1,largeZ do
- blueprint[layer][x][z] = blueprint[layer][x][z] or " "
- end
- end
- end
- end
- function scan(x,z,layer,color)
- --Turtle function, scans a layer in the given measurements (x)x(z)
- --opionally loads it into the given layer, otherwise loads it into the first non-occupied layer
- layer = layer or tScroll.layer
- color = color or tTool[1]["color"]
- color = color:upper()
- local forward = cTurtle.dirStandardize"forward"
- local right = cTurtle.dirStandardize"right"
- tBlueprint[layer] = {}
- for ix=1,x do
- tBlueprint[layer][ix] = {}
- for iz=1,z do
- if turtle.detectDown() then
- tBlueprint[layer][ix][iz] = color
- else
- tBlueprint[layer][ix][iz] = " "
- end
- if iz < z then
- cTurtle.move(forward)
- end
- end
- if ix < x then
- cTurtle.move(right)
- forward = -forward
- end
- end
- renderLayer(tScroll.layer)
- end
- function colorCheck(from,to)
- --check layers for colors, returned as table[canvasColorCode] = colorString
- from = from or 1
- to = to or #tBlueprint
- local tColor = {}
- for il=from,to do
- for ix=1,#tBlueprint[il] do
- for iz=1,#tBlueprint[il][ix] do
- local color = tBlueprint[il][ix][iz] or " "
- if color ~= " " then
- if color:match(built) then
- color = color:lower()
- end
- if not tColor[color] then
- if color == "x" then
- tColor[color] = "break"
- else
- for k,v in pairs(colors) do
- if type(v) == "number" then
- if tColorNumsRev[v] == color then
- tColor[color] = k
- break
- end
- end
- end
- end
- end
- end
- end
- end
- end
- return tColor
- end
- function colorSlots(color)
- --edit color slots
- tColorSlots[color] = tColorSlots[color] or {}
- local from,to
- if tTerm.isColor then
- local button
- if color == "x" then
- if not tOngoing.breakMode then
- button,from = tBox.render(1,tTerm.x,"Input slot number for broken blocks. This slot will be used to pick up blocks and drop them instantly.",2,1,"%d","Cancel","Ok","Slot:",tColorSlots[color][1] or "15")
- to = from
- else
- return
- end
- else
- button,from,to = tBox.render(1,tTerm.x,"Input slot range for "..tColorString[tColorNums[color]]..".",2,2,"%d","Cancel","Ok","From:","To:",tColorSlots[color][1] or "1",tColorSlots[color][#tColorSlots[color]] or "16")
- end
- if button == "Cancel" then
- return false --cancel
- end
- else
- --non-color turtles
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1,1)
- if color == "x" then
- if not tOngoing.breakMode then
- print("Input slot number for broken blocks. This slot will be used to pick up blocks and drop them instantly.")
- term.write"From: "
- from = tonumber(read())
- to = from
- else
- return
- end
- else
- print("Input slot range for "..tColorString[tColorNums[color]]..".")
- term.write"From: "
- local cursX,cursY = term.getCursorPos()
- term.setCursorPos(1,cursY+1)
- term.write"To: "
- term.setCursorPos(cursX,cursY)
- from = tonumber(read())
- term.setCursorPos(5,cursY+1)
- to = tonumber(read())
- end
- end
- if from > to
- or to > 16
- or from < 1 then
- if tTerm.isColor then
- tBox.render(1,tTerm.x,"Faulty slot range "..from.."-"..to.." given!")
- else
- print("Faulty slot range "..from.."-"..to.." given!")
- end
- return
- end
- tColorSlots[color] = {}
- while from <= to do
- table.insert(tColorSlots[color],from)
- from = from+1
- end
- tColorSlots[color]["sColor"] = tColorString[tColorNums[color]]
- return true
- end
- function selectColor(colorNum)
- --turtle function, checks the slot range for the given color for blocks.
- --if none is found,a refill from the player is requested.
- while true do
- for i=1,#tColorSlots[colorNum] do
- local slot = tColorSlots[colorNum][i]
- if not tOngoing.breakMode and turtle.getItemCount(slot) > 0
- or tOngoing.breakMode and turtle.getItemCount(slot) > 1 then
- turtle.select(slot)
- return true
- end
- end
- local enderChestTimer
- if tOngoing.enderChest then
- if cTurtle.enderRestock(tOngoing.enderChest,tColorSlots[colorNum],tColorSlots[colorNum]) then
- for i=1,#tColorSlots[colorNum] do
- local slot = tColorSlots[colorNum][i]
- if turtle.getItemCount(slot) > 0 then
- turtle.select(slot)
- return true
- end
- end
- else
- enderChestTimer = os.startTimer(tTimer.enderChest)
- end
- end
- if tTerm.isColor then
- renderLayer(tScroll.layer)
- tMenuBar.render()
- local button = tBox.render(1,tTerm.x,"More blocks required in the "..tColorSlots[colorNum]["sColor"].." slot range "..tColorSlots[colorNum][1].."-"..tColorSlots[colorNum][#tColorSlots[colorNum]]..".",2,0,".","Cancel","Ok")
- if button == "cancel" then
- return false --cancel
- end
- else
- --input on non-color turtle
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1,1)
- print("More blocks required in the "..tColorSlots[colorNum]["sColor"].." slot range "..tColorSlots[colorNum][1].."-"..tColorSlots[colorNum][#tColorSlots[colorNum]]..[[.
- Press enter to recheck.
- Press backspace to quit build.]])
- local rednetTimer
- if modem then
- rednet.broadcast("More blocks required in the "..tColorSlots[colorNum]["sColor"].." slot range "..tColorSlots[colorNum][1].."-"..tColorSlots[colorNum][#tColorSlots[colorNum]]..[[.
- X: ]]..cTurtle.tPos.x..[[
- Y: ]]..cTurtle.tPos.y..[[
- Z: ]]..cTurtle.tPos.z)
- rednetTimer = os.startTimer(tTimer.rednet)
- end
- while true do
- local tEvent = {os.pullEvent()}
- if tEvent[1] == "key" then
- local key = tEvent[2]
- if key == 28 then --enter
- break
- elseif key == 14 then --backspace
- return
- end
- elseif tEvent[1] == "rednet_message" then
- local message = tEvent[3]
- if message == "" then
- end
- elseif tEvent[1] == "timer" then
- local timerID = tEvent[2]
- if timerID == rednetTimer then
- rednet.broadcast("More blocks required in the "..tColorSlots[colorNum]["sColor"].." slot range "..tColorSlots[colorNum][1].."-"..tColorSlots[colorNum][#tColorSlots[colorNum]]..[[.
- X: ]]..cTurtle.tPos.x..[[
- Y: ]]..cTurtle.tPos.y..[[
- Z: ]]..cTurtle.tPos.z)
- elseif timerID == enderChestTimer then
- break
- end
- end
- end
- end
- end
- end
- function checkUsage(startLayer,endLayer)
- --calculates fuel and block usage for the given layer range
- startLayer = startLayer or 1
- endLayer = endLayer or #tBlueprint
- local fuelUsage = 0
- local tColorBlocks = {}
- local ixFrom = 1
- local ixTo = #tBlueprint[startLayer]
- local ixAdd = 1
- local izFrom = 1
- local izTo = #tBlueprint[startLayer][1]
- local izAdd = 1
- local curX = 0
- local curY = 0
- local curZ = 0
- for layer=startLayer,endLayer do
- if layer%2 == 0 then
- ixFrom = #tBlueprint[layer]
- ixTo = 1
- ixAdd = -1
- else
- ixFrom = 1
- ixTo = #tBlueprint[layer]
- ixAdd = 1
- end
- for x=ixFrom,ixTo,ixAdd do
- if x%2 == 0 then
- izFrom = #tBlueprint[layer][x]
- izTo = 1
- izAdd = -1
- else
- izFrom = 1
- izTo = #tBlueprint[layer][x]
- izAdd = 1
- end
- for z=izFrom,izTo,izAdd do
- local block = tBlueprint[layer][x][z] or " "
- if block ~= " " then --checks for none white, racist turtle!
- tColorBlocks[block] = (tColorBlocks[block] or 0)+1
- if block:match(unbuilt) then --checks for built blocks
- fuelUsage = fuelUsage+math.abs(curX-x)+math.abs(curZ-z)
- curX = x
- curZ = z
- end
- end
- end
- end
- if layer < endLayer then
- if layer > curY then
- fuelUsage = fuelUsage+1
- curY = curY+1
- end
- end
- end
- return fuelUsage,tColorBlocks
- end
- function buildBlueprint(startLayer,endLayer,recovery)
- --turtle function, build the given layers
- --builds all layers if none is given
- startLayer = startLayer or 1
- endLayer = endLayer or #tBlueprint
- local colorTable = colorCheck(startLayer,endLayer)
- for k,v in pairs(colorTable) do
- if not tColorSlots[k] then
- if not colorSlots(k) then
- return
- end
- end
- end
- tOngoing.blueprint = tFile.curBlueprint
- tOngoing.startLayer = startLayer
- tOngoing.endLayer = endLayer
- tOngoing.enderChest = tOngoing.enderChest or false
- cTurtle.tSettings.enderFuel = tOngoing.enderChest
- --saves tOngoing
- local file = fs.open(tFile.ongoingBuild,"w")
- file.writeLine(textutils.serialize(tOngoing))
- file.close()
- if tOrigin.x and not recovery then
- if tOrigin.x ~= cTurtle.tPos.x
- or tOrigin.y ~= cTurtle.tPos.y
- or tOrigin.z ~= cTurtle.tPos.z then
- local button
- if tTerm.isColor then
- button = tBox.render(1,tTerm.x,"Use current build origin point|X: "..tOrigin.x.."|Y: "..tOrigin.y.."|Z: "..tOrigin.z.."|X dir: "..tOrigin.xDir.."|Z dir: "..tOrigin.zDir.."|Y dir: "..tOrigin.yDir.."|Or use current location?",3,0,".","Cancel","Current","Cur. loc")
- else
- button = noColorInput("Use current build origin point\nX: "..tOrigin.x.."\nY: "..tOrigin.y.."\nZ: "..tOrigin.z.."\nX dir: "..tOrigin.xDir.."\nZ dir: "..tOrigin.zDir.."\nY dir: "..tOrigin.yDir.."\nOr use current location?","Cancel","Current orgin","Cur. loc")
- end
- if button == "Cancel" then
- return
- elseif button == "Cur. loc" then
- tOrigin.x = cTurtle.tPos.x
- tOrigin.y = cTurtle.tPos.y
- tOrigin.z = cTurtle.tPos.z
- else
- cTurtle.moveTo(tOrigin.y,"y")
- end
- end
- elseif recovery then
- --skip
- else
- tOrigin.x = cTurtle.tPos.x
- tOrigin.y = cTurtle.tPos.y
- tOrigin.z = cTurtle.tPos.z
- tOrigin.xDir = "+"
- tOrigin.zDir = "+"
- tOrigin.yDir = "+"
- end
- saveBlueprint(tFile.curBlueprint)
- local ixFrom = 1
- local ixTo = #tBlueprint[startLayer]
- local ixAdd = 1
- local izFrom = 1
- local izTo = #tBlueprint[startLayer][1]
- local izAdd = 1
- local curSlot = 1
- local iLayerFrom
- local iLayerTo
- local iLayerAdd
- local placeFunc
- local compareFunc
- local digFunc
- if tOrigin.yDir == "-" then
- iLayerFrom = endLayer
- iLayerTo = startLayer
- iLayerAdd = -1
- down = true
- placeFunc = turtle.placeUp
- compareFunc = turtle.compareUp
- digFunc = turtle.digUp
- else
- iLayerFrom = startLayer
- iLayerTo = endLayer
- iLayerAdd = 1
- down = false
- placeFunc = turtle.placeDown
- compareFunc = turtle.compareDown
- digFunc = turtle.digDown
- end
- for layer=iLayerFrom,iLayerTo,iLayerAdd do
- if layer%2 == 0 then
- ixFrom = #tBlueprint[layer]
- ixTo = 1
- ixAdd = -1
- else
- ixFrom = 1
- ixTo = #tBlueprint[layer]
- ixAdd = 1
- end
- for x=ixFrom,ixTo,ixAdd do
- if x%2 == 0 then
- izFrom = #tBlueprint[layer][x]
- izTo = 1
- izAdd = -1
- else
- izFrom = 0
- izTo = #tBlueprint[layer][x]
- izAdd = 1
- end
- for z=izFrom,izTo,izAdd do
- local block = tBlueprint[layer][x][z] or " "
- if block ~= " " --checks for none white, racist turtle!
- and block:match(unbuilt) then --checks for built blocks
- if tOrigin.xDir == "-" then
- cTurtle.moveTo(tOrigin.x-x+1,"x",tOngoing.breakMode)
- else
- cTurtle.moveTo(tOrigin.x+x-1,"x",tOngoing.breakMode)
- end
- if tOrigin.zDir == "-" then
- cTurtle.moveTo(tOrigin.z-z+1,"z",tOngoing.breakMode)
- else
- cTurtle.moveTo(tOrigin.z+z-1,"z",tOngoing.breakMode)
- end
- if block == "x" then
- if not tOngoing.breakMode then
- turtle.select(tColorSlots.x[1])
- end
- while turtle.detectDown() do
- turtle.digDown()
- if not tOngoing.breakMode then
- turtle.dropDown(64)
- end
- end
- else
- if not selectColor(block) then
- return --cancel
- end
- if not compareFunc() then
- while not placeFunc() do
- digFunc()
- end
- end
- end
- tBlueprint[layer][x][z] = block:upper() --marks this block as built
- saveBlueprint(tFile.curBlueprint)
- end
- end
- end
- if not down and layer < iLayerTo then
- if tOrigin.y+layer > cTurtle.tPos.y then
- cTurtle.moveTo(tOrigin.y+layer,"y",tOngoing.breakMode)
- end
- elseif down and layer > iLayerTo then
- if tOrigin.y+layer-iLayerFrom-1 < cTurtle.tPos.y then
- cTurtle.moveTo(tOrigin.y+layer-iLayerFrom-1,"y",tOngoing.breakMode)
- end
- else
- cTurtle.moveTo(tOrigin.x,"x")
- cTurtle.moveTo(tOrigin.z,"z")
- cTurtle.moveTo(tOrigin.y,"y")
- end
- end
- fs.delete(tFile.ongoingBuild) --clears ongoing build
- if tTerm.isColor then
- tMenuBar.render()
- renderLayer(tScroll.layer)
- end
- end
- function createLayer(x,z,layerNum,overwrite)
- --simple layer creation function
- if overwrite then
- tBlueprint[layerNum or #tBlueprint+1] = {}
- else
- table.insert(tBlueprint,layerNum or #tBlueprint+1,{})
- end
- x = math.max(x or 0,tTerm.xCanvas)
- z = math.max(z or 0,tTerm.zCanvas)
- for ix=1,x do
- tBlueprint[layerNum][ix] = {}
- for iz=1,z do
- tBlueprint[layerNum][ix][iz] = " "
- end
- end
- end
- function copyLayer(layer)
- --creates a copy layer
- local layerCopy = {}
- for ix=1,#tBlueprint[layer] do
- layerCopy[ix] = {}
- for iz=1,#tBlueprint[layer][ix] do
- layerCopy[ix][iz] = tBlueprint[tScroll.layer][ix][iz] or " "
- end
- end
- return layerCopy
- end
- function flipLayer(layer,direction)
- --flips layer vertically or horizontally
- local layerFlipped = {}
- if direction == "x" then
- for ix=#layer,1,-1 do
- layerFlipped[#layerFlipped+1] = {}
- for iz=1,#layer[ix] do
- layerFlipped[#layerFlipped][iz] = layer[ix][iz] or " "
- end
- end
- else
- for ix=1,#layer do
- layerFlipped[ix] = {}
- for iz=#layer[ix],1,-1 do
- layerFlipped[ix][#layerFlipped[ix]+1] = layer[ix][iz] or " "
- end
- end
- end
- return layerFlipped
- end
- function layerPaste(layer,num,overwrite)
- --pastes layer into tBlueprint, this is used to avoid recursive tables
- if overwrite then
- tBlueprint[num] = {}
- else
- table.insert(tBlueprint,num,{})
- end
- for ix=1,#layer do
- tBlueprint[num][ix] = {}
- for iz=1,#layer[ix] do
- tBlueprint[num][ix][iz] = layer[ix][iz]
- end
- end
- end
- function layerCombine(from,to,recolor)
- --combines layers in the range (from) (to), optionally gives them each an unique color
- local layerComb = {}
- for i=from,to do
- local color = i-from+1
- while color > 15 do
- color = color-15
- end
- if color > 9 then
- if color-9 == 1 then
- color = "a"
- elseif color-9 == 2 then
- color = "b"
- elseif color-9 == 3 then
- color = "c"
- elseif color-9 == 4 then
- color = "d"
- elseif color-9 == 5 then
- color = "e"
- elseif color-9 == 6 then
- color = "f"
- end
- else
- color = string.format(color)
- end
- for ix=1,#tBlueprint[i] do
- layerComb[ix] = layerComb[ix] or {}
- for iz=1,#tBlueprint[i][ix] do
- if tBlueprint[i][ix][iz] > " " then
- if recolor then
- layerComb[ix][iz] = color
- else
- layerComb[ix][iz] = tBlueprint[i][ix][iz]
- end
- else
- layerComb[ix][iz] = layerComb[ix][iz] or " "
- end
- end
- end
- end
- return layerComb
- end
- function renderLayer(layer)
- --Renders the give layer on the canvas
- --if none, renders currently viewed layer
- layer = layer or tScroll.layer
- if not tBlueprint[layer] then
- createLayer(tTerm.xCanvas,tTerm.zCanvas,layer,true)
- end
- local canvasX = tTerm.xCanvas
- local canvasZ = tTerm.zCanvas
- local gridLine = "1234567890"
- if tTerm.grid then
- --terminal grid line rendering
- canvasX = canvasX-1
- canvasZ = canvasZ-1
- term.setCursorPos(1,tTerm.y)
- term.setBackgroundColor(tColors.gridBorder)
- term.setTextColor(tColors.gridBorderText)
- term.write(gridLine:rep(math.ceil(canvasX/#gridLine)).." ")
- gridLine = 1
- for i=2,tTerm.y-1 do
- term.setCursorPos(tTerm.x,i)
- term.write(gridLine)
- gridLine = gridLine+1
- if gridLine > 9 then
- gridLine = 0
- end
- end
- for im=1,#tMon do
- --monitor gird line rendering
- gridLine = "1234567890"
- tMon[im]["setCursorPos"](1,tMon[im]["y"])
- tMon[im]["setBackgroundColor"](tColors.gridBorder)
- tMon[im]["setTextColor"](tColors.gridBorderText)
- tMon[im]["write"](gridLine:rep(math.ceil(tMon[im]["xCanvas"]/#gridLine)).." ")
- gridLine = 1
- for iy=1,tMon[im]["y"]-1 do
- tMon[im]["setCursorPos"](tMon[im]["x"],iy)
- tMon[im]["write"](gridLine)
- gridLine = gridLine+1
- if gridLine > 9 then
- gridLine = 0
- end
- end
- end
- end
- for x=1+tScroll.x.value,canvasX+tScroll.x.value do -- render current layer on terminal
- tBlueprint[layer][x] = tBlueprint[layer][x] or {}
- if tTerm.bgLayer then
- tTerm.bgLayer[x] = tTerm.bgLayer[x] or {}
- end
- for z=1+tScroll.y.value,canvasZ+tScroll.y.value do
- tBlueprint[layer][x][z] = tBlueprint[layer][x][z] or " "
- local color = tBlueprint[layer][x][z]
- local bgColor
- if tTerm.bgLayer then
- bgColor = tTerm.bgLayer[x][z] or " "
- end
- if tTerm.grid then
- --grid mode
- if color == " " then
- term.setTextColor(tColors.gridBackgroundText)
- if bgColor and bgColor ~= " " then
- --layer background
- term.setBackgroundColor(tColors.backgroundLayer)
- else
- term.setBackgroundColor(tColors.gridBackground)
- end
- elseif tTerm.built and color:match(built) then
- term.setTextColor(tColors.builtMark)
- term.setBackgroundColor(tColorNums[color])
- else
- term.setTextColor(tColors.gridBackgroundText)
- term.setBackgroundColor(tColorNums[color])
- end
- term.setCursorPos(x-tScroll.x.value,z-tScroll.y.value+1)
- if tTerm.built and color:match(built) and color ~= "X" then
- --built render mode
- term.write"B"
- elseif color == "x" then
- term.setTextColor(colors.lightGray)
- term.write"X"
- else
- term.write"+"
- end
- else
- --non grid mode
- if color == " " and bgColor and bgColor ~= " " then
- --layer background
- term.setBackgroundColor(tColors.backgroundLayer)
- else
- term.setBackgroundColor(tColorNums[color])
- end
- term.setCursorPos(x-tScroll.x.value,z-tScroll.y.value+1)
- if tTerm.built and color:match(built) and color ~= "X" then
- term.setTextColor(tColors.builtMark)
- term.write"B"
- elseif color == "x" then
- term.setTextColor(colors.lightGray)
- term.write"X"
- else
- term.write" "
- end
- end
- end
- end
- for i=1,#tMon do
- local xCanvas = tMon[i]["xCanvas"]
- local zCanvas = tMon[i]["zCanvas"]
- if tTerm.grid then
- --grid mode prep
- xCanvas = xCanvas-1
- zCanvas = zCanvas-1
- tMon[i]["setTextColor"](tColors.gridBackgroundText)
- end
- for x=1+tScroll.x.value,xCanvas+tScroll.x.value do
- tBlueprint[layer][x] = tBlueprint[layer][x] or {}
- for z=1+tScroll.y.value,zCanvas+tScroll.y.value do
- tBlueprint[layer][x][z] = tBlueprint[layer][x][z] or " "
- if tTerm.grid then
- --grid mode
- local marker = "+"
- if tBlueprint[layer][x][z] == " " then
- if tTerm.bgLayer and tTerm.bgLayer[x][z] ~= " " then
- --layer background
- tMon[i]["setBackgroundColor"](tColors.backgroundLayer)
- else
- tMon[i]["setBackgroundColor"](tColors.gridBackground)
- end
- else
- tMon[i]["setBackgroundColor"](tColorNums[tBlueprint[layer][x][z]])
- marker = "X"
- end
- tMon[i]["setCursorPos"](x-tScroll.x.value,z-tScroll.y.value)
- tMon[i]["write"](marker)
- else
- --non grid mode
- local color = tBlueprint[layer][x][z]
- if color == " " and tTerm.bgLayer and tTerm.bgLayer[x][z] ~= " " then
- --layer background
- color = tColors.backgroundLayer
- else
- color = tColorNums[color]
- end
- paintutils.drawPixel(x-tScroll.x.value,z-tScroll.y.value,color,true)
- end
- end
- end
- end
- selectorRender()
- circleRender()
- --update menuBar info
- tMenuBar.infoString = "X:"..tScroll.x.value.." Y:"..layer.." Z:"..tScroll.y.value
- paintutils.drawLine(tMenuBar.Main.length+2,1,tTerm.x,1,tColors.menuBar)
- term.setBackgroundColor(tColors.menuBar)
- term.setTextColor(tColors.infoText)
- term.setCursorPos(tTerm.x-#tMenuBar.infoString,1)
- term.write(tMenuBar.infoString)
- term.setCursorPos(#tMenuBar.mainButton+2,1)
- term.setBackgroundColor(tColors.menuBar)
- term.write"1: "
- if tColorNums[tTool[1]["color"]] ~= tColors.menuBar and tTool[1]["tool"] ~= "Selector" then
- term.setTextColor(tColorNums[tTool[1]["color"]])
- end
- term.write(tTool[1]["tool"])
- term.setTextColor(tColors.infoText)
- if tTool.selector.enabled then
- return
- elseif tTool[1]["tool"] ~= "Dragger"
- and tTool[1]["tool"] ~= "Fill"
- and tTool[1]["tool"] ~= "Circle" then
- term.write(":"..tTool[1]["size"].." 2: ")
- else
- term.write(" 2: ")
- end
- if tColorNums[tTool[2]["color"]] ~= tColors.menuBar then
- term.setTextColor(tColorNums[tTool[2]["color"]])
- end
- term.write(tTool[2]["tool"])
- if tTool[2]["tool"] ~= "Dragger"
- and tTool[2]["tool"] ~= "Fill"
- and tTool[2]["tool"] ~= "Circle" then
- term.setTextColor(tColors.infoText)
- term.write(":"..tTool[2]["size"])
- end
- end
- function renderPoint(x,z,color,replace)
- --base rendering functions, this is used for everything except full canvas rendering
- local canvasX = tTerm.xCanvas
- local canvasZ = tTerm.zCanvas
- local marker = " "
- if tTerm.grid then
- canvasX = canvasX-1
- canvasZ = canvasZ-1
- term.setTextColor(tColors.gridBackgroundText)
- marker = "+"
- end
- if x < 1
- or z < 1 then
- return
- end
- replace = replace or tTool.overwrite
- local layer = tScroll.layer
- if tTool.built and color ~= " " and color ~= "x" then --built mode
- color = color:upper()
- end
- if tTerm.built and color:match(built) and color ~= "X" then
- term.setTextColor(tColors.builtMark)
- marker = "B"
- elseif color == "x" then
- term.setTextColor(colors.lightGray)
- marker = "X"
- end
- xP = x+tScroll.x.value
- zP = z+tScroll.y.value
- tBlueprint[layer][xP] = tBlueprint[layer][xP] or {}
- tBlueprint[layer][xP][zP] = tBlueprint[layer][xP][zP] or " "
- if replace --overwrite mode enabled
- or tBlueprint[layer][xP][zP] == " " --or point color is white
- or color == " " then --or current color is white
- tBlueprint[layer][xP][zP] = color or tBlueprint[layer][xP][zP]
- if tTerm.grid then
- if color == " " then
- local color = tColors.gridBackground
- if tTerm.bgLayer and tTerm.bgLayer[xP][zP] ~= " " then
- color = tColors.backgroundLayer
- marker = " "
- end
- term.setBackgroundColor(color)
- for i=1,#tMon do
- tMon[i]["setBackgroundColor"](color)
- end
- else
- term.setBackgroundColor(tColorNums[color])
- for i=1,#tMon do
- tMon[i]["setBackgroundColor"](tColorNums[color])
- end
- end
- if x <= tTerm.xCanvas-1
- and z <= tTerm.zCanvas-1 then
- term.setCursorPos(x,z+1)
- term.write(marker)
- end
- for i=1,#tMon do
- if x <= tMon[i]["xCanvas"]-1
- and z <= tMon[i]["zCanvas"]-1 then
- tMon[i]["setCursorPos"](x,z)
- tMon[i]["write"](marker)
- end
- end
- else
- if color == " " and tTerm.bgLayer and tTerm.bgLayer[xP][zP] ~= " " then
- color = tColors.backgroundLayer
- else
- color = tColorNums[color] or tColorNums[tBlueprint[layer][xP][zP]]
- end
- term.setBackgroundColor(color)
- term.setCursorPos(x,z+1)
- term.write(marker)
- for i=1,#tMon do
- tMon[i]["setBackgroundColor"](color)
- tMon[i]["setCursorPos"](x,z)
- tMon[i]["write"](marker)
- end
- end
- end
- end
- function renderLine(startX,endX,z,color)
- --renders horizontinal canvas lines
- for i=startX,endX do
- renderPoint(i,z,color)
- end
- end
- local function renderWall(startZ,endZ,x,color)
- --renders vertical canvas lines
- for i=startZ,endZ do
- renderPoint(x,i,color)
- end
- end
- function saveBlueprint(fileName)
- --saves the blueprint to file
- trimBlueprint(tBlueprint)
- local file = fs.open(fileName,"w")
- file.writeLine("Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program)
- for layer=1,#tBlueprint do
- file.writeLine("Layer "..layer.." :")
- for x=1,#tBlueprint[layer] do
- local line = "X"..x..string.rep(" ",#string.format(#tBlueprint[layer])-#string.format(x))..": "
- for z=1,#tBlueprint[layer][x] do
- local block = tBlueprint[layer][x][z] or " "
- line = line..block
- end
- file.writeLine(line)
- end
- end
- if tColorSlots then
- file.writeLine"Color slots table:"
- file.writeLine(textutils.serialize(tColorSlots))
- end
- if tOrigin then
- file.writeLine"Build origin data:"
- file.writeLine(textutils.serialize(tOrigin))
- end
- file.close()
- end
- function loadBlueprint(fileName)
- --loads blueprint from file
- local file = fs.open(fileName,"r")
- local tRetBlueprint = {}
- local tRetColors
- local tRetOrigin
- if file.readLine() == "Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program then
- local line = file.readLine()
- while line:match"Layer %d+" do
- local layer = tonumber(line:match"%d+")
- tRetBlueprint[layer] = {}
- line = file.readLine()
- while line:match"X%d+" do
- local x = tonumber(line:match"X(%d+)")
- line = line:match"X%d+%s?:%s(.+)" or ""
- tRetBlueprint[layer][x] = {}
- for block in line:gmatch"." do
- tRetBlueprint[layer][x][#tRetBlueprint[layer][x]+1] = string.format(block)
- end
- line = file.readLine()
- end
- end
- if line:match"Color slots table:" then
- tRetColors = textutils.unserialize(file.readLine())
- line = file.readLine() or ""
- end
- if line:match"Build origin data:" then
- tRetOrigin = textutils.unserialize(file.readLine())
- end
- end
- file.close()
- if #tRetBlueprint <= 0 then
- tRetBlueprint = false
- end
- return tRetBlueprint, tRetColors or {}, tRetOrigin or {}
- end
- function loadOldBlueprint(fileName)
- --loads blueprint from file
- local file = fs.open(fileName,"r")
- local tRetBlueprint
- local tRetColors
- if file.readLine() == "Blueprint file for CometWolf's Turtle Architect. Pastebin: "..tPaste.program then
- tRetBlueprint = textutils.unserialize(file.readLine())
- tRetColors = file.readLine()
- if tRetColors then
- tRetColors = textutils.unserialize(tRetColors)
- end
- end
- file.close()
- return tRetBlueprint or false, tRetColors or false
- end
- function noColorInput(text,...)
- term.clear()
- term.setCursorPos(1,1)
- print(text)
- local cursX,cursY = term.getCursorPos()
- local button = 1
- local tButtons = {...}
- while true do
- for i=1,#tButtons do
- local menuText = tButtons[i]
- if button == i then
- menuText = "["..menuText.."]"
- end
- term.setCursorPos(1,cursY+i-1)
- term.clearLine()
- term.setCursorPos(tTerm.xMid-math.floor(#menuText/2),cursY+i-1)
- term.write(menuText)
- end
- local _e,key = os.pullEvent"key"
- if key == 28 then --enter
- return tButtons[button]
- elseif key == 208 then --down arrow
- button = button+1
- elseif key == 200 then --up arrow
- button = button-1
- end
- if button > #tButtons then
- button = 1
- elseif button < 1 then
- button = #tButtons
- end
- end
- end
- function tMenuBar.render(menu)
- --renders top bar menu, and dropdown (menu)
- local func
- if type(menu) == "function" then
- func = menu
- menu = nil
- end
- renderLayer(tScroll.layer)
- tMenuBar.infoString = "X:"..tScroll.x.value.." Y:"..tScroll.layer.." Z:"..tScroll.y.value
- paintutils.drawLine(1,1,tTerm.x,1,tColors.menuBar)
- term.setBackgroundColor(tColors.menuBar)
- term.setTextColor(tColors.infoText)
- term.setCursorPos(tTerm.x-#tMenuBar.infoString,1)
- term.write(tMenuBar.infoString)
- if not menu then
- tMenuBar.open = false
- term.setTextColor(tColors.menuText)
- term.setBackgroundColor(tColors.menuButton)
- term.setCursorPos(1,1)
- term.write(" "..tText.menuButton.." ")
- tMenuBar.mainButton = " "..tText.menuButton.." "
- else
- --dropdown menu
- tMenuBar.open = menu
- term.setCursorPos(1,1)
- term.setBackgroundColor(tColors.menuDropDownPri)
- local menuString = "["..menu..string.rep(" ",math.max(0,tMenuBar.Main.length-#menu-1)).."]"
- term.write(menuString)
- tMenuBar.mainButton = menuString
- for i=1,#tMenuBar[menu] do
- if tMenuBar[menu][i]["color"] then
- term.setBackgroundColor(tMenuBar[menu][i]["color"])
- term.setTextColor(tMenuBar[menu][i]["textColor"])
- elseif i%2 == 0 then
- term.setBackgroundColor(tColors.menuDropDownPri)
- else
- term.setBackgroundColor(tColors.menuDropDownSec)
- end
- local cursX,cursY = tMenuBar[menu]["startX"], i+1
- if cursY > tTerm.y then
- cursY = cursY-(tTerm.y-1)
- cursX = #tMenuBar[menu][i]["item"]+1
- end
- term.setCursorPos(cursX,cursY)
- term.write(tMenuBar[menu][i]["item"])
- end
- end
- --menu bar info
- term.setTextColor(tColors.infoText)
- term.setCursorPos(#tMenuBar.mainButton+2,1)
- term.setBackgroundColor(tColors.menuBar)
- term.write"1: "
- if tColorNums[tTool[1]["color"]] ~= tColors.menuBar and tTool[1]["tool"] ~= "Selector" then
- term.setTextColor(tColorNums[tTool[1]["color"]])
- end
- term.write(tTool[1]["tool"])
- term.setTextColor(tColors.infoText)
- if tTool.selector.enabled then
- return
- elseif tTool[1]["tool"] ~= "Dragger"
- and tTool[1]["tool"] ~= "Fill"
- and tTool[1]["tool"] ~= "Circle" then
- term.write(":"..tTool[1]["size"].." 2: ")
- else
- term.write(" 2: ")
- end
- if tColorNums[tTool[2]["color"]] ~= tColors.menuBar then
- term.setTextColor(tColorNums[tTool[2]["color"]])
- end
- term.write(tTool[2]["tool"])
- if tTool[2]["tool"] ~= "Dragger"
- and tTool[2]["tool"] ~= "Fill"
- and tTool[2]["tool"] ~= "Selector"
- and tTool[2]["tool"] ~= "Circle" then
- term.setTextColor(tColors.infoText)
- term.write(":"..tTool[2]["size"])
- end
- if func then
- func()
- end
- end
- function tContextMenu.render(x,y)
- renderLayer(tScroll.layer)
- x = math.min(x,tTerm.x-tContextMenu.length)
- y = math.min(y,tTerm.y-#tContextMenu+1)
- for i=1,#tContextMenu do
- term.setCursorPos(x,y+i-1)
- if i%2 == 0 then
- term.setBackgroundColor(tColors.contextMenuPri)
- else
- term.setBackgroundColor(tColors.contextMenuSec)
- end
- if tContextMenu[i]["item"]:match"Paste" then
- if not tTool.selector.copy then
- term.setTextColor(colors.lightGray)
- else
- term.setTextColor(tColors.contextMenuText)
- end
- elseif tContextMenu[i]["item"]:match"Copy"
- or tContextMenu[i]["item"]:match"Cut"
- or tContextMenu[i]["item"]:match"Select"
- or tContextMenu[i]["item"]:match"Delete"
- or tContextMenu[i]["item"]:match"Recolor" then
- if not tTool.selector[1]
- or tTool.selector.copy then
- term.setTextColor(colors.lightGray)
- else
- term.setTextColor(tColors.contextMenuText)
- end
- elseif not tTool.selector[1] and not tTool.selector.paste then
- term.setTextColor(colors.lightGray)
- else
- term.setTextColor(tColors.contextMenuText)
- end
- term.write(tContextMenu[i]["item"])
- end
- tContextMenu.x = x
- tContextMenu.y = y
- tContextMenu.open = true
- end
- function getFunc(menu,func)
- --gets the desired function from the menu table
- local menu = tMenuBar[menu]
- for i=1,#menu do
- if menu[i]["item"]:match(func) then
- return menu[i]["func"]
- end
- end
- end
- function tMenuBar.click(clickX,clickY)
- --determines what menu was clicked, if any
- local open = tMenuBar.open
- if clickY == 1 then
- if clickX <= #tMenuBar.mainButton then
- return "Main"
- elseif clickX >= tTerm.x-#tMenuBar.infoString then
- return getFunc("Layer","Goto...")
- end
- elseif open then
- --drop down menu click
- if tMenuBar[open]["startX"] <= clickX and tMenuBar[open]["startX"]+tMenuBar[open]["length"]+1 >= clickX
- and #tMenuBar[open] >= clickY-1 then
- return tMenuBar[open][clickY-1]["func"]
- elseif #tMenuBar[open] > tTerm.y-1 and tMenuBar[open]["startX"]+tMenuBar[open]["length"]+1 <= clickX
- and clickX <= tMenuBar[open]["startX"]+(tMenuBar[open]["length"]*2)+1
- and #tMenuBar[open]-(tTerm.y-1) >= clickY-1 then
- return tMenuBar[open][clickY-2+tTerm.y]["func"]
- end
- end
- return false
- --no menu clicked
- end
- function tContextMenu.click(clickX,clickY)
- --determines what menu was clicked, if any
- if not tContextMenu.open then
- return false
- end
- if clickY == 1 then
- if clickX <= #tMenuBar.mainButton then
- return tMenuBar.render"main"
- elseif clickX >= tTerm.x-#tMenuBar.infoString then
- return getFunc("Layer","Goto...")
- end
- else
- --drop down menu click
- if tContextMenu.x <= clickX and tContextMenu.x+tContextMenu.length+1 >= clickX
- and tContextMenu[clickY-tContextMenu.y+1] then
- return tContextMenu[clickY-tContextMenu.y+1]["func"]
- end
- end
- return false
- --no menu clicked
- end
- function brushExpand(tPointData,color)
- --brush tool function
- local tAffectedPoints = {}
- for i=1,#tPointData do
- local layer = tPointData[i]["layer"]
- local x = tPointData[i]["x"]+1
- local z = tPointData[i]["z"]
- if tBlueprint[layer][x] and tBlueprint[layer][x][z] then
- renderPoint(x-tScroll.x.value,z-tScroll.y.value,color)
- table.insert(tAffectedPoints,{["layer"] = layer,["x"] = x,["z"] = z})
- end
- x = tPointData[i]["x"]-1
- if tBlueprint[layer][x] and tBlueprint[layer][x][z] then
- renderPoint(x-tScroll.x.value,z-tScroll.y.value,color)
- table.insert(tAffectedPoints,{["layer"] = layer,["x"] = x,["z"] = z})
- end
- x = tPointData[i]["x"]
- z = tPointData[i]["z"]+1
- if tBlueprint[layer][x] and tBlueprint[layer][x][z] then
- renderPoint(x-tScroll.x.value,z-tScroll.y.value,color)
- table.insert(tAffectedPoints,{["layer"] = layer,["x"] = x,["z"] = z})
- end
- z = tPointData[i]["z"]-1
- if tBlueprint[layer][x] and tBlueprint[layer][x][z] then
- renderPoint(x-tScroll.x.value,z-tScroll.y.value,color)
- table.insert(tAffectedPoints,{["layer"] = layer,["x"] = x,["z"] = z})
- end
- end
- return tAffectedPoints
- end
- function squareExpand(x,z,color,size)
- --square tool function
- renderPoint(x,z,color)
- if size == 2 then
- renderPoint(x+1,z,color)
- renderPoint(x+1,z+1,color)
- renderPoint(x,z+1,color)
- elseif size > 2 then
- for i=1,size-2 do
- renderWall(z-i,z+i,x+i,color)
- renderWall(z-i,z+i,x-i,color)
- renderLine(x-i,x+i,z+i,color)
- renderLine(x-i,x+i,z-i,color)
- end
- end
- end
- function fillExpand(x,z,layer,replaceColor,fillColor)
- --fill tool function
- if fillColor == replaceColor then
- return
- end
- renderPoint(x,z,fillColor,true)
- local tAffectedPoints = {}
- tAffectedPoints[1] = {["x"] = x+tScroll.x.value, ["z"] = z+tScroll.y.value}
- local loops = 0
- local tPoints = {}
- while #tAffectedPoints > 0 do
- if loops%50 == 0 then
- sleep(0.05)
- end
- local x = tAffectedPoints[1]["x"]+1
- local z = tAffectedPoints[1]["z"]
- if not (tPoints[x] and tPoints[x][z])
- and tBlueprint[layer][x] and tBlueprint[layer][x][z] and tBlueprint[layer][x][z] == replaceColor then
- renderPoint(x-tScroll.x.value,z-tScroll.y.value,fillColor,true)
- tPoints[x] = tPoints[x] or {}
- tPoints[x][z] = true
- table.insert(tAffectedPoints,{["x"] = x,["z"] = z})
- end
- x = tAffectedPoints[1]["x"]-1
- if not (tPoints[x] and tPoints[x][z])
- and tBlueprint[layer][x] and tBlueprint[layer][x][z] and tBlueprint[layer][x][z] == replaceColor then
- renderPoint(x-tScroll.x.value,z-tScroll.y.value,fillColor,true)
- tPoints[x] = tPoints[x] or {}
- tPoints[x][z] = true
- table.insert(tAffectedPoints,{["x"] = x,["z"] = z})
- end
- x = tAffectedPoints[1]["x"]
- z = tAffectedPoints[1]["z"]+1
- if not (tPoints[x] and tPoints[x][z])
- and tBlueprint[layer][x] and tBlueprint[layer][x][z] and tBlueprint[layer][x][z] == replaceColor then
- renderPoint(x-tScroll.x.value,z-tScroll.y.value,fillColor,true)
- tPoints[x] = tPoints[x] or {}
- tPoints[x][z] = true
- table.insert(tAffectedPoints,{["x"] = x,["z"] = z})
- end
- z = tAffectedPoints[1]["z"]-1
- if not (tPoints[x] and tPoints[x][z])
- and tBlueprint[layer][x] and tBlueprint[layer][x][z] and tBlueprint[layer][x][z] == replaceColor then
- renderPoint(x-tScroll.x.value,z-tScroll.y.value,fillColor,true)
- tPoints[x] = tPoints[x] or {}
- tPoints[x][z] = true
- table.insert(tAffectedPoints,{["x"] = x,["z"] = z})
- end
- table.remove(tAffectedPoints,1)
- loops = loops+1
- end
- end
- function selectorRender(x,y)
- --renders paste or selection on canvas
- if not tTool.selector[1] or not tTool.selector.enabled then
- return
- elseif not tTool.selector[2] then
- tTool.selector[2] = {
- ["x"] = tTool.selector[1]["x"],
- ["z"] = tTool.selector[1]["z"]
- }
- end
- local x1 = tTool.selector[1]["x"]-tScroll.x.value+(x or 0)
- local x2 = tTool.selector[2]["x"]-tScroll.x.value+(x or 0)
- local z1 = tTool.selector[1]["z"]-tScroll.y.value+(y or 0)+1
- local z2 = tTool.selector[2]["z"]-tScroll.y.value+(y or 0)+1
- local canvasEdge = tTerm.y
- if tTerm.grid then
- canvasEdge = canvasEdge-1
- end
- local paste = tTool.selector.copy
- if paste then
- local x = (x or x1)-1
- local z = (y or z1)-1
- for ix=1,#paste do
- for iz=1,#paste[ix] do
- local color = paste[ix][iz]
- if color ~= " " and iz+z >= 2 and iz+z <= canvasEdge then
- paintutils.drawPixel(ix+x,iz+z,tColorNums[color])
- end
- end
- end
- else
- if z1 >= 2 and z1 <= canvasEdge then
- paintutils.drawLine(x1,z1,x2,z1,tColors.selector)
- if z2 >= 2 and z2 <= canvasEdge then
- paintutils.drawLine(x2,z2,x1,z2,tColors.selector)
- else
- z2 = canvasEdge
- end
- paintutils.drawLine(x2,z1,x2,z2,tColors.selector)
- paintutils.drawLine(x1,z2,x1,z1,tColors.selector)
- elseif z2 >= 2 and z2 <= canvasEdge then
- paintutils.drawLine(x2,2,x2,z2,tColors.selector)
- paintutils.drawLine(x1,z2,x1,2,tColors.selector)
- paintutils.drawLine(x2,z2,x1,z2,tColors.selector)
- else
- paintutils.drawLine(x2,2,x2,canvasEdge,tColors.selector)
- paintutils.drawLine(x1,canvasEdge,x1,2,tColors.selector)
- end
- end
- if x then
- tTool.selector[2]["x"] = tTool.selector[2]["x"]+x-tTool.selector[1]["x"]
- tTool.selector[1]["x"] = x+tScroll.x.value
- tTool.selector[2]["z"] = tTool.selector[2]["z"]+y-tTool.selector[1]["z"]
- tTool.selector[1]["z"] = y+tScroll.y.value
- end
- end
- function selectorCopy(_x1,_z1,_x2,_z2,layer,CUT)
- layer = layer or tScroll.layer
- local tRet = {}
- x1 = math.min(_x1,_x2)
- x2 = math.max(_x1,_x2)
- z1 = math.min(_z1,_z2)
- z2 = math.max(_z1,_z2)
- for ix=x1,x2 do
- tRet[#tRet+1] = {}
- for iz=z1,z2 do
- tRet[#tRet][#tRet[#tRet]+1] = tBlueprint[layer][ix][iz] or " "
- if CUT then
- tBlueprint[layer][ix][iz] = " "
- end
- end
- end
- return tRet
- end
- function selectorPaste(x,z,paste,num)
- --pastes selection into layer at x,z
- z = z-1
- x = x-1
- num = num or tScroll.layer
- for ix=1,#paste do
- tBlueprint[num][x+ix] = tBlueprint[num][x+ix] or {}
- for iz=1,#paste[ix] do
- local color = paste[ix][iz]
- if color ~= " " then
- tBlueprint[num][x+ix][z+iz] = color
- end
- end
- end
- end
- function selectorRecolor(color,x1,z1,x2,z2,layer)
- layer = layer or tScroll.layer
- local tRet = {}
- for ix=x1,x2 do
- tBlueprint[layer][ix] = tBlueprint[layer][ix] or {}
- for iz=z1,z2 do
- if tBlueprint[layer][ix][iz] ~= " " then
- tBlueprint[layer][ix][iz] = color
- end
- end
- end
- renderLayer(layer)
- end
- function circleRender(color,draw)
- if tTool[1].tool ~= "Circle"
- and tTool[2].tool ~= "Circle" then
- return
- end
- local x1 = tTool.circle[1].x
- local x2 = tTool.circle[2].x
- local y1 = tTool.circle[1].y
- local y2 = tTool.circle[2].y
- if not (x1 and x2 and y1 and y2) then
- return
- end
- color = color or tTool.circle[2].color
- local function round(num)
- if num+0.5 > math.ceil(num) then
- return math.ceil(num)
- else
- return math.floor(num)
- end
- end
- local x = {
- max = math.max(x1,x2)-tScroll.x.value,
- min = math.min(x1,x2)-tScroll.x.value
- }
- x.rad = round((x.max-x.min)/2)
- x.center = x.rad+x.min
- local y = {
- max = math.max(y1,y2)-tScroll.y.value+1,
- min = math.min(y1,y2)-tScroll.y.value+1
- }
- y.rad = round((y.max-y.min)/2)
- y.center = y.rad+y.min
- local tPoints = {}
- local canvasEdgeY = tTerm.y
- local canvasEdgeX = tTerm.xCanvas
- if tTerm.grid then
- canvasEdgeX = canvasEdgeX-1
- canvasEdgeY = canvasEdgeY-1
- end
- local radStep = 1/((1.5*x.rad)+(1.5*y.rad)/2)
- for angle = 1, math.pi+radStep, radStep do
- local pX = round(math.cos(angle)*x.rad)
- local pY = round(math.sin(angle)*y.rad)
- tPoints[pX] = tPoints[pX] or {}
- tPoints[pX][pY] = true
- end
- if draw then
- for pX,yT in pairs(tPoints) do
- for pY in pairs(yT) do
- for i=-1,1,2 do
- for j=-1,1,2 do
- local layer = tBlueprint[tScroll.layer]
- local pX = x.center + i*pX + tScroll.x.value
- local pY = y.center + j*pY + tScroll.y.value
- layer[pX] = layer[pX] or {}
- layer[pX][pY-1] = color
- if pX > tScroll.x.value and pX <= canvasEdgeX+tScroll.x.value
- and pY > tScroll.y.value and pY <= canvasEdgeY+tScroll.y.value then
- paintutils.drawPixel(pX,pY,tColorNums[color])
- end
- end
- end
- tTool.circle = {
- [1] = {},
- [2] = {}
- }
- end
- end
- else
- for pX,yT in pairs(tPoints) do
- for pY in pairs(yT) do
- for i=-1,1,2 do
- for j=-1,1,2 do
- local pX = x.center + i*pX
- local pY = y.center + j*pY
- if pX <= canvasEdgeX
- and pY <= canvasEdgeY and pY > 1 then
- paintutils.drawPixel(pX,pY,tColorNums[color])
- end
- end
- end
- end
- end
- end
- end
- --[[
- --------------------------------------------------------------------------------------------------------------
- | Actual program |
- --------------------------------------------------------------------------------------------------------------
- --]]
- --turtle specific files
- if turtle then
- if not fs.exists"cTurtle" then
- tPaste.get(tPaste.cTurtle,"/cTurtle")
- end
- if not cTurtle then
- os.loadAPI(tFile.cTurtle) --Complete turtle API, by CometWolf -Paste code JRPN0P8x
- end
- if peripheral.getType"right" == "modem" and peripheral.call("right","isWireless") then
- modem = peripheral.wrap"right"
- rednet.open"right"
- rednet.broadcast"Architect turtle"
- end
- end
- --file load
- if tArg[1] and tArg[1] ~= "-a" then
- if fs.exists(tArg[1]) then
- tBlueprint,tColorSlots,tOrigin = loadBlueprint(tArg[1])
- if not tBlueprint then
- print(tArg[1].." is not a Turtle Architect file!") --wrong file format
- return
- end
- end
- tFile.curBlueprint = tArg[1]
- elseif fs.exists(tFile.ongoingBuild) then
- local file = fs.open(tFile.ongoingBuild,"r")
- tOngoing = textutils.unserialize(file.readAll())
- file.close()
- end
- --machine check
- if not tTerm.isColor then
- if not turtle then
- --turtle check
- error"This program may only be used on regular turtles or advanced computers/turtles!"
- elseif tArg[1] then
- --regular turtle program
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- local status = tArg[1].." loaded"
- while true do
- local enderAction
- if tOngoing.enderChest then
- enderAction = "Disable ender chest("..tOngoing.enderChest..")"
- else
- enderAction = "Enable ender chest"
- end
- term.clear()
- term.setCursorPos(1,1)
- local button = noColorInput(status,"Commence build","Check usage",enderAction,"Edit origin point","Mark as not built","Quit")
- if button == "Commence build" then
- buildBlueprint(1,#tBlueprint)
- status = "Finished construction of "..tArg[1]
- elseif button == "Check usage" then
- local fuelUsage, tColorBlocks = checkUsage(1,#tBlueprint)
- term.clear()
- term.setCursorPos(1,1)
- print("Fuel: "..fuelUsage)
- for k,v in pairs(tColorBlocks) do
- print(tColorString[tColorNums[k]]..": "..v)
- end
- print"Press any key to continue"
- os.pullEvent"key"
- elseif button == "Enable ender chest" then
- term.clear()
- term.setCursorPos(1,1)
- print"Input ender chest slot:"
- tOngoing.enderChest = tonumber(read())
- cTurtle.tSettings.enderFuel = tOngoing.enderChest
- status = "Enabled ender chest in slot "..tOngoing.enderChest
- elseif button:match"Disable ender chest" then
- tOngoing.enderChest = false
- cTurtle.tSettings.enderFuel = false
- status = "Disabled ender chest"
- elseif button == "Edit origin point" then
- term.clear()
- term.setCursorPos(1,1)
- print("Editing origin point")
- term.write"X: "
- local cursX,cursY = term.getCursorPos()
- term.setCursorPos(1,cursY+1)
- term.write"Y: "
- term.setCursorPos(1,cursY+2)
- term.write"Z: "
- term.setCursorPos(1,cursY+3)
- term.write"X dir: "
- term.setCursorPos(1,cursY+4)
- term.write"Z dir: "
- term.setCursorPos(1,cursY+5)
- term.write"Y dir: "
- term.setCursorPos(4,cursY)
- tOrigin.x = read()
- term.setCursorPos(4,cursY+1)
- tOrigin.y = read()
- term.setCursorPos(4,cursY+2)
- tOrigin.z = read()
- term.setCursorPos(9,cursY+3)
- tOrigin.xDir = read()
- term.setCursorPos(9,cursY+4)
- tOrigin.zDir = read()
- term.setCursorPos(9,cursY+5)
- tOrigin.yDir = read()
- saveBlueprint(tFile.curBlueprint)
- status = "Updated origin point for "..tArg[1]
- elseif button == "Mark as not built" then
- for il=1,#tBlueprint do
- for ix=1,#tBlueprint[il] do
- for iz=1,#tBlueprint[il][ix] do
- local pointNum = tBlueprint[il][ix][iz] or 0
- if pointNum > 15 then
- tBlueprint[il][ix][iz] = pointNum-15
- end
- end
- end
- end
- saveBlueprint(tFile.curBlueprint)
- status = "Marked "..tArg[1].." as not built"
- else --quit
- term.clear()
- term.setCursorPos(1,1)
- return
- end
- end
- elseif tOngoing.blueprint then --checks for ongoing build
- local status = "Ongoing build "..tOngoing.blueprint.." found!"
- while true do
- local enderAction
- if tOngoing.enderChest then
- enderAction = "Disable ender chest("..tOngoing.enderChest..")"
- else
- enderAction = "Enable ender chest"
- end
- local button = noColorInput(status,"Resume","Restart",enderAction,"Cancel")
- if button == "Resume" then
- tFile.curBlueprint = tOngoing.blueprint
- tBlueprint,tColorSlots,tOrigin = loadBlueprint(tFile.curBlueprint)
- buildBlueprint(tOngoing.startLayer,tOngoing.endLayer,true)
- return
- elseif button == "Restart" then
- tFile.curBlueprint = tOngoing.blueprint
- tBlueprint,tColorSlots,tOrigin = loadBlueprint(tFile.curBlueprint)
- for il=1,#tBlueprint do
- for ix=1,#tBlueprint[il] do
- for iz=1,#tBlueprint[il][ix] do
- local pointNum = tBlueprint[il][ix][iz]
- if pointNum > 15 then
- tBlueprint[il][ix][iz] = pointNum-15
- end
- end
- end
- end
- buildBlueprint(tOngoing.startLayer,tOngoing.endLayer)
- return
- elseif button == "Enable ender chest" then
- term.clear()
- term.setCursorPos(1,1)
- print"Input ender chest slot:"
- tOngoing.enderChest = tonumber(read())
- cTurtle.tSettings.enderFuel = tOngoing.enderChest
- status = "Enabled ender chest in slot "..tOngoing.enderChest
- elseif button:match"Disable ender chest" then
- tOngoing.enderChest = false
- cTurtle.tSettings.enderFuel = false
- status = "Disabled ender chest"
- end
- end
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1,1)
- else
- print("Usage: "..tFile.program.." /filePath") --no file path given
- end
- return
- end
- --color program begins
- if not tBlueprint[1] then
- createLayer(tTerm.xCanvas,tTerm.zCanvas,1)
- end
- tMenuBar.render()
- renderLayer(1)
- if tOngoing.blueprint and (tArg[1] == "-a" or not tArg[1]) then --checks for ongoing build
- local file = fs.open(tFile.ongoingBuild,"r")
- tOngoing = textutils.unserialize(file.readAll())
- file.close()
- tFile.curBlueprint = tOngoing.blueprint
- local button
- if not tArg[1] then
- button = tBox.render(1,tTerm.x,"Ongoing build "..tOngoing.blueprint.." found!",4,0,".","Erase","Resume","Edit","Restart") -- requests action
- else
- button = "Resume"
- end
- if button == "Resume" then
- tBlueprint,tColorSlots,tOrigin = loadBlueprint(tFile.curBlueprint)
- buildBlueprint(tOngoing.startLayer,tOngoing.endLayer,true)
- elseif button == "Edit" then
- tBlueprint,tColorSlots,tOrigin = loadBlueprint(tFile.curBlueprint)
- tMenuBar.render()
- renderLayer(1)
- elseif button == "Restart" then
- tBlueprint,tColorSlots,tOrigin = loadBlueprint(tFile.curBlueprint)
- for il=1,#tBlueprint do
- for ix=1,#tBlueprint[il] do
- for iz=1,#tBlueprint[il][ix] do
- local pointNum = tBlueprint[il][ix][iz]
- if pointNum > 15 then
- tBlueprint[il][ix][iz] = pointNum-15
- end
- end
- end
- end
- buildBlueprint(tOngoing.startLayer,tOngoing.endLayer)
- end
- end
- --auto monitor connection mode
- if tArg[2] == "-m" then
- local tSides = rs.getSides()
- tMon = {}
- for is=1,#tSides do
- if peripheral.getType(tSides[is]) == "monitor" and peripheral.call(tSides[is],"isColor") then
- tMon[#tMon+1] = peripheral.wrap(tSides[is])
- tMon[#tMon]["side"] = tSides[is]
- tMon[#tMon]["x"],tMon[#tMon]["y"] = tMon[#tMon]["getSize"]()
- tMon[#tMon]["xMid"] = math.ceil(tMon[#tMon]["x"]/2)
- tMon[#tMon]["yMid"] = math.ceil(tMon[#tMon]["y"]/2)
- tMon[#tMon]["xCanvas"] = tMon[#tMon]["x"] --total x veiwing area
- tMon[#tMon]["zCanvas"] = tMon[#tMon]["y"] --total y veiwing area
- elseif peripheral.getType(tSides[is]) == "modem"
- and not peripheral.call(tSides[is],"isWireless") then
- local tPeripherals = peripheral.call(tSides[is],"getNamesRemote")
- for ip=1,#tPeripherals do
- if string.match(tPeripherals[ip],"monitor")
- and peripheral.call(tPeripherals[ip],"isColor") then
- tMon[#tMon+1] = peripheral.wrap(tPeripherals[ip])
- tMon[#tMon]["side"] = tPeripherals[ip]
- tMon[#tMon]["x"],tMon[#tMon]["y"] = tMon[#tMon]["getSize"]()
- tMon[#tMon]["xMid"] = math.ceil(tMon[#tMon]["x"]/2)
- tMon[#tMon]["yMid"] = math.ceil(tMon[#tMon]["y"]/2)
- tMon[#tMon]["xCanvas"] = tMon[#tMon]["x"] --total x veiwing area
- tMon[#tMon]["zCanvas"] = tMon[#tMon]["y"] --total y veiwing area
- end
- end
- end
- end
- if #tMon > 0 then
- renderLayer(1)
- end
- end
- while true do
- --Event handling
- tEvent = {os.pullEvent()}
- local xCanvas = tTerm.xCanvas
- local zCanvas = tTerm.zCanvas+1
- if tEvent[1] == "monitor_touch" then
- for i=1,#tMon do
- if tMon[i]["side"] == tEvent[2] then
- xCanvas = tMon[i]["xCanvas"]
- zCanvas = tMon[i]["zCanvas"]
- break
- end
- end
- tEvent[1] = "mouse_click"
- tEvent[2] = 1
- tEvent[4] = tEvent[4]+1
- end
- if tTerm.grid then
- xCanvas = xCanvas-1
- zCanvas = zCanvas-1
- end
- if not tMenuBar.open and (tEvent[1] == "mouse_drag" or tEvent[1] == "mouse_click")
- and tEvent[4] <= zCanvas+1 and tEvent[4] > 1
- and tEvent[3] <= xCanvas then
- --canvas input
- local t = tTool[tEvent[2]]
- if t.tool == "Brush" then
- if t.size <= 2 then
- renderPoint(tEvent[3],tEvent[4]-1,t.color)
- end
- if t.size >= 2 then
- local tPoints = {
- [1] = {
- ["layer"] = tScroll.layer,
- ["x"] = tEvent[3]+tScroll.x.value,
- ["z"] = tEvent[4]+tScroll.y.value-1
- }
- }
- for i=1,t.size-1 do
- tPoints = brushExpand(tPoints,t.color)
- end
- end
- elseif t.tool == "Dragger" then
- if tEvent[1] == "mouse_click" then
- tTool.dragPoint = {
- ["x"] = tEvent[3],
- ["y"] = tEvent[4]
- }
- else --mouse drag
- tScroll.x.value = math.max(0,tScroll.x.value+(tTool.dragPoint.x-tEvent[3]))
- tScroll.y.value = math.max(0,tScroll.y.value+(tTool.dragPoint.y-tEvent[4]))
- tTool.dragPoint = {
- ["x"] = tEvent[3],
- ["y"] = tEvent[4]
- }
- end
- renderLayer(tScroll.layer)
- elseif tTool.selector.enabled then
- if tEvent[2] == 1 then
- if tContextMenu.open then
- if tEvent[1] == "mouse_click" then
- local clicked = tContextMenu.click(tEvent[3],tEvent[4])
- if clicked then
- clicked(tEvent[4],tEvent[4])
- else
- tContextMenu.open = false
- renderLayer(tScroll.layer)
- end
- end
- else
- if tEvent[1] == "mouse_click" then
- tTool.selector[1] = {
- ["x"] = tEvent[3]+tScroll.x.value,
- ["z"] = tEvent[4]+tScroll.y.value-1,
- ["layer"] = tScroll.layer
- }
- tTool.selector[2] = nil
- else --mouse drag
- tTool.selector[2] = {
- ["x"] = tEvent[3]+tScroll.x.value,
- ["z"] = tEvent[4]+tScroll.y.value-1
- }
- end
- renderLayer(tScroll.layer)
- end
- elseif tEvent[2] == 2 then
- if tEvent[1] == "mouse_click" then
- tContextMenu.render(tEvent[3],tEvent[4])
- end
- end
- elseif t.tool == "Line" then
- elseif t.tool == "Fill" then
- fillExpand(tEvent[3],tEvent[4]-1,tScroll.layer,tBlueprint[tScroll.layer][tEvent[3]+tScroll.x.value][tEvent[4]+tScroll.y.value-1],t.color)
- elseif t.tool == "Square" then
- squareExpand(tEvent[3],tEvent[4],t.color,t.size)
- elseif t.tool == "Circle" then
- if tEvent[1] == "mouse_click" then
- tTool.circle[1] = {
- x = tEvent[3]+tScroll.x.value,
- y = tEvent[4]+tScroll.y.value-1
- }
- if tTool.circle[2].x then
- tTool.circle[2] = {}
- renderLayer(tScroll.layer)
- end
- else
- tTool.circle[2] = {
- x = tEvent[3]+tScroll.x.value,
- y = tEvent[4]+tScroll.y.value-1,
- color = t.color
- }
- tTool.circle[1].color = t.color
- renderLayer(tScroll.layer)
- end
- end
- elseif tEvent[1] == "mouse_click" then
- --non-canvas mouse clicks
- if tEvent[4] == 1 then
- --top bar menu clicks
- tMenuBar.render(tMenuBar.click(tEvent[3],tEvent[4]))
- elseif tMenuBar.open then
- --dropdown menu open
- local clicked = tMenuBar.click(tEvent[3],tEvent[4])
- tMenuBar.render()
- --closes drop down menu
- if clicked then
- --runs clicked function
- clicked(tEvent[2])
- end
- end
- elseif tEvent[1] == "mouse_scroll" and not tMenuBar.open then
- --mouse scroll
- tScroll.y.value = math.max(0,tScroll.y.value+tEvent[2])
- renderLayer(tScroll.layer)
- elseif tEvent[1] == "key" then
- --key inputs
- local key = tEvent[2]
- if not tMenuBar.open then
- local renderMenu
- if key == 205 then --right arrow
- tScroll.x.value = tScroll.x.value+1
- elseif key == 203 then --left arrow
- tScroll.x.value = math.max(0,tScroll.x.value-1)
- elseif key == 200 then --up arrow
- tScroll.y.value = math.max(0,tScroll.y.value-1)
- elseif key == 208 then --down arrow
- tScroll.y.value = tScroll.y.value+1
- elseif key == 209 then --page down
- tScroll.layer = math.max(1,tScroll.layer-1)
- elseif key == 201 then --page up
- tScroll.layer = math.min(#tBlueprint,tScroll.layer+1)
- elseif key == 211 then --delete
- getFunc("Layer","Delete current layer")()
- elseif key == 199 then --home
- tScroll.layer = 1
- elseif key == 28 then --enter
- if tTool[1].tool == "Circle" then
- circleRender(false,true)
- end
- elseif key == 207 then --end
- tScroll.layer = #tBlueprint
- elseif key == 31 then --S
- getFunc("Blueprint","Save ")() --double space to differnetiate between save and save as...
- elseif key == 33 then --F
- tTool.selector = {}
- if tTool[1]["tool"] ~= "Fill" then
- tTool[1]["tool"] = "Fill"
- else
- tTool[1]["tool"] = "Brush"
- end
- elseif key == 46 then --C
- renderMenu = "Color"
- elseif key == 20 then --T
- renderMenu = getFunc("Main","Tools")
- elseif key == 48 then --B
- renderMenu = getFunc("Main","Blueprint")
- elseif key == 38 then --L
- renderMenu = getFunc("Main","Layer")
- elseif key == 31 then --S
- renderMenu = getFunc("Main","Settings")
- elseif key == 49 then --N
- getFunc("Layer","New...")()
- elseif key == 34 then --G
- getFunc("Layer","Goto...")()
- elseif key == 32 then --D
- tTool.selector = {}
- if tTool[1]["tool"] ~= "Dragger" then
- tTool[1]["tool"] = "Dragger"
- else
- tTool[1]["tool"] = "Brush"
- end
- end
- if renderMenu then
- tMenuBar.render(renderMenu)
- else
- renderLayer(tScroll.layer)
- end
- end
- elseif tEvent[1] == "char" then
- --character input, nothing here yet
- elseif tEvent[1] == "monitor_resize" and tMon then
- --monitor changed size
- for i=1,#tMon do
- tMon[i]["x"],tMon[i]["y"] = tMon[i]["getSize"]()
- tMon[i]["xMid"] = math.ceil(tMon[i]["x"]/2)
- tMon[i]["yMid"] = math.ceil(tMon[i]["y"]/2)
- tMon[i]["xCanvas"] = tMon[i]["x"] --total x veiwing area
- tMon[i]["zCanvas"] = tMon[i]["y"] --total y veiwing area, accounts for the menubar on top
- end
- tMenuBar.render(tMenuBar.open)
- renderLayer(tScroll.layer)
- end
- end
- --[[
- --------------------------------------------------------------------------------------------------------------
- | Program end |
- --------------------------------------------------------------------------------------------------------------
- --]]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement