Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local BufferMetatable = { __index = getfenv() }
- --[[
- Returns the given hex value in decimal. This is used for unserializing the colors.
- ]]
- local function hexToDecimal (hexString)
- return math.pow (2, tonumber (hexString, 16))
- end
- --[[
- Returns the given decimal number in a hex format. This is for serializing the colors.
- ]]
- local function decimalToHex (num)
- return string.format ("%x", math.log (num) / math.log (2))
- end
- --[[
- Copies the contents of the buffer (text, text colors, and background colors) and
- returns them along with the original buffer object.
- ]]
- function copyBuffer (self)
- local function copyTable (_table)
- local copy = {}
- for key, value in pairs (_table) do
- copy[key] = value
- end
- return copy
- end
- return {
- text = copyTable (self.text),
- textColors = copyTable (self.textColors),
- backColors = copyTable (self.backColors)
- },
- self
- end
- function getSize (self)
- return self.width, self.height, self
- end
- function clearLine (self)
- self.textColors[self.cursorY] = self.textColor:rep (self.width)
- self.backColors[self.cursorY] = self.backColor:rep (self.width)
- self.text[self.cursorY] = (" "):rep (self.width)
- return self
- end
- function init (self)
- for lineNumber = 1, self.height do
- self.cursorY = lineNumber
- self:clearLine()
- end
- self.cursorY = 1
- return self
- end
- clear = init
- function setCursorBlink (self, shouldCursorBlink)
- self.shouldCursorBlink = shouldCursorBlink
- return self
- end
- function isColor (self)
- return self.isColor, self
- end
- isColour = isColor
- function setCursorPos (self, x, y)
- -- We might NaN or something. Had it happen before. Scary stuff.
- self.cursorX = math.floor (x) or self.cursorX
- self.cursorY = math.floor (y) or self.cursorY
- return self
- end
- function getCursorPos (self)
- return self.cursorX, self.cursorY, self
- end
- function setTextColor (self, textColor)
- self.textColor = decimalToHex (textColor)
- return self
- end
- setTextColour = setTextColor
- function setBackgroundColor (self, backColor)
- self.backColor = decimalToHex (backColor)
- return self
- end
- setBackgroundColour = setBackgroundColor
- function scroll (self, numScrolls)
- for timesScrolled = 1, math.abs (numScrolls) do
- if numScrolls > 0 then
- for lineNumber = 1, self.height do
- self.text[lineNumber] = self.text[lineNumber + 1] or (" "):rep (self.width)
- self.textColors[lineNumber] = self.textColors[lineNumber + 1] or self.textColor:rep (self.width)
- self.backColors[lineNumber] = self.backColors[lineNumber + 1] or self.backColor:rep (self.width)
- end
- elseif numScrolls < 0 then
- for lineNumber = self.height, 1, -1 do
- self.text[lineNumber] = self.text[lineNumber - 1] or (" "):rep (self.width)
- self.textColors[lineNumber] = self.textColors[lineNumber - 1] or self.textColor:rep (self.width)
- self.backColors[lineNumber] = self.backColors[lineNumber - 1] or self.backColor:rep (self.width)
- end
- end
- end
- return self
- end
- function write (self, text)
- text = ((text == nil) and "" or text):gsub ("\t", " "):gsub ("%c", "?")
- -- Something wrong with truncation, probably. When starting off screen, we get the truncated part on the right of the screen.
- if self.cursorX < 1 then
- local oldCursorX = self.cursorX
- self.cursorX = (oldCursorX + text:len() > 1) and 1 or oldCursorX + text:len()
- text = text:sub (math.max (1, 2 - oldCursorX))
- end
- if self.cursorX + text:len() > self.width + 1 then
- text = text:sub (1, text:len() - (self.cursorX + text:len() - self.width))
- end
- if self.cursorY > 0 and self.cursorY <= self.height and self.cursorX < self.width + 1 and self.cursorX > 0 then
- self.text[self.cursorY] = self.text[self.cursorY]:sub (1, self.cursorX - 1) .. text .. self.text[self.cursorY]:sub (self.cursorX + text:len())
- self.textColors[self.cursorY] = self.textColors[self.cursorY]:sub (1, self.cursorX - 1) .. self.textColor:rep (text:len()) .. self.textColors[self.cursorY]:sub (self.cursorX + text:len())
- self.backColors[self.cursorY] = self.backColors[self.cursorY]:sub (1, self.cursorX - 1) .. self.backColor:rep (text:len()) .. self.backColors[self.cursorY]:sub (self.cursorX + text:len())
- end
- self.cursorX = self.cursorX + text:len()
- return self
- end
- --[[
- Renders the contents of the buffer at the given coordinates.
- ]]
- function render (self, x, y)
- local lastTextColor;
- local lastBackColor;
- local backColor;
- local textColor;
- local character;
- local charactersToWriteX = 1
- local charactersToWrite = ""
- local function renderLine (lineNumber, line)
- for posInLine = 1, self.width do
- character = line:sub (posInLine, posInLine)
- backColor = hexToDecimal (self.backColors[lineNumber]:sub (posInLine, posInLine))
- textColor = hexToDecimal (self.textColors[lineNumber]:sub (posInLine, posInLine))
- if backColor ~= lastBackColor or textColor ~= lastTextColor then
- if charactersToWriteX ~= nil then
- term.native.setCursorPos (x + charactersToWriteX - 1, y + lineNumber - 1)
- term.native.write (charactersToWrite)
- charactersToWrite = character
- end
- charactersToWriteX = posInLine
- if backColor ~= lastBackColor then
- term.native.setBackgroundColor (backColor)
- lastBackColor = backColor
- end
- if textColor ~= lastTextColor then
- term.native.setTextColor (textColor)
- lastTextColor = textColor
- end
- else
- charactersToWrite = charactersToWrite .. character
- end
- end
- term.native.setCursorPos (x + charactersToWriteX - 1, y + lineNumber - 1)
- term.native.write (charactersToWrite)
- charactersToWrite = ""
- charactersToWriteX = 1
- end
- for lineNumber, line in pairs (self.text) do
- -- Check if there any inconsistencies between the copy of the buffer and the main buffer.
- -- This prevents any unnecessary line updates.
- if self.copy.text[lineNumber] ~= self.text[lineNumber]
- or self.copy.textColors[lineNumber] ~= self.textColors[lineNumber]
- or self.copy.backColors[lineNumber] ~= self.backColors[lineNumber] then
- renderLine (lineNumber, line)
- end
- end
- -- Update the copy of the buffer with the current state of the buffer.
- self.copy = self:copyBuffer()
- term.native.setCursorPos (x + self.cursorX - 1, y + self.cursorY - 1)
- term.native.setCursorBlink (self.shouldCursorBlink)
- return self
- end
- function new (width, height, isColor)
- local self = {
- width = width,
- height = height,
- isColor = isColor,
- cursorX = 1,
- cursorY = 1,
- textColor = "0",
- backColor = "f",
- shouldCursorBlink = true,
- textColors = {},
- backColors = {},
- text = {},
- copy = nil
- }
- setmetatable (self, BufferMetatable)
- self:init()
- self.copy = self:copyBuffer()
- return self
- end
- function redirect (self)
- local redirectTable = {}
- for functionName, _ in pairs (term.native) do
- redirectTable[functionName] = function (...)
- return self[functionName] (self, ...)
- end
- end
- return redirectTable, self
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement