Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local COMMAND_POSITION = {138, 49, 1400}
- local SCANNER_OFFSET = {0, 0, 0}
- local startFacing = 0
- local P = require "SimplifyPathfinding"
- local F = require "Frame"
- local M = require "SimplifyPathfinding.Util.MapExtras"
- local TRANSMISSION_CHANNEL = 4589
- local mons = {peripheral.find("monitor")}
- local mon, mon2
- local modem = peripheral.find("modem", function(_, w) return w.isWireless() end)
- modem.open(TRANSMISSION_CHANNEL)
- if mons[1].getSize() < mons[2].getSize() then
- mon = mons[2]
- mon2 = mons[1]
- else
- mon = mons[1]
- mon2 = mons[2]
- end
- mon2.setTextScale(1.5)
- local frame = F.new(mon)
- local frame2 = F.new(mon2)
- frame.Initialize()
- frame2.Initialize()
- local mw, mh = frame.getSize()
- local Pathfinder = P.New(
- "Test Map",
- COMMAND_POSITION[1] + SCANNER_OFFSET[1],
- COMMAND_POSITION[2] + SCANNER_OFFSET[2],
- COMMAND_POSITION[3] + SCANNER_OFFSET[3]
- )
- local MapExtra = M.New(Pathfinder)
- local outputStack = {}
- local outputWindow = window.create(frame, 3, 14, mw - 4, 5)
- local function PrintToOutput(...)
- local old = term.redirect(outputWindow)
- local packed = table.pack(...)
- for i = 1, packed.n do
- packed[i] = tostring(packed[i])
- end
- print()
- write(
- string.format(
- "[%s] %s",
- outputStack[#outputStack],
- table.concat(packed, ' ')
- )
- )
- term.redirect(old)
- end
- local function PrintGoodToOutput(...)
- local old = term.redirect(outputWindow)
- local oldc = term.getTextColor()
- local packed = table.pack(...)
- for i = 1, packed.n do
- packed[i] = tostring(packed[i])
- end
- print()
- term.setTextColor(colors.green)
- write(
- string.format(
- "[%s] %s",
- outputStack[#outputStack],
- table.concat(packed, ' ')
- )
- )
- term.setTextColor(oldc)
- term.redirect(old)
- end
- local function PrintErrorToOutput(...)
- local old = term.redirect(outputWindow)
- local oldc = term.getTextColor()
- local packed = table.pack(...)
- for i = 1, packed.n do
- packed[i] = tostring(packed[i])
- end
- print()
- term.setTextColor(colors.red)
- write(
- string.format(
- "[%s] %s",
- outputStack[#outputStack],
- table.concat(packed, ' ')
- )
- )
- term.setTextColor(oldc)
- term.redirect(old)
- end
- local function PushOutputStack(name)
- table.insert(outputStack, name)
- end
- local function PopOutputStack()
- table.remove(outputStack)
- end
- local state = {
- busy = false,
- map = {
- serializing = false,
- map = Pathfinder.Map,
- percent = 0,
- size = 0
- }
- }
- local function FindBlock(scanData, name)
- for i, block in ipairs(scanData) do
- if block.name == name then
- return block
- end
- end
- end
- local function makeOffsets(block)
- return block.x + COMMAND_POSITION[1] + SCANNER_OFFSET[1],
- block.y + COMMAND_POSITION[2] + SCANNER_OFFSET[2],
- block.z + COMMAND_POSITION[3] + SCANNER_OFFSET[3]
- end
- local function PutBlock(data, name)
- commands.exec(
- string.format(
- "setblock %d %d %d %s",
- data.X or data.x, data.Y or data.y, data.Z or data.z,
- name
- )
- )
- end
- local buttons = {}
- local function CheckButtons(x, y)
- for i = 1, #buttons do
- local b = buttons[i]
- if x >= b.X and x < b.X + b.W and y >= b.Y and y < b.Y + b.H then
- b:Callback()
- end
- end
- end
- local function DrawButtons()
- for i = 1, #buttons do
- buttons[i]:Draw()
- end
- end
- local function DrawBox(termObj, x, y, w, h, c)
- local line = string.rep(' ', w)
- termObj.setBackgroundColor(c)
- for ypos = y, y + h - 1 do
- termObj.setCursorPos(x, ypos)
- termObj.write(line)
- end
- end
- local function CenterText(termObj, x, y, w, h, txt)
- termObj.setCursorPos(
- x + math.floor((w - 1) / 2 - txt:len() / 2 + 0.5),
- y + math.floor((h - 1) / 2 + 0.5)
- )
- termObj.write(txt)
- end
- local function Button(termObj, x, y, w, h, fgcolor, bgcolor, bgdisable, txt, callback)
- if type(callback) ~= "function" then
- error("REEEEEEEEEEEEEEE", 2)
- end
- local function Draw(self)
- DrawBox(termObj, x, y, w, h, self.enable and bgcolor or bgdisable)
- termObj.setTextColor(fgcolor)
- CenterText(termObj, x, y, w, h, txt)
- end
- local obj = {
- enable = true,
- Draw = Draw,
- X = x,
- Y = y,
- W = w,
- H = h
- }
- function obj.Callback(...)
- obj.enable = false
- local ok, err = pcall(callback, ...)
- if not ok then
- PrintErrorToOutput("Failed:", err)
- PopOutputStack()
- end
- obj.enable = true
- end
- buttons[#buttons + 1] = obj
- return obj
- end
- local Redraw
- local function Serialize(self)
- PushOutputStack("SERIALIZE")
- state.map.serializing = true
- state.map.percent = 0
- state.map.serialized = nil
- state.map.size = 0
- PrintToOutput("Serializing...")
- Redraw()
- state.map.serialized = Pathfinder.Map:Serialize(false, function(_, percent)
- state.map.percent = percent
- Redraw()
- end)
- PrintGoodToOutput("Serializing Done.")
- PrintToOutput(string.format("Write actions needed: %d", #state.map.serialized))
- state.map.serializing = false
- state.map.percent = 1
- PrintToOutput("Getting filesize.")
- Redraw()
- local h = io.open("output.txt", 'w')
- for _, thing in ipairs(state.map.serialized) do
- h:write(thing)
- print(_)
- end
- h:close()
- state.map.size = fs.getSize("output.txt")
- PrintGoodToOutput("Done.")
- PopOutputStack()
- end
- local function Draw(self)
- PushOutputStack("DRAW")
- Redraw()
- if not state.pathResult then
- PrintErrorToOutput("No path to be drawn!")
- return
- end
- if state.drawn then
- PrintToOutput("Clearing path.")
- else
- PrintToOutput("Drawing path.")
- end
- Redraw()
- for i = 1, #state.pathResult do
- PutBlock(state.pathResult[i], state.drawn and "minecraft:air" or "minecraft:redstone_block")
- end
- PrintGoodToOutput("Done.")
- state.drawn = not state.drawn
- PopOutputStack()
- end
- local function Scan(self)
- PushOutputStack("SCAN")
- PrintToOutput("Scanning.")
- Redraw()
- if state.drawn then
- PrintToOutput("Clearing old path before scanning.")
- Draw{}
- end
- local ok, data = MapExtra:Scan(
- 24,
- makeOffsets{x=0,y=0,z=0}
- )
- if ok then
- PrintGoodToOutput("Scan OK")
- else
- PrintErrorToOutput("Scan FAIL:", data)
- Redraw()
- return
- end
- state.goldBlock = FindBlock(data, "minecraft:gold_block")
- state.diamondBlock = FindBlock(data, "minecraft:diamond_block")
- if state.goldBlock then
- PrintGoodToOutput(" Found gold block.")
- else
- PrintErrorToOutput(" Did not find gold block.")
- end
- if state.diamondBlock then
- PrintGoodToOutput(" Found diamond block.")
- else
- PrintErrorToOutput(" Did not find diamond block.")
- end
- Redraw()
- PopOutputStack()
- end
- local function Path(self)
- PushOutputStack("PATH")
- Redraw()
- if state.drawn then
- PrintToOutput("Clearing old path before pathfinding.")
- Draw{}
- end
- if not state.goldBlock then
- PrintErrorToOutput("Cannot pathfind, missing gold block.")
- state.pathResult = nil
- return
- end
- if not state.diamondBlock then
- PrintErrorToOutput("Cannot pathfind, missing diamond block.")
- state.pathResult = nil
- return
- end
- local x1, y1, z1 = makeOffsets(state.goldBlock)
- local x2, y2, z2 = makeOffsets(state.diamondBlock)
- Pathfinder:AddAir(x1, y1, z1)
- Pathfinder:AddAir(x2, y2, z2)
- PrintToOutput("Pathfinding...")
- Redraw()
- local ok, result = Pathfinder:Pathfind(x1, y1, z1, x2, y2, z2, startFacing)
- if not ok then
- PrintErrorToOutput("Pathfinding failed:", result)
- state.pathResult = nil
- else
- PrintGoodToOutput("Pathfinding success! Path length:", #result)
- state.pathResult = result
- end
- PopOutputStack()
- end
- local function send(data)
- modem.transmit(
- TRANSMISSION_CHANNEL,
- TRANSMISSION_CHANNEL,
- data
- )
- end
- local function sendACK(data)
- local timeout, count = os.startTimer(0), 0
- while count < 5 do
- local event, id, _, _, msg = os.pullEvent()
- if event == "timer" and id == timeout then
- if count ~= 5 then
- send(data)
- timeout = os.startTimer(2)
- count = count + 1
- PrintToOutput("Transmitting... ( try", count, "/ 4 )")
- end
- elseif event == "modem_message" and type(msg) == "table" then
- PrintToOutput("Received reply:")
- PrintToOutput(" OK:", msg.Ok)
- if not msg.Ok then
- error(string.format("Remote error: %s", msg.Error), 0)
- end
- return
- end
- Redraw()
- end
- error("Too many attempts!", 0)
- end
- local function Transmit(self)
- PushOutputStack "TRANSMIT"
- if not state.pathResult then
- PrintErrorToOutput("No path to transmit!")
- return
- end
- PrintToOutput("Transmitting GOTO start-of-path.")
- Redraw()
- sendACK {
- Action = "GOTO",
- Position = {
- state.pathResult[1].X,
- state.pathResult[1].Y,
- state.pathResult[1].Z
- },
- Ok = true
- }
- -- wait for turtle to be in position
- PrintToOutput("Waiting for turtle to be in position.")
- Redraw()
- local timeout = os.startTimer(30)
- while true do
- local event, id, _, _, msg = os.pullEvent()
- if event == "timer" and id == timeout then
- error("Timed out while waiting for turtle.", 0)
- elseif event == "modem_message" and type(msg) == "table" then
- if msg.Ok and msg.Action == "ARRIVED" then
- PrintGoodToOutput("Turtle arrived at position.")
- break
- elseif not msg.Ok then
- error(string.format("Remote error: %s", msg.Error), 0)
- else
- error("Unknown transmission received.", 0)
- end
- end
- end
- PrintToOutput("Ordering turtle to follow path.")
- Redraw()
- sendACK {
- Action = "FOLLOW_PATH",
- Path = state.pathResult,
- Ok = true
- }
- PrintToOutput("Waiting for turtle to complete path.")
- Redraw()
- timeout = os.startTimer(60)
- while true do
- local event, id, _, _, msg = os.pullEvent()
- if event == "timer" and id == timeout then
- error("Timed out while waiting for turtle.", 0)
- elseif event == "modem_message" and type(msg) == "table" then
- if msg.Ok and msg.Action == "ARRIVED" then
- PrintGoodToOutput("Turtle completed path.")
- break
- elseif not msg.Ok then
- error(string.format("Remote error: %s", msg.Error), 0)
- else
- error("Unknown transmission received.", 0)
- end
- end
- end
- PopOutputStack()
- end
- local function ToggleDebug()
- PushOutputStack "DEBUG"
- Pathfinder.Debug.PlaceBlocks = not Pathfinder.Debug.PlaceBlocks
- if Pathfinder.Debug.PlaceBlocks then
- PrintToOutput "Enabled."
- else
- PrintToOutput "Disabled."
- end
- PopOutputStack()
- end
- --[[
- state.map = {
- serialized = {} or nil
- serializing = true or false
- percent = 0 <-> 1
- }
- state.goldBlock = {x, y, z} or nil
- state.diamondBlock = {x, y, z} or nil
- ]]
- Redraw = function()
- local w, h = frame.getSize()
- frame.setBackgroundColor(colors.black)
- frame.clear()
- -- Header
- DrawBox(frame, 1, 1, w, 3, state.busy and colors.red or colors.gray)
- CenterText(frame, 1, 1, w, 3, state.busy and "Pathfinder/Mapper Controller (Busy)" or "Pathfinder/Mapper Controller")
- -- Map information box
- DrawBox(frame, 2, 4, 22, 1, colors.purple)
- CenterText(frame, 2, 4, 22, 1, "Map Data")
- DrawBox(frame, 2, 5, 22, 6, colors.lightGray)
- frame.setCursorPos(3, 6)
- frame.setTextColor(colors.white)
- if state.map.serialized then
- frame.write(string.format("Name: %s", Pathfinder.Map.Name))
- frame.setCursorPos(3, 7)
- frame.write(string.format("Offs: %d %d %d", Pathfinder.Map.Offset[1], Pathfinder.Map.Offset[2], Pathfinder.Map.Offset[3]))
- frame.setCursorPos(3, 8)
- frame.write(string.format("Size: %d bytes", state.map.size))
- elseif state.map.serializing then
- frame.write("Serializing")
- frame.setCursorPos(3, 7)
- local line = string.rep('\143', math.floor(19 * state.map.percent + 0.5))
- frame.write("[")
- frame.setTextColor(colors.green)
- frame.write(line)
- frame.setTextColor(colors.white)
- frame.setCursorPos(22, 7)
- frame.write(']')
- else
- frame.write("No map data.")
- end
- -- Pathfinder controls
- DrawBox(frame, 28, 4, 22, 1, colors.purple)
- CenterText(frame, 28, 4, 22, 1, "Controls")
- DrawBox(frame, 28, 5, 22, 6, colors.lightGray)
- -- Scan output
- DrawBox(frame, 2, 12, w - 2, 1, colors.purple)
- CenterText(frame, 2, 12, w - 2, 1, "Output")
- DrawBox(frame, 2, 13, w - 2, 7, colors.lightGray)
- -- SECOND MONITOR
- local w, h = frame2.getSize()
- frame2.setBackgroundColor(colors.black)
- frame2.clear()
- DrawBox(frame2, 1, 1, w, h, colors.gray)
- DrawButtons()
- outputWindow.redraw()
- frame.PushBuffer()
- frame2.PushBuffer()
- end
- local function Main()
- PushOutputStack("MAIN")
- local w, h = frame.getSize()
- -- Serialize map data
- Button(frame, 3, 10, 20, 1, colors.white, colors.green, colors.blue, "Serialize Map Data", Serialize)
- -- Scan
- Button(frame, 29, 6, 6, 3, colors.white, colors.green, colors.blue, "SCAN", Scan)
- -- Pathfind
- Button(frame, 36, 6, 6, 3, colors.white, colors.green, colors.blue, "PATH", Path)
- -- Draw path
- Button(frame, 43, 6, 6, 3, colors.white, colors.green, colors.blue, "DRAW", Draw)
- -- Transmit to turtle
- Button(frame, 29, 10, 10, 1, colors.white, colors.green, colors.blue, "TRANSMIT", Transmit)
- -- Enable debug
- Button(frame, 42, 10, 7, 1, colors.white, colors.green, colors.blue, "DEBUG", ToggleDebug)
- -- Reboot
- Button(frame, w - 2, 1, 3, 3, colors.white, colors.red, colors.red, "", function() Redraw() end)
- -- BUTTONS FOR FACING SETTING
- local up = "\24"
- local down = "\25"
- local right = "\26"
- local left = "\27"
- local btns = {}
- local function enable(i)
- for j = 1, 4 do
- if i == j then
- btns[j].enable = true
- else
- btns[j].enable = false
- end
- end
- end
- btns[1] = Button(frame2, 3, 1, 1, 1, colors.white, colors.blue, colors.lightGray, up, function()
- startFacing = 0
- enable(1)
- end)
- btns[2] = Button(frame2, 3, 3, 1, 1, colors.white, colors.blue, colors.lightGray, down, function()
- startFacing = 2
- enable(2)
- end)
- btns[3] = Button(frame2, 4, 2, 1, 1, colors.white, colors.blue, colors.lightGray, right, function()
- startFacing = 1
- enable(3)
- end)
- btns[4] = Button(frame2, 2, 2, 1, 1, colors.white, colors.blue, colors.lightGray, left, function()
- startFacing = 3
- enable(4)
- end)
- enable(1)
- PrintToOutput "Ready."
- Redraw()
- while true do
- local event, _, x, y = os.pullEvent("monitor_touch")
- state.busy = true
- Redraw()
- CheckButtons(x, y)
- state.busy = false
- Redraw()
- end
- end
- local function SIGTERM()
- while true do
- local event, data, x, y = os.pullEventRaw()
- if event == "monitor_touch" and x >= mw - 2 and y <= 3 then
- if state.busy then
- os.queueEvent("terminate")
- else
- os.sleep()
- os.reboot()
- end
- elseif event == "task_complete" then
- print(data, x, y)
- end
- end
- end
- while true do
- local ok, err = pcall(parallel.waitForAny, Main, SIGTERM)
- if not ok then
- printError(err)
- pcall(PrintErrorToOutput, "ERRORED -", err)
- if not err:lower():find("yielding") then
- pcall(PrintErrorToOutput, "Not due to too long without yielding. Stopping.")
- break
- else
- pcall(PrintErrorToOutput, "It is unknown if the operation completed.")
- end
- outputStack = {"MAIN"}
- os.sleep(5)
- else
- break
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement