Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
local clrLk = {}
for n=1,16 do
clrLk[2^(n-1)] = string.sub( "0123456789abcdef",n,n )
end
local invLk = {}
for i=1,16 do
invLk[string.sub( "0123456789abcdef",i,i )] = 2^(i-1)
end
--CONFIG:
local lazy = false
--[[?:
lazy is weather or not write will precalculate string replacement. If you're blitting a lot, turn this off. If you're using mostly
active buffers, turn this on. This will:
Speed up writing
Slows down bliting(only happens when pulling up a previously off-screen application)
Eat up more memory(a decent bit--this will keep lazilly adding stuff to a table rather than calculating it.)
If you're bliting a lot, you probably want to set it to false
Default value: false
]]
--[[A NOTE ON EXESSIVE OP COUNT INCRECIMENT:
Due to the way Lua works, if you get a rediculously high number(like, if you left something running without ever de-foucusing and re-foucusing it for several months), this script WILL break.
That said, if you ever get a legitiment case of this happening, let me know.
]]
local function yield()
os.queueEvent"bufferYield"
os.pullEvent"bufferYield"
end
local function clearRealdisp(self)
for i=1,self.sizey do
game.l("wiope "..i+self.pY)
self.t.clearLine(i+self.pY)
end
end
--[[ idk wtf this is, but I'm afriad to delete it ._.
if ((b[y] or {})[x] or {}).bg then
term.setBackgroundColor(b[y][x].bg)
end
if ((b[y] or {})[x] or {}).tx then
term.setTextColor(b[y][x].tx)
end ]]
function newBuf(w,h,nativeT)
game.l"newBuf"
local a,b = term.getSize()
w,h = (w or a),(h or b)
local self = {}
local function clearLine(l)
error"DFGDFGSDFGDFSGF"
l= l or 1
local x,y = self.getCursorPos()
self.t.setBackgroundColor(self.bg)
for y=1,self.getSize() do
for i=1,self.sizex do
if not (self.nr[l+(self.pX-1)] or {})[(self.pX-1)+i] then
self.t.setCursorPos((self.pX-1)+i,l+(self.pY-1))
self.t.write" "
end
end
end
--term.setBackgroundColor(colors.black)
self.t.write(white)
self.t.setCursorPos(x,y)
end
local function refreshY(ry,Y,x,y)
local tx,ty = term.getSize()
if self[ry] then --px is the x position for next write to, Y is the part of the screen on the real terminal t write to, X is the part of the real screen to write to, rx & ry are the parts of the buffer,
local txt,tColor,bColor = "","",""
local px =1
for X=1+x,tx+x do
local rx = X-x
-- game.l("rx : "..rx.." ry "..ry.." X "..X.." Y "..Y)
if (self.nr[ry] or {})[rx] then
game.l"caught"
if txt~="" then --We need to blit stuff before the nozone, if there is anything there.
game.l"entr"
self.t.setCursorPos(px,Y)
self.t.blit(txt,tColor,bColor)
--sleep(1)
txt,tColor,bColor = "","",""
end
px=rx+1--The position for the next blit is now set to right after this nozone. This will keep getting set until the last nozone, so the rest of the text comes out right
else
if self[ry][rx] then
txt = txt..self[ry][rx].txt --Add this peice of text (ex. "x") to the line txt, same for text/background colors. In a y:x table
tColor = tColor..(clrLk[self[ry][rx].tc] or "0")
bColor = bColor..(clrLk[self[ry][rx].bg] or "f")
else
txt=txt.." "
tColor=tColor..clrLk[self.tc]
bColor=bColor..clrLk[self.bg]
end
end
end
self.t.setCursorPos(px,Y)
-- game.l("t "..tostring(txt).." co "..tostring(tColor).." bCo "..tostring(bColor))
self.t.blit(txt,tColor,bColor)
end
end
local function deepcopy(orig)--taken from http://lua-users.org/wiki/CopyTable
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key)] = deepcopy(orig_value)
end
setmetatable(copy, deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
function self.getSize()
return self.sizex,self.sizey
end
function self.resize(x,y)
game.l"resize"
if type(x)~="number" or type(y)~="number"then
return error"[buffer][resize] - Expected number, number"
end
self.sizex,self.sizey = x,y
self.bufferblit()
end
function self.setCursorPos(x,y)
if y < 1 or y > self.sizey then
y = -666
end
--game.l("set "..x.." y "..y)
if type(x)~="number" or type(y)~="number"then
return error"[buffer][setCursorPos] - Expected number, number"
end
x,y=math.floor(x),math.floor(y)
self.x,self.y=x,y
if self.isActive then
self.t.setCursorPos(x+(self.pX-1),y+(self.pY-1))
end
end
function self.getCursorPos()
return self.x,self.y
end
function self.setBackgroundColor(color)
self.bg = color
if self.isActive then
self.t.setBackgroundColor(color)
end
end
function self.setTextColor(color)
self.tc = color
if self.isActive then
self.t.setTextColor(color)
end
end
function self.getTextColor(color)
return self.tc
end
function self.getBackgroundColor(color)
return self.bg
end
function self.setCursorBlink(a)
self.cursorBlink = a
if self.isActive then
self.t.setCursorBlink(a)
end
end
function self.scroll(ammount)
game.l("scrl "..ammount)
ammount = ammount or 1
for i=1,table.maxn(self) do
self[i]=nil
self[i] = deepcopy(self[i+ammount]) or {}
end
self[0] = nil
self[#self] = nil
self[#self+1]={}
if self.isActive then
--clear the actual term:
--[[ for i=1,self.sizey+1 do
clearLine(i)
end]]
self.bufferblit(self.pX-1,self.pY-1)
self.setCursorPos(1,self.sizey)
end
end
function self.current()
return self
end
function self.makeActive(pX,pY)
game.l"mkAct"
self.isActive,self.pX,self.pY = true,pX or (self.pX or 1),pY or (self.pY or 1)
self.bufferblit(self.pX-1,self.pY-1)
self.t.setCursorPos(self.x+self.pX-1,self.y+self.pY-1)
self.t.setCursorBlink(self.cursorBlink)
end
function self.setActivePos(pX,pY)
self.pX,self.pY = pX or self.pX,pY or self.pY
end
function self.makeInactive()
self.isActive = false
if self.isActive then
os.shutdown()
end
end
self.setTextColour = self.setTextColor
self.setBackgroundColour = self.setBackgroundColor
self.getTextColour = self.getTextColor
self.getBackgroundColour = self.getBackgroundColor
function self.isColor(color)
return self.t.isColor(color)
end
--old writing method
--[[
if self.lazy then
self[self.y] = self[self.y] or {}
self[self.y][self.x] = self[self.y][self.x] or {}
self[self.y][self.x][self.opCount] = {}
--self[self.y][self.x][self.opCount].t = p
self[self.y][self.x][self.opCount].bg = self.bg
self[self.y][self.x][self.opCount].tc = self.tc
self[self.y][self.x][self.opCount].txt = txt
self.opCount = self.opCount+1
else
--self.t.write"l"-------------------------------------------------------------------
local oldTxt,oldbg,oldtc
if (self[self.y] or {})[self.x] then
oldTxt,oldbg,oldtc=self[self.y][self.x].txt,self[self.y][self.x].bg,self[self.y][self.x].tc
end
oldTxt = nil
--game.l"old"-------------------------------------------------------------------
--self.t.write(self)
self[self.y] = self[self.y] or {}
--game.l"1"--------------------------------------------------------------------------------------------------------------------------------------
self[self.y][self.x] = self[self.y][self.x] or {}
--self.t.write"2"---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
self[self.y][self.x].txt = txt
--self.t.write"3"----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
self[self.y][self.x].bg = self.bg
--game.l"4"-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
self[self.y][self.x].tc = self.tc
--game.l"str"------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local left = string.sub(oldTxt or "",#txt,#(oldTxt or ""))
--game.l"man"-------------------------------------------------------------------
if #left>1 then
--game.l"left"
--self.t.write(" "..self.y)-------------------------------------------------------------------
--self.t.write(" "..self.x+#txt)-------------------------------------------------------------------
--self.t.write(" "..left)-------------------------------------------------------------------
self[self.y] = self[self.y] or {}
self[self.y][self.x+#txt] = self[self.y][self.x+#txt] or {}
self[self.y][self.x+#txt].txt = left
--game.l"left1"
self[self.y][self.x+#txt].bg = oldbg
self[self.y][self.x+#txt].tc = oldtc
end
--clear anything in our path:
for i=self.x+1,self.x+#txt do
self[self.y][i] = nil
end
self.x = self.x+#txt--increase x count
end
--game.l"bye"-------------------------------------------------------------------
if self.isActive then
--game.l"a"-------------------------------------------------------------------
--self.t.setCursorPos(self.x+self.pX,self.y+self.pY) if the buffer is active, this is not necisary
--game.l"m"-------------------------------------------------------------------
--self.t.setBackgroundColor(((self[y] or {})[x] or {}).bg) -- The buffer is active, meaning it should already be set to its own colors
--self.t.setTextColor((self[y] or {})[x] or {}).tc)
self.t.write(txt)
end
--game.l"{"
for i=1,#self do
if self[i] then
game.l(textutils.serialize(self[i]))
end
end
game.l"}"]]-----------------------------------------
self.isColour = self.isColor
function self.newNozone(startx,endx,starty,endy)
for i=starty,endy do
self.nr[i] = self.nr[i] or {}
for o=startx,endx do
self.nr[i][o] = true
end
end
end
function self.destroyNozone(startx,endx,starty,endy) -- With aerosol cans
for i=starty,endy do
self.nr[i] = self.nr[i] or {}
for o=startx,endx do
self.nr[i][o] = nil
end
end
end
local function cAt(txt,num)
return string.sub(txt,num,num)
end
function self.write(txt)
--game.l("x "..tostring(self.x).." y "..tostring(self.y).." write : "..txt)
if type(txt)~="string" then
txt = tostring(txt)
end
self[self.y]=self[self.y] or {}
self.nr[self.y]=self.nr[self.y] or {}
-- We split these up into 2 loops, as it is more effecient to check once than many times during the loop
local x
if self.isActive and (not shoddyWrite) then
--game.l"activeWrite"--------------------------
--game.l( "at "..tostring((self.x+self.pX)-1) .. " y "..tostring((self.y+self.pY)-1) )
self.t.setBackgroundColor(self.bg)
self.t.setTextColor(self.tc)
x = self.x-1
for i=1,#txt do --Note: Doing this forwards & not checking if the cursor is at the edge does have a slight impact on compatibility if term.write is called through something other than write.
x=x+1
-- game.l("r - i "..i.." x "..x.." c "..cAt(txt,i).." ; y "..self.y)
self[self.y][x] = {}
self[self.y][x].txt = cAt(txt,i)
self[self.y][x].bg = self.bg
self[self.y][x].tc = self.tc
if (self.nr[self.y] or {})[x] then
game.l"blockd"
else
self.t.setCursorPos(((x+self.pX)-1),(self.y+self.pY)-1)
self.t.write(cAt(txt,i))
end
end
--Now, set the X cursor pos to the correct place
self.x = self.x+#txt
--game.l(self.x)
else
-- C&P'd from above
for i=1,#txt do
x=i+self.x-1
self[self.y][x] = {}
self[self.y][x].txt = cAt(txt,i)
self[self.y][x].bg = self.bg
self[self.y][x].tc = self.tc
end
--Now, set the X cursor pos to the correct place
self.x = self.x+#txt
if self.isActive and shoddyWrite then --Refresh the line if this buffer is active
refreshY(self.y,self.y+(self.pY-1),(self.pX-1),(self.pY-1))
end
end
end
function self.blit(txt,txtCol,backCol)
--game.l("blit "..txt)
local cx = self.x --The position to do next blit to
local btxt,btxtCol,bbackCol = "","",""
for i=1,#txt do
self[self.y] = self[self.y] or {}
self[self.y][self.x+i-1] = {}
self[self.y][self.x+i-1].bg = invLk[backCol:sub(i,i)]
self[self.y][self.x+i-1].tc = invLk[txtCol:sub(i,i)]
self[self.y][self.x+i-1].txt= txt:sub(i,i)
--game.l(textutils.serialize(self[self.y][self.x+i]))
if (self.nr[self.y] or {})[self.x+i-1] then
cx = self.x+i
if btxt~="" then
self.t.setCursorPos(cx+self.pY-1,self.y+(self.pY-1))
self.t.blit(btxt,btxtCol,bbackCol)
btxt,btxtCol,bbackCol = "","",""
end
else
btxt=btxt..txt:sub(i,i)
btxtCol = btxtCol..txtCol:sub(i,i)
bbackCol = bbackCol..backCol:sub(i,i)
end
end
self.t.setCursorPos(cx+self.pY-2,self.y+(self.pY-1))
self.t.blit(btxt,btxtCol,bbackCol)
end
function self.bufferblit(x,y) -- NOTE: Code normal buffer system firs
game.l"bblit"
--[[clear the screen
--for i=1,table.maxn(self) do
----------game.l("writy "..i+self.pY)-----------------------
self.t.clearLine(i+self.pY-1)
end]]
x,y=x or self.lastX, y or self.lastY
self.lastX,self.lastY = x,y
--x,y=x-1,y-1
-------game.l("blitx "..x.." y "..y)--------------------
if self.lazy then
--group operations by opnum
game.l"dsgfhjklsklghdsjklghsdjklghsdfjklgdhgjklsdhgfjkldhgjkldfhgsdfjkghsdfjkghdfsjklghsdjkigfhdgjkhg"
local ops = {}
local where = {}
for i=1,table.maxn(self) do
ops[i] = op[i] or {}
where[i]=where[i] or {}
if self[i] then
for o=1,table.maxn(self[i]) do
if #ops[i] == 1 then
ops[i][1] = self[i][o].opN
where[i][1] = o
else
for p=1,#ops[i] do
if ops[i][p] > self[i][o].opN then
table.insert(ops[i],p,self[i][o].opN)
table.insert(where[i],p,o)
end
end
end
end
end
end
for i=1,#ops do
for o=1,#ops[i] do
term.setBackgroundColor(self[i][where.o].bg)
term.setTextColor(self[i][where.o].tc)
self.t.write(self[i][where.o].txt)
end
end
else
--[[for i=1,table.maxn(self) do --redo, and go over the screen parts rendering to rather than entire buffer.
if self[i] then
--local yta = ""--------------------
for o=1,table.maxn(self[i]) do
--game.l("m Y "..i.." x "..o)-----------------------------------------------------
if self[i][o] and (not (self.nr[i] or {})[o]) then
self.t.setCursorPos(o+x,i+y)
self.t.setBackgroundColor(self[i][o].bg)
self.t.setTextColor(self[i][o].tc)
self.t.write(self[i][o].txt)
--yta=yta..self[i][o].txt ----------------------
--game.l("ye Y "..i.." x "..o)-----------------------------------------------------
end
end
--game.l(yta)-----------------------
end
end ]]
--Construct string for text, text colors, and background colors
local tx,ty = term.getSize()
for Y=1+y,ty+y do
local ry = Y-y
--[[if self[ry] then
local txt,tColor,bColor = "","",""
local px =1
for X=1+x,tx+x do
local rx = X-x
if (self.nr[ry] or {})[rx] then
if txt~="" then
game.l"entr"
self.t.setCursorPos(px,y)
self.t.blit(txt,tColor,bColor)
--sleep(1)
txt,tColor,bColor = "","",""
end
px=rx+1
else
if self[ry][rx] then
txt = txt..self[ry][rx].txt --Add this peice of text (ex. "x") to the line txt, same for text/background colors. In a y:x table
tColor = tColor..(clrLk[self[ry][rx].tc] or "0")
bColor = bColor..(clrLk[self[ry][rx].bg] or "f")
else
txt=txt.." "
tColor=tColor..clrLk[self.tc]
bColor=bColor..clrLk[self.bg]
end
end
end
self.t.setCursorPos(px,Y)
--game.l("t "..tostring(txt).." co "..tostring(tColor).." bCo "..tostring(bColor))
self.t.blit(txt,tColor,bColor)
end ]]
refreshY(ry,Y,x,y)
end
end
end
function self.clear()
local oldx,oldy = self.x,self.y
for i=1,self.sizey do --table.maxn(self) do
self.setCursorPos(1,i)
self.clearLine()
end
self.setCursorPos(oldx,oldy)
end
function self.clearLine()
local str = ""
for i=1,self.getSize() do
str=str.." "
end
local oldX = self.x
self.setCursorPos(1,self.y)
self.write(str)
self.setCursorPos(oldX,self.y)
end
local buffer=self
--buffer vars
self.opCount = 1
self.cursorBlink = true
--set bg colors
self.bg = colors.black
self.tc = colors.white
self.t = nativeT
self.y = 1
self.x = 1
self.pY = 0
self.pX = 1
self.lastX = 1
self.lastY= 1
self.lazy = lazy
self.isntNative = true
self.resize(w,h)
self.nr = {} -- Nozone, in a y:x table. To remove, use an aerosol can.
return self--,"Thank you, come again!"
end