Advertisement
fatboychummy

command.lua

Oct 9th, 2021
1,188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.52 KB | None | 0 0
  1. local COMMAND_POSITION = {138, 49, 1400}
  2. local SCANNER_OFFSET = {0, 0, 0}
  3.  
  4. local startFacing = 0
  5.  
  6. local P = require "SimplifyPathfinding"
  7. local F = require "Frame"
  8. local M = require "SimplifyPathfinding.Util.MapExtras"
  9. local TRANSMISSION_CHANNEL = 4589
  10.  
  11. local mons = {peripheral.find("monitor")}
  12. local mon, mon2
  13. local modem = peripheral.find("modem", function(_, w) return w.isWireless() end)
  14. modem.open(TRANSMISSION_CHANNEL)
  15. if mons[1].getSize() < mons[2].getSize() then
  16.   mon = mons[2]
  17.   mon2 = mons[1]
  18. else
  19.   mon = mons[1]
  20.   mon2 = mons[2]
  21. end
  22. mon2.setTextScale(1.5)
  23. local frame = F.new(mon)
  24. local frame2 = F.new(mon2)
  25. frame.Initialize()
  26. frame2.Initialize()
  27. local mw, mh = frame.getSize()
  28.  
  29. local Pathfinder = P.New(
  30.   "Test Map",
  31.   COMMAND_POSITION[1] + SCANNER_OFFSET[1],
  32.   COMMAND_POSITION[2] + SCANNER_OFFSET[2],
  33.   COMMAND_POSITION[3] + SCANNER_OFFSET[3]
  34. )
  35. local MapExtra = M.New(Pathfinder)
  36.  
  37. local outputStack = {}
  38. local outputWindow = window.create(frame, 3, 14, mw - 4, 5)
  39. local function PrintToOutput(...)
  40.   local old = term.redirect(outputWindow)
  41.   local packed = table.pack(...)
  42.   for i = 1, packed.n do
  43.     packed[i] = tostring(packed[i])
  44.   end
  45.   print()
  46.   write(
  47.     string.format(
  48.       "[%s] %s",
  49.       outputStack[#outputStack],
  50.       table.concat(packed, ' ')
  51.     )
  52.   )
  53.   term.redirect(old)
  54. end
  55. local function PrintGoodToOutput(...)
  56.   local old = term.redirect(outputWindow)
  57.   local oldc = term.getTextColor()
  58.   local packed = table.pack(...)
  59.   for i = 1, packed.n do
  60.     packed[i] = tostring(packed[i])
  61.   end
  62.   print()
  63.   term.setTextColor(colors.green)
  64.   write(
  65.     string.format(
  66.       "[%s] %s",
  67.       outputStack[#outputStack],
  68.       table.concat(packed, ' ')
  69.     )
  70.   )
  71.   term.setTextColor(oldc)
  72.   term.redirect(old)
  73. end
  74. local function PrintErrorToOutput(...)
  75.   local old = term.redirect(outputWindow)
  76.   local oldc = term.getTextColor()
  77.   local packed = table.pack(...)
  78.   for i = 1, packed.n do
  79.     packed[i] = tostring(packed[i])
  80.   end
  81.   print()
  82.   term.setTextColor(colors.red)
  83.   write(
  84.     string.format(
  85.       "[%s] %s",
  86.       outputStack[#outputStack],
  87.       table.concat(packed, ' ')
  88.     )
  89.   )
  90.   term.setTextColor(oldc)
  91.   term.redirect(old)
  92. end
  93. local function PushOutputStack(name)
  94.   table.insert(outputStack, name)
  95. end
  96. local function PopOutputStack()
  97.   table.remove(outputStack)
  98. end
  99.  
  100. local state = {
  101.   busy = false,
  102.   map = {
  103.     serializing = false,
  104.     map = Pathfinder.Map,
  105.     percent = 0,
  106.     size = 0
  107.   }
  108. }
  109.  
  110. local function FindBlock(scanData, name)
  111.  
  112.   for i, block in ipairs(scanData) do
  113.     if block.name == name then
  114.       return block
  115.     end
  116.   end
  117. end
  118.  
  119. local function makeOffsets(block)
  120.   return block.x + COMMAND_POSITION[1] + SCANNER_OFFSET[1],
  121.          block.y + COMMAND_POSITION[2] + SCANNER_OFFSET[2],
  122.          block.z + COMMAND_POSITION[3] + SCANNER_OFFSET[3]
  123. end
  124.  
  125. local function PutBlock(data, name)
  126.   commands.exec(
  127.     string.format(
  128.       "setblock %d %d %d %s",
  129.       data.X or data.x, data.Y or data.y, data.Z or data.z,
  130.       name
  131.     )
  132.   )
  133. end
  134.  
  135. local buttons = {}
  136. local function CheckButtons(x, y)
  137.   for i = 1, #buttons do
  138.     local b = buttons[i]
  139.  
  140.     if x >= b.X and x < b.X + b.W and y >= b.Y and y < b.Y + b.H then
  141.       b:Callback()
  142.     end
  143.   end
  144. end
  145.  
  146. local function DrawButtons()
  147.   for i = 1, #buttons do
  148.     buttons[i]:Draw()
  149.   end
  150. end
  151.  
  152. local function DrawBox(termObj, x, y, w, h, c)
  153.   local line = string.rep(' ', w)
  154.  
  155.   termObj.setBackgroundColor(c)
  156.   for ypos = y, y + h - 1 do
  157.     termObj.setCursorPos(x, ypos)
  158.     termObj.write(line)
  159.   end
  160. end
  161.  
  162. local function CenterText(termObj, x, y, w, h, txt)
  163.   termObj.setCursorPos(
  164.     x + math.floor((w - 1) / 2 - txt:len() / 2 + 0.5),
  165.     y + math.floor((h - 1) / 2 + 0.5)
  166.   )
  167.   termObj.write(txt)
  168. end
  169.  
  170. local function Button(termObj, x, y, w, h, fgcolor, bgcolor, bgdisable, txt, callback)
  171.   if type(callback) ~= "function" then
  172.     error("REEEEEEEEEEEEEEE", 2)
  173.   end
  174.   local function Draw(self)
  175.     DrawBox(termObj, x, y, w, h, self.enable and bgcolor or bgdisable)
  176.  
  177.     termObj.setTextColor(fgcolor)
  178.  
  179.     CenterText(termObj, x, y, w, h, txt)
  180.   end
  181.  
  182.   local obj = {
  183.     enable = true,
  184.     Draw = Draw,
  185.     X = x,
  186.     Y = y,
  187.     W = w,
  188.     H = h
  189.   }
  190.   function obj.Callback(...)
  191.     obj.enable = false
  192.     local ok, err = pcall(callback, ...)
  193.     if not ok then
  194.       PrintErrorToOutput("Failed:", err)
  195.       PopOutputStack()
  196.     end
  197.     obj.enable = true
  198.   end
  199.  
  200.   buttons[#buttons + 1] = obj
  201.  
  202.   return obj
  203. end
  204.  
  205. local Redraw
  206.  
  207. local function Serialize(self)
  208.   PushOutputStack("SERIALIZE")
  209.  
  210.   state.map.serializing = true
  211.   state.map.percent = 0
  212.   state.map.serialized = nil
  213.   state.map.size = 0
  214.  
  215.   PrintToOutput("Serializing...")
  216.   Redraw()
  217.   state.map.serialized = Pathfinder.Map:Serialize(false, function(_, percent)
  218.     state.map.percent = percent
  219.     Redraw()
  220.   end)
  221.   PrintGoodToOutput("Serializing Done.")
  222.   PrintToOutput(string.format("Write actions needed: %d", #state.map.serialized))
  223.   state.map.serializing = false
  224.   state.map.percent = 1
  225.  
  226.   PrintToOutput("Getting filesize.")
  227.   Redraw()
  228.   local h = io.open("output.txt", 'w')
  229.   for _, thing in ipairs(state.map.serialized) do
  230.     h:write(thing)
  231.     print(_)
  232.   end
  233.   h:close()
  234.  
  235.   state.map.size = fs.getSize("output.txt")
  236.  
  237.   PrintGoodToOutput("Done.")
  238.  
  239.   PopOutputStack()
  240. end
  241.  
  242. local function Draw(self)
  243.   PushOutputStack("DRAW")
  244.  
  245.   Redraw()
  246.   if not state.pathResult then
  247.     PrintErrorToOutput("No path to be drawn!")
  248.     return
  249.   end
  250.  
  251.   if state.drawn then
  252.     PrintToOutput("Clearing path.")
  253.   else
  254.     PrintToOutput("Drawing path.")
  255.   end
  256.   Redraw()
  257.  
  258.   for i = 1, #state.pathResult do
  259.     PutBlock(state.pathResult[i], state.drawn and "minecraft:air" or "minecraft:redstone_block")
  260.   end
  261.  
  262.   PrintGoodToOutput("Done.")
  263.  
  264.   state.drawn = not state.drawn
  265.  
  266.   PopOutputStack()
  267. end
  268.  
  269. local function Scan(self)
  270.   PushOutputStack("SCAN")
  271.  
  272.   PrintToOutput("Scanning.")
  273.   Redraw()
  274.  
  275.   if state.drawn then
  276.     PrintToOutput("Clearing old path before scanning.")
  277.     Draw{}
  278.   end
  279.  
  280.   local ok, data = MapExtra:Scan(
  281.     24,
  282.     makeOffsets{x=0,y=0,z=0}
  283.   )
  284.  
  285.   if ok then
  286.     PrintGoodToOutput("Scan OK")
  287.   else
  288.     PrintErrorToOutput("Scan FAIL:", data)
  289.     Redraw()
  290.     return
  291.   end
  292.   state.goldBlock = FindBlock(data, "minecraft:gold_block")
  293.   state.diamondBlock = FindBlock(data, "minecraft:diamond_block")
  294.  
  295.   if state.goldBlock then
  296.     PrintGoodToOutput("  Found gold block.")
  297.   else
  298.     PrintErrorToOutput("  Did not find gold block.")
  299.   end
  300.   if state.diamondBlock then
  301.     PrintGoodToOutput("  Found diamond block.")
  302.   else
  303.     PrintErrorToOutput("  Did not find diamond block.")
  304.   end
  305.  
  306.   Redraw()
  307.  
  308.   PopOutputStack()
  309. end
  310.  
  311. local function Path(self)
  312.   PushOutputStack("PATH")
  313.   Redraw()
  314.  
  315.   if state.drawn then
  316.     PrintToOutput("Clearing old path before pathfinding.")
  317.     Draw{}
  318.   end
  319.  
  320.   if not state.goldBlock then
  321.     PrintErrorToOutput("Cannot pathfind, missing gold block.")
  322.     state.pathResult = nil
  323.     return
  324.   end
  325.   if not state.diamondBlock then
  326.     PrintErrorToOutput("Cannot pathfind, missing diamond block.")
  327.     state.pathResult = nil
  328.     return
  329.   end
  330.  
  331.   local x1, y1, z1 = makeOffsets(state.goldBlock)
  332.   local x2, y2, z2 = makeOffsets(state.diamondBlock)
  333.  
  334.   Pathfinder:AddAir(x1, y1, z1)
  335.   Pathfinder:AddAir(x2, y2, z2)
  336.  
  337.   PrintToOutput("Pathfinding...")
  338.   Redraw()
  339.  
  340.   local ok, result = Pathfinder:Pathfind(x1, y1, z1, x2, y2, z2, startFacing)
  341.   if not ok then
  342.     PrintErrorToOutput("Pathfinding failed:", result)
  343.     state.pathResult = nil
  344.   else
  345.     PrintGoodToOutput("Pathfinding success! Path length:", #result)
  346.     state.pathResult = result
  347.   end
  348.  
  349.  
  350.   PopOutputStack()
  351. end
  352.  
  353. local function send(data)
  354.   modem.transmit(
  355.     TRANSMISSION_CHANNEL,
  356.     TRANSMISSION_CHANNEL,
  357.     data
  358.   )
  359. end
  360. local function sendACK(data)
  361.   local timeout, count = os.startTimer(0), 0
  362.   while count < 5 do
  363.     local event, id, _, _, msg = os.pullEvent()
  364.     if event == "timer" and id == timeout then
  365.       if count ~= 5 then
  366.         send(data)
  367.         timeout = os.startTimer(2)
  368.         count = count + 1
  369.         PrintToOutput("Transmitting... ( try", count, "/ 4 )")
  370.       end
  371.     elseif event == "modem_message" and type(msg) == "table" then
  372.       PrintToOutput("Received reply:")
  373.       PrintToOutput("  OK:", msg.Ok)
  374.       if not msg.Ok then
  375.         error(string.format("Remote error: %s", msg.Error), 0)
  376.       end
  377.       return
  378.     end
  379.     Redraw()
  380.   end
  381.  
  382.   error("Too many attempts!", 0)
  383. end
  384. local function Transmit(self)
  385.   PushOutputStack "TRANSMIT"
  386.   if not state.pathResult then
  387.     PrintErrorToOutput("No path to transmit!")
  388.     return
  389.   end
  390.  
  391.   PrintToOutput("Transmitting GOTO start-of-path.")
  392.   Redraw()
  393.  
  394.   sendACK {
  395.     Action = "GOTO",
  396.     Position = {
  397.       state.pathResult[1].X,
  398.       state.pathResult[1].Y,
  399.       state.pathResult[1].Z
  400.     },
  401.     Ok = true
  402.   }
  403.  
  404.  
  405.   -- wait for turtle to be in position
  406.   PrintToOutput("Waiting for turtle to be in position.")
  407.   Redraw()
  408.   local timeout = os.startTimer(30)
  409.   while true do
  410.     local event, id, _, _, msg = os.pullEvent()
  411.     if event == "timer" and id == timeout then
  412.       error("Timed out while waiting for turtle.", 0)
  413.     elseif event == "modem_message" and type(msg) == "table" then
  414.       if msg.Ok and msg.Action == "ARRIVED" then
  415.         PrintGoodToOutput("Turtle arrived at position.")
  416.         break
  417.       elseif not msg.Ok then
  418.         error(string.format("Remote error: %s", msg.Error), 0)
  419.       else
  420.         error("Unknown transmission received.", 0)
  421.       end
  422.     end
  423.   end
  424.  
  425.   PrintToOutput("Ordering turtle to follow path.")
  426.   Redraw()
  427.   sendACK {
  428.     Action = "FOLLOW_PATH",
  429.     Path = state.pathResult,
  430.     Ok = true
  431.   }
  432.  
  433.   PrintToOutput("Waiting for turtle to complete path.")
  434.   Redraw()
  435.   timeout = os.startTimer(60)
  436.   while true do
  437.     local event, id, _, _, msg = os.pullEvent()
  438.     if event == "timer" and id == timeout then
  439.       error("Timed out while waiting for turtle.", 0)
  440.     elseif event == "modem_message" and type(msg) == "table" then
  441.       if msg.Ok and msg.Action == "ARRIVED" then
  442.         PrintGoodToOutput("Turtle completed path.")
  443.         break
  444.       elseif not msg.Ok then
  445.         error(string.format("Remote error: %s", msg.Error), 0)
  446.       else
  447.         error("Unknown transmission received.", 0)
  448.       end
  449.     end
  450.   end
  451.  
  452.   PopOutputStack()
  453. end
  454.  
  455. local function ToggleDebug()
  456.   PushOutputStack "DEBUG"
  457.   Pathfinder.Debug.PlaceBlocks = not Pathfinder.Debug.PlaceBlocks
  458.   if Pathfinder.Debug.PlaceBlocks then
  459.     PrintToOutput "Enabled."
  460.   else
  461.     PrintToOutput "Disabled."
  462.   end
  463.  
  464.   PopOutputStack()
  465. end
  466.  
  467. --[[
  468.   state.map = {
  469.     serialized = {} or nil
  470.     serializing = true or false
  471.     percent = 0 <-> 1
  472.   }
  473.   state.goldBlock = {x, y, z} or nil
  474.   state.diamondBlock = {x, y, z} or nil
  475.  
  476. ]]
  477. Redraw = function()
  478.   local w, h = frame.getSize()
  479.  
  480.   frame.setBackgroundColor(colors.black)
  481.   frame.clear()
  482.  
  483.   -- Header
  484.   DrawBox(frame, 1, 1, w, 3, state.busy and colors.red or colors.gray)
  485.   CenterText(frame, 1, 1, w, 3, state.busy and "Pathfinder/Mapper Controller (Busy)" or "Pathfinder/Mapper Controller")
  486.  
  487.   -- Map information box
  488.   DrawBox(frame, 2, 4, 22, 1, colors.purple)
  489.   CenterText(frame, 2, 4, 22, 1, "Map Data")
  490.   DrawBox(frame, 2, 5, 22, 6, colors.lightGray)
  491.   frame.setCursorPos(3, 6)
  492.   frame.setTextColor(colors.white)
  493.   if state.map.serialized then
  494.     frame.write(string.format("Name: %s", Pathfinder.Map.Name))
  495.     frame.setCursorPos(3, 7)
  496.     frame.write(string.format("Offs: %d %d %d", Pathfinder.Map.Offset[1], Pathfinder.Map.Offset[2], Pathfinder.Map.Offset[3]))
  497.     frame.setCursorPos(3, 8)
  498.     frame.write(string.format("Size: %d bytes", state.map.size))
  499.   elseif state.map.serializing then
  500.     frame.write("Serializing")
  501.     frame.setCursorPos(3, 7)
  502.     local line = string.rep('\143', math.floor(19 * state.map.percent + 0.5))
  503.     frame.write("[")
  504.     frame.setTextColor(colors.green)
  505.     frame.write(line)
  506.     frame.setTextColor(colors.white)
  507.     frame.setCursorPos(22, 7)
  508.     frame.write(']')
  509.   else
  510.     frame.write("No map data.")
  511.   end
  512.  
  513.   -- Pathfinder controls
  514.   DrawBox(frame, 28, 4, 22, 1, colors.purple)
  515.   CenterText(frame, 28, 4, 22, 1, "Controls")
  516.   DrawBox(frame, 28, 5, 22, 6, colors.lightGray)
  517.  
  518.   -- Scan output
  519.   DrawBox(frame, 2, 12, w - 2, 1, colors.purple)
  520.   CenterText(frame, 2, 12, w - 2, 1, "Output")
  521.   DrawBox(frame, 2, 13, w - 2, 7, colors.lightGray)
  522.  
  523.   -- SECOND MONITOR
  524.  
  525.   local w, h = frame2.getSize()
  526.   frame2.setBackgroundColor(colors.black)
  527.   frame2.clear()
  528.  
  529.   DrawBox(frame2, 1, 1, w, h, colors.gray)
  530.  
  531.  
  532.   DrawButtons()
  533.   outputWindow.redraw()
  534.   frame.PushBuffer()
  535.   frame2.PushBuffer()
  536. end
  537.  
  538. local function Main()
  539.   PushOutputStack("MAIN")
  540.   local w, h = frame.getSize()
  541.  
  542.   -- Serialize map data
  543.   Button(frame, 3, 10, 20, 1, colors.white, colors.green, colors.blue, "Serialize Map Data", Serialize)
  544.  
  545.   -- Scan
  546.   Button(frame, 29, 6, 6, 3, colors.white, colors.green, colors.blue, "SCAN", Scan)
  547.   -- Pathfind
  548.   Button(frame, 36, 6, 6, 3, colors.white, colors.green, colors.blue, "PATH", Path)
  549.   -- Draw path
  550.   Button(frame, 43, 6, 6, 3, colors.white, colors.green, colors.blue, "DRAW", Draw)
  551.   -- Transmit to turtle
  552.   Button(frame, 29, 10, 10, 1, colors.white, colors.green, colors.blue, "TRANSMIT", Transmit)
  553.   -- Enable debug
  554.   Button(frame, 42, 10, 7, 1, colors.white, colors.green, colors.blue, "DEBUG", ToggleDebug)
  555.  
  556.   -- Reboot
  557.   Button(frame, w - 2, 1, 3, 3, colors.white, colors.red, colors.red, "", function() Redraw() end)
  558.  
  559.   -- BUTTONS FOR FACING SETTING
  560.   local up = "\24"
  561.   local down = "\25"
  562.   local right = "\26"
  563.   local left = "\27"
  564.   local btns = {}
  565.   local function enable(i)
  566.     for j = 1, 4 do
  567.       if i == j then
  568.         btns[j].enable = true
  569.       else
  570.         btns[j].enable = false
  571.       end
  572.     end
  573.   end
  574.  
  575.   btns[1] = Button(frame2, 3, 1, 1, 1, colors.white, colors.blue, colors.lightGray, up, function()
  576.     startFacing = 0
  577.     enable(1)
  578.   end)
  579.   btns[2] = Button(frame2, 3, 3, 1, 1, colors.white, colors.blue, colors.lightGray, down, function()
  580.     startFacing = 2
  581.     enable(2)
  582.   end)
  583.   btns[3] = Button(frame2, 4, 2, 1, 1, colors.white, colors.blue, colors.lightGray, right, function()
  584.     startFacing = 1
  585.     enable(3)
  586.   end)
  587.   btns[4] = Button(frame2, 2, 2, 1, 1, colors.white, colors.blue, colors.lightGray, left, function()
  588.     startFacing = 3
  589.     enable(4)
  590.   end)
  591.   enable(1)
  592.  
  593.   PrintToOutput "Ready."
  594.   Redraw()
  595.  
  596.   while true do
  597.     local event, _, x, y = os.pullEvent("monitor_touch")
  598.     state.busy = true
  599.     Redraw()
  600.     CheckButtons(x, y)
  601.     state.busy = false
  602.     Redraw()
  603.   end
  604. end
  605.  
  606. local function SIGTERM()
  607.   while true do
  608.     local event, data, x, y = os.pullEventRaw()
  609.  
  610.     if event == "monitor_touch" and x >= mw - 2 and y <= 3 then
  611.       if state.busy then
  612.         os.queueEvent("terminate")
  613.       else
  614.         os.sleep()
  615.         os.reboot()
  616.       end
  617.     elseif event == "task_complete" then
  618.       print(data, x, y)
  619.     end
  620.   end
  621. end
  622.  
  623. while true do
  624.   local ok, err = pcall(parallel.waitForAny, Main, SIGTERM)
  625.  
  626.   if not ok then
  627.     printError(err)
  628.     pcall(PrintErrorToOutput, "ERRORED -", err)
  629.     if not err:lower():find("yielding") then
  630.       pcall(PrintErrorToOutput, "Not due to too long without yielding. Stopping.")
  631.       break
  632.     else
  633.       pcall(PrintErrorToOutput, "It is unknown if the operation completed.")
  634.     end
  635.     outputStack = {"MAIN"}
  636.     os.sleep(5)
  637.   else
  638.     break
  639.   end
  640. end
  641.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement