Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local colourToHex = {
- [colours.white] = 0xffffff,
- [colours.orange] = 0xffa500,
- [colours.magenta] = 0xff00ff,
- [colours.lightBlue] = 0xadd8e6,
- [colours.yellow] = 0xffff00,
- [colours.lime] = 0xbfff00,
- [colours.pink] = 0xffc0cb,
- [colours.grey] = 0x808080,
- [colours.lightGrey] = 0xd3d3d3,
- [colours.cyan] = 0x00ffff,
- [colours.purple] = 0x800080,
- [colours.blue] = 0x0000ff,
- [colours.brown] = 0xa52a2a,
- [colours.green] = 0x00ff00,
- [colours.red] = 0xff0000,
- [colours.black] = 0x000000,
- }
- local hexValues = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}
- local hexToColour = {}
- for i = 1, 16 do
- hexToColour[hexValues[i]] = 2^(i-1)
- end
- local charOffset = {
- [ 33 ] = 2, [ 39 ] = 2, [ 40 ] = 1, [ 41 ] = 1, [ 42 ] = 1, [ 44 ] = 2, [ 46 ] = 2, [ 58 ] = 2, [ 59 ] = 2,
- [ 60 ] = 1, [ 62 ] = 1, [ 73 ] = 1, [ 91 ] = 1, [ 93 ] = 1, [ 96 ] = 2, [ 102 ] = 1, [ 105 ] = 2, [ 107 ] = 1,
- [ 108 ] = 2, [ 116 ] = 1, [ 123 ] = 1, [ 124 ] = 2, [ 125 ] = 1,
- }
- local function newRedirect(surface, xOffset, yOffset, width, height)
- local redirect = {
- surface = surface,
- xOffset = xOffset, yOffset = yOffset, zOffset = 1,
- width = 0, height = 0,
- map = {},
- clickCatcher = {
- ID = false,
- object = false,
- },
- cursor = {
- xPos = 1,
- yPos = 1,
- blink = false,
- object = false,
- },
- textColour = colours.white,
- backgroundColour = colours.black,
- isDrawn = false,
- isVisible = true,
- hasChanged = false,
- opacity = 1,
- }
- local function drawClickCatcher()
- local clickCatcherObject = redirect.surface.addBox(redirect.xOffset, redirect.yOffset, redirect.width*6, redirect.height*9, 0x000000, 0)
- clickCatcherObject.setScreenAnchor("MIDDLE", "MIDDLE")
- clickCatcherObject.setVisible(redirect.isVisible)
- clickCatcherObject.setZ(redirect.zOffset + 3)
- redirect.clickCatcher.ID = clickCatcherObject.getId()
- redirect.clickCatcher.object = clickCatcherObject
- end
- local function drawText(xPos, yPos, text, textColour)
- local textObject = redirect.surface.addText((xPos-1)*6 + redirect.xOffset + (charOffset[string.byte(text)] or 0), (yPos-1)*9 + redirect.yOffset, text, colourToHex[textColour])
- textObject.setScreenAnchor("MIDDLE", "MIDDLE")
- textObject.setVisible(redirect.isVisible)
- textObject.setZ(redirect.zOffset + 1)
- return textObject
- end
- local function drawBackground(xPos, yPos, backgroundColour)
- local backgroundObject = redirect.surface.addBox((xPos-1)*6 + redirect.xOffset, (yPos-1)*9 + redirect.yOffset, 6, 9, colourToHex[backgroundColour], redirect.opacity)
- backgroundObject.setScreenAnchor("MIDDLE", "MIDDLE")
- backgroundObject.setVisible(redirect.isVisible)
- backgroundObject.setZ(redirect.zOffset)
- return backgroundObject
- end
- local function drawCursor()
- local cursorObject = redirect.surface.addText((redirect.cursor.xPos-1)*6 + redirect.xOffset + (charOffset[string.byte("_")] or 0), (redirect.cursor.yPos-1)*9 + redirect.yOffset, "_", colourToHex[redirect.textColour])
- cursorObject.setScreenAnchor("MIDDLE", "MIDDLE")
- cursorObject.setVisible((redirect.isVisible and redirect.cursor.blink and (redirect.map[redirect.cursor.yPos] and redirect.map[redirect.cursor.yPos][redirect.cursor.xPos]) and true) or false)
- cursorObject.setZ(redirect.zOffset + 2)
- return cursorObject
- end
- local function createCoord(xPos, yPos, text, textColour, backgroundColour)
- local coord = {
- data = {
- text = text,
- textColour = textColour,
- backgroundColour = backgroundColour,
- },
- text = false,
- background = false,
- }
- if redirect.isDrawn then
- coord.text = drawText(xPos, yPos, text, textColour)
- coord.background = drawBackground(xPos, yPos, backgroundColour)
- end
- return coord
- end
- local function updateCoord(xPos, yPos, text, textColour, backgroundColour)
- local coord = redirect.map[yPos] and redirect.map[yPos][xPos]
- if coord then
- local coordData = coord.data
- if coordData.text ~= text or coordData.textColour ~= textColour or coordData.backgroundColour ~= backgroundColour then
- coordData.text = text
- coordData.textColour = textColour
- coordData.backgroundColour = backgroundColour
- if redirect.isDrawn then
- coord.text.setText(text)
- coord.text.setColor(colourToHex[textColour])
- coord.text.setX((xPos-1)*6 + redirect.xOffset + (charOffset[string.byte(text)] or 0))
- coord.background.setColor(colourToHex[backgroundColour])
- redirect.hasChanged = true
- end
- end
- end
- end
- local function updateCursor()
- if redirect.isDrawn then
- local cursor = redirect.cursor.object
- if cursor then
- cursor.setX((redirect.cursor.xPos-1)*6 + redirect.xOffset + (charOffset[string.byte("_")] or 0))
- cursor.setY((redirect.cursor.yPos-1)*9 + redirect.yOffset)
- cursor.setZ(redirect.zOffset + 2)
- cursor.setVisible((redirect.isVisible and redirect.cursor.blink and (redirect.map[redirect.cursor.yPos] and redirect.map[redirect.cursor.yPos][redirect.cursor.xPos]) and true) or false)
- cursor.setColor(colourToHex[redirect.textColour])
- end
- end
- end
- redirect.getDrawn = function()
- return redirect.isDrawn
- end
- redirect.setDrawn = function(isDrawn)
- if type(isDrawn) == "boolean" and redirect.isDrawn ~= isDrawn then
- if isDrawn == true then
- for yPos, line in ipairs(redirect.map) do
- for xPos, coord in ipairs(line) do
- coord.text = drawText(xPos, yPos, coord.data.text, coord.data.textColour)
- coord.background = drawBackground(xPos, yPos, coord.data.backgroundColour)
- end
- end
- drawClickCatcher()
- redirect.cursor.object = drawCursor()
- else
- for yPos, line in ipairs(redirect.map) do
- for xPos, coord in ipairs(line) do
- coord.text.delete()
- coord.background.delete()
- coord.text = false
- coord.background = false
- end
- end
- redirect.cursor.object.delete()
- redirect.cursor.object = false
- redirect.clickCatcher.ID = false
- redirect.clickCatcher.object.delete()
- redirect.clickCatcher.object = false
- end
- redirect.isDrawn = isDrawn
- redirect.hasChanged = true
- return true
- end
- return false
- end
- redirect.getVisible = function()
- return redirect.isVisible
- end
- redirect.setVisible = function(isVisible)
- if type(isVisible) == "boolean" and redirect.isVisible ~= isVisible then
- if redirect.isDrawn then
- for yPos, line in ipairs(redirect.map) do
- for xPos, coord in ipairs(line) do
- coord.text.setVisible(isVisible)
- coord.background.setVisible(isVisible)
- end
- end
- redirect.clickCatcher.object.setVisible(isVisible)
- redirect.cursor.object.setVisible(isVisible and redirect.cursor.blink)
- redirect.hasChanged = true
- end
- redirect.isVisible = isVisible
- return true
- end
- return false
- end
- redirect.getOpacity = function()
- return redirect.opacity
- end
- redirect.setOpacity = function(opacity)
- if type(opacity) == "number" and opacity >= 0 and opacity <= 1 then
- if redirect.isDrawn then
- for yPos, line in ipairs(redirect.map) do
- for xPos, coord in ipairs(line) do
- coord.background.setOpacity(opacity)
- end
- end
- redirect.hasChanged = true
- end
- redirect.opacity = opacity
- return true
- end
- return false
- end
- redirect.getSurface = function()
- return redirect.surface
- end
- redirect.setSurface = function(surface, redraw)
- redirect.surface = surface
- if redraw == true and redirect.isDrawn then
- redirect.setDrawn(false)
- redirect.setDrawn(true)
- end
- end
- redirect.getOffset = function()
- return redirect.xOffset, redirect.yOffset
- end
- redirect.setOffset = function(xOffset, yOffset, zOffset)
- redirect.xOffset = math.floor(tonumber(xOffset) or redirect.xOffset)
- redirect.yOffset = math.floor(tonumber(yOffset) or redirect.yOffset)
- redirect.zOffset = math.min(250, math.max(1, math.floor(tonumber(xOffset) or redirect.xOffset)))
- if redirect.isDrawn then
- for yPos, line in ipairs(redirect.map) do
- for xPos, coord in ipairs(line) do
- coord.text.setX((xPos-1)*6 + redirect.xOffset + (charOffset[string.byte(coord.data.text)] or 0))
- coord.text.setY((yPos-1)*9 + redirect.yOffset)
- coord.text.setZ(redirect.zOffset + 1)
- coord.background.setX((xPos-1)*6 + redirect.xOffset)
- coord.background.setY((yPos-1)*9 + redirect.yOffset)
- coord.background.setZ(redirect.zOffset)
- end
- end
- redirect.clickCatcher.object.setX(redirect.xOffset)
- redirect.clickCatcher.object.setY(redirect.yOffset)
- redirect.clickCatcher.object.setZ(redirect.zOffset + 3)
- updateCursor()
- redirect.hasChanged = true
- end
- return true
- end
- redirect.getSize = function()
- return redirect.width, redirect.height
- end
- redirect.setSize = function(width, height)
- for yPos = 1, math.max(height, redirect.height) do
- redirect.map[yPos] = redirect.map[yPos] or {}
- for xPos = 1, math.max(width, redirect.width) do
- if xPos <= width and yPos <= height then
- if not redirect.map[yPos][xPos] then
- redirect.map[yPos][xPos] = createCoord(xPos, yPos, " ", redirect.textColour, redirect.backgroundColour)
- end
- else
- if redirect.map[yPos][xPos] then
- local coord = redirect.map[yPos][xPos]
- if coord.text then
- coord.text.delete()
- end
- if coord.background then
- coord.background.delete()
- end
- if coord.clickCatcher then
- redirect.clickCatchers[coord.clickCatcher.getId()] = nil
- coord.clickCatcher.delete()
- end
- redirect.map[yPos][xPos] = nil
- end
- end
- end
- end
- if redirect.isDrawn then
- redirect.clickCatcher.object.delete()
- drawClickCatcher()
- end
- updateCursor()
- redirect.hasChanged = true
- redirect.width, redirect.height = width, height
- end
- redirect.getClick = function(objectID, xPos, yPos)
- if objectID == redirect.clickCatcher.ID then
- return math.ceil(xPos/6), math.ceil(yPos/9)
- else
- return false, false
- end
- end
- local term = {
- write = function(text)
- local textType = type(text)
- if textType == "string" or textType == "number" then
- local text = string.gsub(text, "%c", " ")
- local length = string.len(text)
- if length > 0 then
- if redirect.map[redirect.cursor.yPos] then
- for xPos = 1, length do
- updateCoord(xPos - 1 + redirect.cursor.xPos, redirect.cursor.yPos, string.sub(text, xPos, xPos), redirect.textColour, redirect.backgroundColour)
- end
- end
- redirect.cursor.xPos = redirect.cursor.xPos + length
- updateCursor()
- end
- end
- end,
- blit = function(text, textColour, backgroundColour)
- if type(text) ~= "string" or type(textColour) ~= "string" or type(backgroundColour) ~= "string" then
- error("Expected string, string, string", 2)
- end
- if #text ~= #textColour or #text ~= #backgroundColour then
- error("Arguments must be the same length", 2)
- end
- local text = string.gsub(text, "%c", " ")
- local length = string.len(text)
- if length > 0 then
- if redirect.map[redirect.cursor.yPos] then
- for xPos = 1, length do
- updateCoord(xPos - 1 + redirect.cursor.xPos, redirect.cursor.yPos, string.sub(text, xPos, xPos), hexToColour[string.sub(textColour, xPos, xPos)] or redirect.textColour, hexToColour[string.sub(backgroundColour, xPos, xPos)]or redirect.backgroundColour)
- end
- end
- redirect.cursor.xPos = redirect.cursor.xPos + length
- updateCursor()
- end
- end,
- clear = function()
- for yPos = 1, redirect.height do
- for xPos = 1, redirect.width do
- updateCoord(xPos, yPos, " ", redirect.textColour, redirect.backgroundColour)
- end
- end
- end,
- clearLine = function()
- if redirect.map[redirect.cursor.yPos] then
- for xPos = 1, redirect.width do
- updateCoord(xPos, redirect.cursor.yPos, " ", redirect.textColour, redirect.backgroundColour)
- end
- end
- end,
- getCursorPos = function()
- return redirect.cursor.xPos, redirect.cursor.yPos
- end,
- setCursorPos = function(xPos, yPos)
- redirect.cursor.xPos = math.floor(tonumber(xPos) or redirect.cursor.xPos)
- redirect.cursor.yPos = math.floor(tonumber(yPos) or redirect.cursor.yPos)
- updateCursor()
- end,
- setCursorBlink = function(blink)
- if type(blink) == "boolean" then
- redirect.cursor.blink = blink
- updateCursor()
- end
- end,
- isColour = function()
- return true
- end,
- getSize = function()
- return redirect.width, redirect.height
- end,
- scroll = function(noOfLines)
- local n = math.floor(tonumber(noOfLines) or 0)
- if n ~= 0 and redirect.height > 0 then
- for yPos = (n > 0 and 1) or redirect.height, (n < 0 and 1) or redirect.height, n/math.abs(n) do
- for xPos = 1, redirect.width do
- if redirect.map[yPos + n] then
- local coord = redirect.map[yPos + n][xPos].data
- updateCoord(xPos, yPos, coord.text, coord.textColour, coord.backgroundColour)
- else
- updateCoord(xPos, yPos, " ", redirect.textColour, redirect.backgroundColour)
- end
- end
- end
- end
- end,
- setTextColour = function(colour)
- local colour = tonumber(colour)
- if colourToHex[colour] then
- redirect.textColour = colour
- updateCursor()
- end
- end,
- getTextColour = function()
- return redirect.textColour
- end,
- setBackgroundColour = function(colour)
- local colour = tonumber(colour)
- if colourToHex[colour] then
- redirect.backgroundColour = colour
- updateCursor()
- end
- end,
- getBackgroundColour = function()
- return redirect.backgroundColour
- end,
- }
- term.isColor = term.isColour
- term.setTextColor = term.setTextColour
- term.getTextColor = term.getTextColour
- term.setBackgroundColor = term.setBackgroundColour
- term.getBackgroundColor = term.getBackgroundColour
- redirect.term = term
- redirect.setSize(width, height)
- return redirect
- end
- local function printUsage()
- print("redirectToGlass: <(string) programPath> <(string) username> <(string) bridgeSide>")
- end
- local tArgs = {...}
- local programPath, username, bridgeSide = tArgs[1], tArgs[2], tArgs[3]
- if type(programPath) ~= "string" then
- printError("programPath must be of type: string")
- printUsage()
- return
- elseif not fs.exists(programPath) or fs.isDir(programPath) then
- printError("File not found: "..programPath)
- printUsage()
- return
- end
- if type(username) ~= "string" then
- printError("username must be of type: string")
- printUsage()
- return
- end
- local bridge
- if type(bridgeSide) ~= "string" then
- printError("bridgeSide must be of type: string")
- printUsage()
- return
- else
- local peripheralType = peripheral.getType(bridgeSide)
- if peripheralType == "openperipheral_bridge" then
- bridge = peripheral.wrap(bridgeSide)
- else
- printError("terminal glasses bridge not found on side: "..bridgeSide)
- printUsage()
- return
- end
- end
- local playerSurface = false
- while not playerSurface do
- local players = bridge.getUsers()
- for _, playerData in ipairs(players) do
- if playerData.name == username then
- playerSurface = bridge.getSurfaceByName(username)
- playerSurface.clear()
- break
- end
- end
- if not playerSurface then
- os.pullEvent("glasses_attach")
- end
- end
- local width, height = 51, 19
- local xOffset, yOffset = -(math.floor(width*6/2)), -(math.floor(height*9/2))
- local redirect = newRedirect(playerSurface, xOffset, yOffset, width, height)
- redirect.setOpacity(1)
- redirect.setVisible(false)
- redirect.setDrawn(true)
- local ignoredEvents = {
- key = true,
- key_up = true,
- mouse_click = true,
- mouse_drag = true,
- mouse_scroll = true,
- mouse_up = true,
- term_resize = true,
- }
- local prevTerm = term.current()
- local fnFile, err = loadfile(programPath)
- if fnFile then
- local tEnv = {}
- setmetatable( tEnv, { __index = _G } )
- setfenv( fnFile, tEnv )
- local thread = coroutine.create(fnFile)
- local running, filter = true, nil
- local function resumeThread(event)
- if not filter or event[1] == filter or event[1] == "terminate" then
- filter = nil
- local ok, passback = coroutine.resume(thread, unpack(event))
- if not ok then
- running = false
- term.redirect(prevTerm)
- printError(passback)
- elseif coroutine.status(thread) == "dead" then
- running = false
- else
- filter = passback
- end
- end
- end
- term.redirect(redirect.term)
- local event, resume = {}, true
- local lastClickX, lastClickY = false, false
- while running do
- if resume and not ignoredEvents[event[1]] then
- resumeThread(event)
- end
- if redirect.hasChanged then
- bridge.sync()
- redirect.hasChanged = false
- end
- if running then
- event, resume = {coroutine.yield()}, true
- if event[1] == "glasses_key_down" then
- resumeThread({"key", event[5]})
- if #string.gsub(event[6], "%c", "") > 0 then
- resumeThread({"char", event[6]})
- end
- resume = false
- elseif event[1] == "glasses_key_up" then
- resumeThread({"key_up", event[5]})
- resume = false
- elseif event[1] == "glasses_component_mouse_down" then
- local xPos, yPos = redirect.getClick(event[5], event[7], event[8])
- if xPos and yPos then
- resumeThread({"mouse_click", event[9] + 1, xPos, yPos})
- lastClickX, lastClickY = xPos, yPos
- end
- resume = false
- elseif event[1] == "glasses_component_mouse_up" then
- local xPos, yPos = redirect.getClick(event[5], event[7], event[8])
- if xPos and yPos then
- resumeThread({"mouse_up", event[9] + 1, xPos, yPos})
- lastClickX, lastClickY = false, false
- end
- resume = false
- elseif event[1] == "glasses_mouse_up" then
- if lastClickX and lastClickY then
- resumeThread({"mouse_up", event[5] + 1, lastClickX, lastClickY})
- lastClickX, lastClickY = false, false
- end
- resume = false
- elseif event[1] == "glasses_component_mouse_wheel" then
- local xPos, yPos = redirect.getClick(event[5], event[7], event[8])
- if xPos and yPos then
- resumeThread({"mouse_scroll", -event[9]/math.abs(event[9]), xPos, yPos})
- end
- resume = false
- elseif event[1] == "glasses_attach" and event[3] == username and not playerSurface then
- for _, playerData in ipairs(bridge.getUsers()) do
- if playerData.name == username then
- playerSurface = bridge.getSurfaceByName(username)
- redirect.setSurface(playerSurface)
- redirect.setDrawn(true)
- break
- end
- end
- resume = false
- elseif event[1] == "glasses_detach" and event[3] == username and playerSurface then
- redirect.setDrawn(false)
- playerSurface = false
- resume = false
- elseif event[1] == "glasses_capture" and event[3] == username then
- local capture = bridge.getCaptureControl(event[4])
- capture.setKeyRepeat(true)
- capture.setBackground(0x000000)
- redirect.setVisible(true)
- resume = false
- elseif event[1] == "glasses_release" and event[3] == username then
- redirect.setVisible(false)
- resume = false
- end
- end
- end
- else
- printError(err)
- os.pullEvent("key")
- end
- if playerSurface then
- playerSurface.clear()
- bridge.sync()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement