Sxw1212

SkyScraper

Aug 18th, 2013
316
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.11 KB | None | 0 0
  1. function centerPrint(sText)
  2.     local w, h = term.getSize()
  3.     local x, y = term.getCursorPos()
  4.     x = math.max(math.floor((w / 2) - (#sText / 2)), 0)
  5.     term.setCursorPos(x, y)
  6.     term.write(sText)
  7. end
  8.  
  9. function clear()
  10.     term.clear()
  11.     term.setCursorPos(1, 1)
  12. end
  13.  
  14. function nextLine(n)
  15.     n = n or 1
  16.     local x, y = term.getCursorPos()
  17.     term.setCursorPos(x, y + n)
  18. end
  19.  
  20. -- Update
  21.     local url = "https://raw.github.com/Sxw1212/SkyScraper/master/"
  22.     local res = http.get(url .. "elev.lua")
  23.     if res then
  24.         local fh = fs.open("/startup", "w")
  25.         fh.write(res.readAll())
  26.         fh.close()
  27.     else
  28.         clear()
  29.         centerPrint("SkyScraper by Sxw1212")
  30.         nextLine()
  31.         centerPrint("Warning: Updater failed")
  32.         sleep(1)
  33.     end
  34.     local res = http.get(url .. "goroutine.lua")
  35.     if res then
  36.         local fh = fs.open("/goroutine", "w")
  37.         fh.write(res.readAll())
  38.         fh.close()
  39.     else
  40.         clear()
  41.         centerPrint("SkyScraper by Sxw1212")
  42.         nextLine()
  43.         centerPrint("Warning: Updater failed")
  44.         sleep(1)
  45.     end
  46.    
  47. -- System test
  48.     os.loadAPI("goroutine")
  49.  
  50.     clear()
  51.     centerPrint("SkyScraper by Sxw1212")
  52.     nextLine()
  53.     centerPrint("Elevator starting. Please wait")
  54.     nextLine()
  55.     centerPrint("Running System Test...")
  56.    
  57.     if peripheral.getType("bottom") ~= "rednet_cable" then
  58.         nextLine()
  59.         centerPrint("Error: No cable on bottom")
  60.         error()
  61.     end
  62.     if peripheral.getType("back") ~= "modem" then
  63.         nextLine()
  64.         centerPrint("Error: No modem on back")
  65.         error()
  66.     end
  67.    
  68.     sleep(0.25)
  69.    
  70.     nextLine()
  71.     centerPrint("System test completed, starting...")
  72.    
  73.     sleep(0.25)
  74.     clear()
  75.  
  76. -- Vars
  77.     cfg = {}
  78.     PORT = 50101
  79.     PREFIX = "SKYSCRAPER:"
  80.     COLORS = {
  81.         ["detector"] = colors.white,
  82.         ["boarding"] = colors.orange,
  83.         ["elevator"] = colors.magenta
  84.     }
  85.     MODEM = peripheral.wrap("back")
  86.     ELEVATORS = {}
  87.     FLOORS = {"Call Elevator"}
  88.     STAT = "CLEAR"
  89.     SELECTED = 1
  90.     REFRESHQUEUE = true
  91.     MODEM.open(PORT)
  92.  
  93. -- Helper functions
  94.    
  95.     function refresh()
  96.         if REFRESHQUEUE then
  97.             REFRESHQUEUE = false
  98.             os.queueEvent("refresh")
  99.         end
  100.     end
  101.    
  102.     function table.copy(t)
  103.         local t2 = {}
  104.         for k,v in pairs(t) do
  105.             t2[k] = v
  106.         end
  107.         return t2
  108.     end
  109.     function send(msg)
  110.         MODEM.transmit(PORT, PORT, PREFIX .. textutils.serialize(msg))
  111.     end
  112.    
  113.     function recv()
  114.         while true do
  115.             local _, _, _, _, msg = os.pullEvent("modem_message")
  116.             if msg:sub(1, #PREFIX) == PREFIX then
  117.                 local trans = msg:sub((#PREFIX)+1)
  118.                 return textutils.unserialize(trans)
  119.             end
  120.         end
  121.     end
  122.    
  123.     function menuCompat()
  124.         -- Somebody help me, I have no idea how else to do this
  125.         local smenu = table.copy(ELEVATORS)
  126.         smenu[#smenu+1] = cfg
  127.         table.sort(smenu, function (a,b) return (a.y > b.y) end)
  128.        
  129.         local sorted = {}
  130.         local len = #smenu
  131.         for i = 1, len do
  132.             sorted[i] = smenu[i].name
  133.         end
  134.         table.insert(sorted, 1, "Call Elevator")
  135.         FLOORS = sorted
  136.     end
  137.    
  138.     function addFloor(data)
  139.         local contains = false
  140.         for k, v in pairs(ELEVATORS) do
  141.             if v.y == data.y then
  142.                 contains = true
  143.                 ELEVATORS[k].name = data.name
  144.             end
  145.         end
  146.         if not contains then
  147.             table.insert(ELEVATORS, data)
  148.         end
  149.         menuCompat()
  150.     end
  151.    
  152.     function runmenu()
  153.         local function render()
  154.             clear()
  155.             term.setCursorPos(1, 1)
  156.             centerPrint("SkyScraper by Sxw1212")
  157.             nextLine(2)
  158.             for k, v in pairs(FLOORS) do
  159.                 local val = v
  160.                 if cfg.name == v then
  161.                     val = "-" .. val .. "-"
  162.                 elseif SELECTED == k then
  163.                     val = "[" .. val .. "]"
  164.                 end
  165.                 centerPrint(val)
  166.                 nextLine()
  167.             end
  168.         end
  169.         render()
  170.         while true do
  171.             local e, k = os.pullEvent("key")
  172.             if k == keys.up then
  173.                 if SELECTED ~= 1 then
  174.                     if FLOORS[SELECTED - 1] ~= cfg.name then
  175.                         SELECTED = SELECTED - 1
  176.                     elseif SELECTED > 2 then
  177.                         SELECTED = SELECTED - 2
  178.                     end
  179.                 end
  180.             elseif k == keys.down then
  181.                 if FLOORS[SELECTED + 1] then
  182.                     if FLOORS[SELECTED + 1] ~= cfg.name then
  183.                         SELECTED = SELECTED + 1
  184.                     elseif FLOORS[SELECTED + 2] then
  185.                         SELECTED = SELECTED + 2
  186.                     end
  187.                 end
  188.             elseif k == keys.enter then
  189.                 local sel = FLOORS[SELECTED]
  190.                 SELECTED = 1
  191.                 return sel
  192.             end
  193.             render()
  194.         end
  195.     end
  196.  
  197. -- Config
  198.     if not fs.exists("/sky.cfg") then
  199.         centerPrint("SkyScraper configuration")
  200.         term.setCursorPos(1, 2)
  201.         write("Y-Level: ")
  202.         cfg.y = tonumber(read())
  203.         write("Floor name: ")
  204.         cfg.name = read()
  205.        
  206.         local fh = fs.open("/sky.cfg", "w")
  207.         fh.write(textutils.serialize(cfg))
  208.         fh.close()
  209.        
  210.         centerPrint("Done!")
  211.         sleep(0.25)
  212.         clear()
  213.     end
  214.     local fh = fs.open("/sky.cfg", "r")
  215.     cfg = textutils.unserialize(fh.readAll())
  216.     fh.close()
  217.     if cfg.y and cfg.name then
  218.         centerPrint("SkyScraper configuration")
  219.         nextLine()
  220.         centerPrint("Loaded from file!")
  221.         clear()
  222.         cfg.y = tonumber(cfg.y)
  223.     else
  224.         fs.delete("/sky.cfg")
  225.         os.reboot()
  226.     end
  227.  
  228. -- Announce
  229.     send({ "DISCOVER", cfg })
  230.  
  231. -- Handlers
  232.    
  233.     function msgHandler()
  234.         while true do
  235.             local msg = recv()
  236.             if msg[1] == "CALL" then
  237.                 if STAT == "COMING" then
  238.                 else
  239.                     STAT = "BUSY"
  240.                     rs.setBundledOutput("bottom", COLORS.boarding)
  241.                     sleep(1)
  242.                     rs.setBundledOutput("bottom", 0)
  243.                     refresh()
  244.                 end
  245.             elseif msg[1] == "SENDING" then
  246.                 STAT = "BUSY"
  247.                
  248.                 if tostring(msg[2]) == tostring(cfg.y) then
  249.                     STAT = "COMING"
  250.                     rs.setBundledOutput("bottom", COLORS.elevator)
  251.                 end
  252.                 refresh()
  253.             elseif msg[1] == "DISCOVER" then
  254.                 addFloor(msg[2])
  255.                 send({ "HELLO", cfg })
  256.                 refresh()
  257.             elseif msg[1] == "HELLO" then
  258.                 addFloor(msg[2])
  259.                 refresh()
  260.             elseif msg[1] == "CLEAR" then
  261.                 STAT = "CLEAR"
  262.                 refresh()
  263.                 rs.setBundledOutput("bottom", 0)
  264.             elseif msg[1] == "RESET" then
  265.                 os.reboot()
  266.             end
  267.         end
  268.     end
  269.    
  270.     function menu()
  271.         if STAT == "CLEAR" then
  272.             local x, y = term.getSize()
  273.             local floor = runmenu()
  274.             if floor == "Call Elevator" then
  275.                 send({ "CALL", cfg })
  276.                 STAT = "COMING"
  277.                 rs.setBundledOutput("bottom", COLORS.elevator)
  278.             elseif floor ~= cfg.name then
  279.                 for k, v in pairs(ELEVATORS) do
  280.                     if v.name == floor then
  281.                         send({ "SENDING", v.y, cfg})
  282.                     end
  283.                 end
  284.                 STAT = "BUSY"
  285.                 rs.setBundledOutput("bottom", COLORS.boarding)
  286.             end
  287.             refresh()
  288.         elseif STAT == "BUSY" then
  289.             clear()
  290.             centerPrint("SkyScraper by Sxw1212")
  291.             nextLine(7)
  292.             centerPrint("Elevator busy, please wait")
  293.             os.pullEvent("AReallyLongEventThatYou'dBetterNotCallOrElse...")
  294.         elseif STAT == "COMING" then
  295.             clear()
  296.             centerPrint("SkyScraper by Sxw1212")
  297.             nextLine(7)
  298.             centerPrint("Elevator coming, please wait")
  299.             while true do
  300.                 os.pullEvent("redstone")
  301.                 if colors.test(rs.getBundledInput("bottom"), COLORS.detector) then
  302.                     STAT = "CLEAR"
  303.                     send({ "CLEAR", cfg })
  304.                     rs.setBundledOutput("bottom", 0)
  305.                     refresh()
  306.                 end
  307.             end
  308.         end
  309.     end
  310.    
  311.     function main()
  312.         goroutine.spawn("msgHandler", msgHandler)
  313.         goroutine.assignEvent("msgHandler", "modem_message")
  314.         while true do
  315.             REFRESHQUEUE = true
  316.             goroutine.spawn("menu", menu)
  317.            
  318.             goroutine.assignEvent("menu", "key")
  319.             goroutine.assignEvent("menu", "redstone")
  320.            
  321.             os.pullEvent("refresh")
  322.            
  323.             sleep(0.1)
  324.             goroutine.kill("menu")
  325.             sleep(0.1)
  326.         end
  327.     end
  328.    
  329.     goroutine.run(main)
Advertisement
Add Comment
Please, Sign In to add comment