Advertisement
blunty666

multiglass_0_5

Oct 25th, 2015
646
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.26 KB | None | 0 0
  1. local tArgs = {...}
  2. local bridge
  3. if type(tArgs[1]) == "string" and peripheral.getType(tArgs[1]) == "openperipheral_bridge" then
  4.     bridge = peripheral.wrap(tArgs[1])
  5.     bridge.clear()
  6. else
  7.     error("could not find bridge on side: "..tostring(tArgs[1]))
  8. end
  9.  
  10. do -- API installing / loading
  11.     local program = fs.getDir(shell.getRunningProgram())
  12.  
  13.     local function get(url)
  14.         local response = http.get(url)         
  15.         if response then
  16.             local fileData = response.readAll()
  17.             response.close()
  18.             return fileData
  19.         end
  20.         return false
  21.     end
  22.  
  23.     local function save(fileData, path)
  24.         local handle = fs.open(path, "w")
  25.         if handle then
  26.             handle.write(fileData)
  27.             handle.close()
  28.             return true
  29.         else
  30.             return false
  31.         end
  32.     end
  33.  
  34.     local function fetch(url, path)
  35.         local fileData = get(url)          
  36.         if fileData then
  37.             if save(fileData, path) then
  38.                 return true
  39.             else
  40.                 printError("Save failed: ", path)
  41.             end
  42.         else
  43.             printError("Download failed: ", url)
  44.         end
  45.         return false
  46.     end
  47.  
  48.     local apiList = {
  49.         {"tiles", "https://raw.githubusercontent.com/blunty666/Tiles/master/tiles.lua"},
  50.         {"guiTiles", "https://raw.githubusercontent.com/blunty666/Tiles/master/apis/guiTiles.lua"},
  51.         {"glassWindow", "https://raw.githubusercontent.com/blunty666/Tiles/master/apis/glassWindow.lua"},
  52.     }
  53.  
  54.     for _, api in ipairs(apiList) do
  55.         local apiName, apiURL = unpack(api)
  56.         local apiPath = fs.combine(program, apiName)
  57.         if not _G[apiName] then -- api not loaded already
  58.             if not fs.exists(apiPath) then -- api file does not exist
  59.                 print("Downloading API: "..apiName)
  60.                 if not fetch(apiURL, apiPath) then
  61.                     printError("Could not load API: "..apiName)
  62.                     return
  63.                 end
  64.             elseif fs.isDir(apiPath) then -- there is an invalid directory
  65.                 printError("Invalid directory at: "..apiPath)
  66.                 printError("Could not load API: "..apiName)
  67.                 return
  68.             end
  69.             if not os.loadAPI(apiPath) then
  70.                 printError("Could not load API: "..apiName)
  71.                 return
  72.             end
  73.         end
  74.     end
  75. end
  76.  
  77. local function newPlayerSurfaceHandler(playerUUID, surfaceHandler)
  78.    
  79.     local guiHandler = guiTiles.newGuiHandler(surfaceHandler)
  80.  
  81.     local windows = {
  82.         list = {},
  83.         windowToThread = {},
  84.         orderedList = {},
  85.     }
  86.     windows.new = function(playerUUID, threadID, tile, width, height, xOffset, yOffset, zOffset)
  87.         local uniqueID
  88.         repeat
  89.             uniqueID = math.random(0, 9999)
  90.         until not windows.list[uniqueID]
  91.        
  92.         local redirect = glassWindow.new(tile, playerUUID, uniqueID, xOffset, yOffset, zOffset, width, height)
  93.        
  94.         windows.list[uniqueID] = redirect
  95.         table.insert(windows.orderedList, uniqueID)
  96.         redirect.setOffset(nil, nil, 5*#windows.orderedList)
  97.         windows.windowToThread[uniqueID] = threadID
  98.         return redirect
  99.     end
  100.     windows.reorder = function()
  101.         for i, windowID in ipairs(windows.orderedList) do
  102.             windows.list[windowID].setOffset(nil, nil, 5*i)
  103.         end
  104.     end
  105.     windows.toFront = function(windowID)
  106.         for i, winID in ipairs(windows.orderedList) do
  107.             if winID == windowID then
  108.                 table.insert(windows.orderedList, table.remove(windows.orderedList, i))
  109.                 windows.reorder()
  110.                 return true
  111.             end
  112.         end
  113.         return false
  114.     end
  115.     windows.toBack = function(windowID)
  116.         for i, winID in ipairs(windows.orderedList) do
  117.             if winID == windowID then
  118.                 table.insert(windows.orderedList, 1, table.remove(windows.orderedList, i))
  119.                 windows.reorder()
  120.                 return true
  121.             end
  122.         end
  123.         return false
  124.     end
  125.     windows.delete = function(windowID)
  126.         local window = windows.list[windowID]
  127.         if window then
  128.             local tile = window.getTile()
  129.             tile:Delete()
  130.             windows.list[windowID] = nil
  131.             windows.windowToThread[windowID] = nil
  132.             for i, winID in ipairs(windows.orderedList) do
  133.                 if winID == windowID then
  134.                     table.remove(windows.orderedList, i)
  135.                     windows.reorder()
  136.                     break
  137.                 end
  138.             end
  139.             return true
  140.         end
  141.         return false
  142.     end
  143.  
  144.     local threads = {
  145.         list = {},
  146.         orderedList = {},
  147.     }
  148.     threads.new = function(func, terminal)
  149.         local uniqueID
  150.         repeat
  151.             uniqueID = math.random(0, 9999)
  152.         until not threads.list[uniqueID]
  153.        
  154.         local thread = {
  155.             ID = uniqueID,
  156.             running = true,
  157.             filter = nil,
  158.             thread = coroutine.create(func),
  159.             term = terminal,
  160.         }
  161.        
  162.         threads.list[uniqueID] = thread
  163.         table.insert(threads.orderedList, uniqueID)
  164.         return thread
  165.     end
  166.     threads.resume = function(threadInfo, eventType, ...)
  167.         if threadInfo.running then
  168.             if not threadInfo.filter or eventType == threadInfo.filter or eventType == "terminate" then
  169.                 threadInfo.filter = nil
  170.  
  171.                 local prevTerm = threadInfo.term and term.redirect(threadInfo.term)
  172.                 local ok, passback = coroutine.resume(threadInfo.thread, eventType, ...)
  173.                 if prevTerm then
  174.                     term.redirect(prevTerm)
  175.                 end
  176.  
  177.                 if not ok and coroutine.status(threadInfo.thread) == "dead" then
  178.                     threadInfo.running = false
  179.                     printError(passback)
  180.                 elseif coroutine.status(threadInfo.thread) == "dead" then
  181.                     threadInfo.running = false
  182.                 else
  183.                     threadInfo.filter = passback
  184.                 end
  185.             end
  186.         end
  187.     end
  188.     threads.launch = function(path, xOffset, yOffset, visible)
  189.         local thread
  190.         local fnFile, err = loadfile(path)
  191.         if fnFile then
  192.             local tEnv = {
  193.                 shell = shell,
  194.             }
  195.             setmetatable( tEnv, { __index = _G } )
  196.             setfenv( fnFile, tEnv )
  197.             thread = threads.new(fnFile, nil)
  198.         else
  199.             error(err)
  200.         end
  201.        
  202.         local tile = surfaceHandler:AddTile(0, -50, 1)
  203.         tile:SetScreenAnchor("MIDDLE", "MIDDLE")
  204.        
  205.         local window = windows.new(playerUUID, thread.ID, tile, 51, 19, xOffset, yOffset, 1)
  206.        
  207.         thread.term = window.term
  208.         threads.resume(thread)
  209.        
  210.         window.setVisible(visible)
  211.         window.setDrawn(true)
  212.        
  213.         return thread, window
  214.     end
  215.  
  216.     local function main()
  217.  
  218.         threads.launch("rom/programs/advanced/multishell", -(51*6/2), -(19*9/2), false)
  219.            
  220.         local activeWindowID = windows.orderedList[#windows.orderedList] or false
  221.         local nullClickTime, nullClickButton = -math.huge, false
  222.  
  223.         local eventHandlers = {
  224.             glasses_capture = function(event)
  225.                 for _, window in pairs(windows.list) do
  226.                     window.setVisible(true)
  227.                 end
  228.             end,
  229.             glasses_release = function(event)
  230.                 for _, window in pairs(windows.list) do
  231.                     window.setVisible(false)
  232.                 end
  233.             end,
  234.             glasses_mouse_down = function(event)
  235.                 local newClickTime = os.clock()
  236.                 if nullClickButton == event[5] and newClickTime - nullClickTime < 0.25 then
  237.                     if nullClickButton == 0 then
  238.                         for _, window in pairs(windows.list) do
  239.                             window.setVisible(false)
  240.                         end
  241.                         local capture = surfaceHandler:GetCapture()
  242.                         if capture then
  243.                             capture.stopCapturing()
  244.                         end
  245.                     elseif nullClickButton == 1 then
  246.                         threads.launch("rom/programs/advanced/multishell", -(51*6/2) + math.random(-30, 30), -(19*9/2) + math.random(-30, 30), true)
  247.                     end
  248.                     nullClickTime, nullClickButton = -math.huge, false
  249.                 end
  250.                 nullClickTime = newClickTime
  251.                 nullClickButton = event[5]
  252.             end,
  253.             glasses_custom_event = function(event)
  254.                 -- glasses_custom_event - "unknown" - windowID - playerUUID - {event details (...)}
  255.                 if activeWindowID ~= event[3] then
  256.                     windows.toFront(event[3])
  257.                     activeWindowID = event[3]
  258.                 end
  259.                 local threadID = windows.windowToThread[event[3]]
  260.                 if threadID then
  261.                     local thread = threads.list[threadID]
  262.                     if thread then
  263.                         threads.resume(thread, unpack(event, 5))
  264.                     end
  265.                 end
  266.             end,
  267.         }
  268.         local event = {}
  269.         local handler
  270.         while true do
  271.             guiHandler:HandleEvent(event)
  272.            
  273.             handler = eventHandlers[ event[1] ]
  274.             if handler then -- pass event to handler
  275.                 handler(event)
  276.             else -- resume all threads with the event
  277.                 for _, thread in pairs(threads.list) do
  278.                     threads.resume(thread, unpack(event))
  279.                 end
  280.             end
  281.            
  282.             -- check for dead threads
  283.             local newThreadOrderedList = {}
  284.             for _, threadID in ipairs(threads.orderedList) do
  285.                 local thread = threads.list[threadID]
  286.                 if not thread then
  287.                    
  288.                 elseif not thread.running then
  289.                     -- find all windows belonging to this thread
  290.                     local threadWindows = {}
  291.                     for windowID, _threadID in pairs(windows.windowToThread) do
  292.                         if threadID == _threadID then
  293.                             table.insert(threadWindows, windowID)
  294.                         end
  295.                     end
  296.                     -- delete windows
  297.                     for _, windowID in ipairs(threadWindows) do
  298.                         windows.delete(windowID)
  299.                     end
  300.                     -- remove thread
  301.                     threads.list[threadID] = nil
  302.                
  303.                     activeWindowID = windows.orderedList[#windows.orderedList] or false
  304.                 else
  305.                     table.insert(newThreadOrderedList, threadID)
  306.                 end
  307.             end
  308.             threads.orderedList = newThreadOrderedList
  309.            
  310.             -- check if all threads are dead   
  311.             if #newThreadOrderedList == 0 then
  312.                 -- stop capturing
  313.                 local capture = surfaceHandler:GetCapture()
  314.                 if capture then
  315.                     capture.stopCapturing() -- if connected
  316.                 end
  317.                 -- create new thread with window
  318.                 threads.launch("rom/programs/advanced/multishell", -(51*6/2), -(19*9/2), false)
  319.             end
  320.                
  321.             event = {coroutine.yield()}
  322.         end
  323.     end
  324.  
  325.     local function pushUpdates()
  326.         while true do
  327.             for ID, window in pairs(windows.list) do
  328.                 if window.hasUpdates() then
  329.                     window.pushUpdates()
  330.                 end
  331.             end
  332.             coroutine.yield()
  333.         end
  334.     end
  335.    
  336.     return function() parallel.waitForAny(main, pushUpdates) end
  337. end
  338.  
  339. local handler = tiles.newMultiSurfaceHandler(bridge, newPlayerSurfaceHandler)
  340.  
  341. handler:Run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement