Permalink
Cannot retrieve contributors at this time
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?
-os-/library/buffer
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
521 lines (505 sloc)
17.8 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |