Upload System Image
This commit is contained in:
parent
16da0a1837
commit
acf66baf57
221
LevelOS/Changelog.lua
Normal file
221
LevelOS/Changelog.lua
Normal file
@ -0,0 +1,221 @@
|
||||
if LevelOS and LevelOS.self and LevelOS.self.window then
|
||||
LevelOS.self.window.winMode = "widget"
|
||||
end
|
||||
local oldlog = lUtils.asset.load("LevelOS/data/nativelog.lconf") or {}
|
||||
local newlog = lUtils.asset.load("LevelOS/data/changelog.lconf")
|
||||
if newlog then
|
||||
fs.delete("LevelOS/data/nativelog.lconf")
|
||||
fs.move("LevelOS/data/changelog.lconf","LevelOS/data/nativelog.lconf")
|
||||
elseif oldlog then
|
||||
newlog = oldlog
|
||||
end
|
||||
local run = false
|
||||
for c=1,#newlog do
|
||||
if not oldlog[c] then
|
||||
newlog[c].new = true
|
||||
run = true
|
||||
end
|
||||
end
|
||||
local txt = term.setTextColor
|
||||
local bg = term.setBackgroundColor
|
||||
local function clr()
|
||||
local w,h = term.getSize()
|
||||
local x,y = term.getCursorPos()
|
||||
term.setCursorPos(19,y)
|
||||
term.write(string.rep(" ",w-21))
|
||||
term.setCursorPos(x,y)
|
||||
end
|
||||
local function wr(text,color,mX,mY) --max x and y
|
||||
if color then
|
||||
txt(color)
|
||||
end
|
||||
local x,y = term.getCursorPos()
|
||||
local cX = x
|
||||
local cY = y
|
||||
for word in text:gmatch("%S+") do
|
||||
--[[if cX ~= x then
|
||||
word = " "..word
|
||||
end]]
|
||||
if cX+#word <= mX then
|
||||
term.write(word.." ")
|
||||
cX = cX+#word+1
|
||||
elseif cY < mY then
|
||||
cX = x
|
||||
cY = cY+1
|
||||
term.setCursorPos(cX,cY)
|
||||
clr()
|
||||
term.write(word.." ")
|
||||
cX = cX+#word+1
|
||||
else
|
||||
return (cY-y)+1
|
||||
end
|
||||
end
|
||||
return (cY-y)+1
|
||||
end
|
||||
local function rm() -- reached max
|
||||
local x,y = term.getCursorPos()
|
||||
local w,h = term.getSize()
|
||||
if y >= h then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
function render(s)
|
||||
local function cp(x,y)
|
||||
term.setCursorPos(x,y+s)
|
||||
end
|
||||
bg(colors.cyan)
|
||||
term.clear()
|
||||
txt(colors.cyan)
|
||||
bg(colors.white)
|
||||
local w,h = term.getSize()
|
||||
for t=0,h-s do
|
||||
cp(14,4+t)
|
||||
term.write("\149")
|
||||
end
|
||||
-- write with window height as max Y and width-4 as max X
|
||||
local cY = 1
|
||||
for k=#newlog,1,-1 do
|
||||
local v = newlog[k]
|
||||
cY = cY+2
|
||||
|
||||
-- the date
|
||||
cp(2,cY+1)
|
||||
bg(colors.cyan)
|
||||
txt(colors.white)
|
||||
term.write(v.date)
|
||||
cp(13,cY)
|
||||
|
||||
-- cyan = 9, white = 0, lime=5
|
||||
-- the dot
|
||||
if k == #newlog then -- to check if its on top (for the line)
|
||||
term.blit("\159\143\143","999","000")
|
||||
else
|
||||
term.blit("\159\133\143","999","000")
|
||||
end
|
||||
cp(13,cY+1)
|
||||
if v.major then -- if major version make orange dot
|
||||
term.blit("\149 \149","911","010")
|
||||
else
|
||||
term.blit("\149 \149","955","050")
|
||||
end
|
||||
cp(13,cY+2)
|
||||
term.blit("\130\148\131","090","909")
|
||||
|
||||
-- the actual box
|
||||
bg(colors.white)
|
||||
txt(colors.cyan)
|
||||
cp(19,cY)
|
||||
clr()
|
||||
--term.write("\151\129")
|
||||
term.write("\129")
|
||||
cp(w-3,cY)
|
||||
term.write("\130")
|
||||
--term.blit("\148","0","9")
|
||||
--[[cY = cY+1
|
||||
cp(19,cY)
|
||||
clr()]]
|
||||
cY = cY+1
|
||||
cp(18,cY)
|
||||
clr()
|
||||
term.write("\145 ")
|
||||
term.write("v"..v.version)
|
||||
if v.new then
|
||||
txt(colors.orange)
|
||||
term.write(" New!")
|
||||
end
|
||||
cY = cY+1
|
||||
cp(19,cY)
|
||||
clr()
|
||||
cY = cY+1
|
||||
cp(20,cY)
|
||||
clr()
|
||||
if v.description then
|
||||
cY = cY-1
|
||||
cp(21,cY)
|
||||
bg(colors.white)
|
||||
txt(colors.black)
|
||||
cY = cY+wr(v.description,nil,w-4,h)
|
||||
cp(20,cY)
|
||||
clr()
|
||||
cY = cY+1
|
||||
cp(20,cY)
|
||||
clr()
|
||||
end
|
||||
if v.added and #v.added > 0 then
|
||||
bg(colors.lime)
|
||||
txt(colors.white)
|
||||
term.write(" NEW ")
|
||||
cY = cY+1
|
||||
bg(colors.white)
|
||||
cp(19,cY)
|
||||
clr()
|
||||
cY = cY+1
|
||||
txt(colors.black)
|
||||
for t=1,#v.added do
|
||||
cp(21,cY)
|
||||
clr()
|
||||
term.write("\7 ")
|
||||
cY = cY+wr(v.added[t],nil,w-4,h)
|
||||
end
|
||||
cp(20,cY)
|
||||
clr()
|
||||
end
|
||||
if v.fixed and #v.fixed > 0 then
|
||||
if v.added and #v.added > 0 then
|
||||
cY = cY+1
|
||||
cp(20,cY)
|
||||
clr()
|
||||
end
|
||||
bg(colors.lightBlue)
|
||||
txt(colors.white)
|
||||
term.write(" FIXED ")
|
||||
cY = cY+1
|
||||
bg(colors.white)
|
||||
cp(19,cY)
|
||||
clr()
|
||||
cY = cY+1
|
||||
txt(colors.black)
|
||||
for t=1,#v.fixed do
|
||||
cp(21,cY)
|
||||
clr()
|
||||
term.write("\7 ")
|
||||
cY = cY+wr(v.fixed[t],nil,w-4,h)
|
||||
end
|
||||
end
|
||||
bg(colors.white)
|
||||
txt(colors.cyan)
|
||||
cp(19,cY)
|
||||
clr()
|
||||
cY = cY+1
|
||||
cp(19,cY)
|
||||
clr()
|
||||
term.write("\144")
|
||||
cp(w-3,cY)
|
||||
term.blit("\159","0","9")
|
||||
if rm() then break end
|
||||
end
|
||||
term.setCursorPos(1,1)
|
||||
bg(colors.cyan)
|
||||
txt(colors.white)
|
||||
term.clearLine()
|
||||
term.setCursorPos(2,1)
|
||||
term.write("Changelog")
|
||||
term.setCursorPos(w-2,1)
|
||||
term.write("×")
|
||||
end
|
||||
render(0)
|
||||
local scroll = 0
|
||||
while true do
|
||||
local e = {os.pullEvent()}
|
||||
local w,h = term.getSize()
|
||||
if e[1] == "term_resize" then
|
||||
render(scroll)
|
||||
elseif e[1] == "mouse_scroll" and scroll-e[2] <= 0 then
|
||||
scroll = scroll-e[2]
|
||||
render(scroll)
|
||||
elseif e[1] == "mouse_up" and e[3] == w-2 and e[4] == 1 then
|
||||
return
|
||||
end
|
||||
end
|
||||
897
LevelOS/Clock.lua
Normal file
897
LevelOS/Clock.lua
Normal file
@ -0,0 +1,897 @@
|
||||
local assets = {
|
||||
[ "slider.lua" ] = {
|
||||
id = 1,
|
||||
content = "local s = shapescape.getSlide()\
|
||||
if not s.var then s.var = {} end\
|
||||
\
|
||||
local set = \"LevelOS/data/settings.lconf\"\
|
||||
\
|
||||
if lOS.settings.rTime == nil then\
|
||||
lOS.settings.rTime = false\
|
||||
end\
|
||||
\
|
||||
local r = string.rep\
|
||||
\
|
||||
local rtime = lOS.settings.rTime\
|
||||
\
|
||||
local w,h = term.getSize()\
|
||||
\
|
||||
if rtime then\
|
||||
term.setBackgroundColor(colors.green)\
|
||||
term.setCursorPos(1,1)\
|
||||
term.write(r(\" \",w-1))\
|
||||
term.setBackgroundColor(colors.white)\
|
||||
term.write(\" \")\
|
||||
else\
|
||||
term.setCursorPos(1,1)\
|
||||
term.setBackgroundColor(colors.white)\
|
||||
term.write(\" \")\
|
||||
term.setBackgroundColor(colors.red)\
|
||||
term.write(r(\" \",w-1))\
|
||||
end\
|
||||
\
|
||||
while true do\
|
||||
local w,h = term.getSize()\
|
||||
if lOS.settings.rTime ~= rtime then\
|
||||
rtime = lOS.settings.rTime\
|
||||
local b1,b2,fg\
|
||||
b1 = \"d\"\
|
||||
b2 = \"e\"\
|
||||
fg = \"0\"\
|
||||
local a,b,c\
|
||||
if rtime then\
|
||||
a,b,c = 1,w,1\
|
||||
else\
|
||||
a,b,c = w,1,-1\
|
||||
end\
|
||||
for x=a,b,c do\
|
||||
local d,e = x-1,w-x\
|
||||
term.setCursorPos(1,1)\
|
||||
term.blit(r(\" \",d)..\" \"..r(\" \",e),r(\"f\",w),r(b1,d)..fg..r(b2,e))\
|
||||
os.sleep(0.05)\
|
||||
end\
|
||||
end\
|
||||
e = {os.pullEvent()}\
|
||||
end",
|
||||
name = "slider.lua",
|
||||
},
|
||||
[ "switch_time.lua" ] = {
|
||||
id = 2,
|
||||
content = "lOS.settings.rTime = not lOS.settings.rTime",
|
||||
name = "switch_time.lua",
|
||||
},
|
||||
[ "rendercalender.lua" ] = {
|
||||
id = 7,
|
||||
content = "local w,h = term.getSize()\
|
||||
while h < 21 do\
|
||||
os.pullEvent()\
|
||||
w,h = term.getSize()\
|
||||
end\
|
||||
local epoch = os.epoch(\"local\")/1000\
|
||||
local date = os.date(\"*t\",epoch)\
|
||||
local targetmonth = date.month\
|
||||
local targetyear = date.year\
|
||||
local d = {}\
|
||||
d.sec = 1\
|
||||
d.min = d.sec*60\
|
||||
d.hour = d.min*60\
|
||||
d.day = d.hour*24\
|
||||
local function dayadd()\
|
||||
epoch = epoch+d.day\
|
||||
date = os.date(\"*t\",epoch)\
|
||||
end\
|
||||
local function daysub()\
|
||||
epoch = epoch-d.day\
|
||||
date = os.date(\"*t\",epoch)\
|
||||
end\
|
||||
while date.year < targetyear or date.month < targetmonth do\
|
||||
dayadd()\
|
||||
end\
|
||||
term.setBackgroundColor(colors.gray)\
|
||||
term.setTextColor(colors.white)\
|
||||
term.clear()\
|
||||
term.setCursorPos(1,1)\
|
||||
term.write(os.date(\"%B %Y\"))\
|
||||
term.setCursorPos(1,3)\
|
||||
days = {\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\",\"Su\"}\
|
||||
for t=1,7 do\
|
||||
term.write(\" \"..days[t]..\" \")\
|
||||
end\
|
||||
local x = term.getCursorPos()\
|
||||
term.setCursorPos(x-3,1)\
|
||||
--LevelOS.setWin(x-1,24)\
|
||||
term.write(\"\\30 \\31\")\
|
||||
while date.day > 1 do\
|
||||
daysub()\
|
||||
end\
|
||||
while date.wday ~= 2 do\
|
||||
daysub()\
|
||||
end\
|
||||
local current = os.date(\"*t\")\
|
||||
for w=1,6 do\
|
||||
--term.setCursorPos(1,5+(w-1)*3)\
|
||||
for t=1,7 do\
|
||||
local x,y = 1+(t-1)*4,5+(w-1)*3\
|
||||
local cur = false\
|
||||
if current.day == date.day and current.month == date.month and current.year == date.year then\
|
||||
term.setTextColor(colors.black)\
|
||||
term.setBackgroundColor(colors.lightGray)\
|
||||
lUtils.border(x,y-1,x+3,y+1)\
|
||||
cur = true\
|
||||
else\
|
||||
term.setBackgroundColor(colors.gray)\
|
||||
end\
|
||||
if targetmonth == date.month then\
|
||||
term.setTextColor(colors.white)\
|
||||
elseif cur then\
|
||||
term.setTextColor(colors.gray)\
|
||||
else\
|
||||
term.setTextColor(colors.lightGray)\
|
||||
end\
|
||||
term.setCursorPos(x+1,y)\
|
||||
term.write(os.date(\"%d\",epoch))\
|
||||
dayadd()\
|
||||
end\
|
||||
end\
|
||||
while true do os.pullEvent() end",
|
||||
name = "rendercalender.lua",
|
||||
},
|
||||
[ "offset.lua" ] = {
|
||||
id = 3,
|
||||
content = "if lOS.settings.timeOffset then\
|
||||
local o = lOS.settings.timeOffset\
|
||||
if o >= 0 then\
|
||||
self.txt = \"+\"..o\
|
||||
else\
|
||||
self.txt = tostring(o)\
|
||||
end\
|
||||
end",
|
||||
name = "offset.lua",
|
||||
},
|
||||
[ "offset_up.lua" ] = {
|
||||
id = 5,
|
||||
content = "lOS.settings.timeOffset = lOS.settings.timeOffset + 0.5",
|
||||
name = "offset_up.lua",
|
||||
},
|
||||
[ "time.lua" ] = {
|
||||
id = 0,
|
||||
content = "if not lOS.settings.timeOffset then\
|
||||
lOS.settings.timeOffset = 0\
|
||||
end\
|
||||
local t = os.date(\"*t\",os.epoch(\"utc\")/1000+lOS.settings.timeOffset*3600)\
|
||||
term.setBackgroundColor(colors.gray)\
|
||||
term.setTextColor(colors.white)\
|
||||
term.setCursorPos(self.x1,self.y1)\
|
||||
local function tz(n)\
|
||||
return string.rep(\"0\",2-string.len(n))..n\
|
||||
end\
|
||||
if lOS.settings.rTime then\
|
||||
bigfont.bigPrint(tz(t.hour)..\":\"..tz(t.min)..\":\"..tz(t.sec))\
|
||||
else\
|
||||
local nTime = (os.time()+lOS.settings.timeOffset)%24\
|
||||
local nHour = math.floor(nTime)\
|
||||
local nMinute = math.floor((nTime - nHour) * 60)\
|
||||
bigfont.bigPrint(tz(nHour)..\":\"..tz(nMinute))\
|
||||
end\
|
||||
term.setTextColor(colors.lightGray)\
|
||||
local days = {\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"}\
|
||||
local months = {\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"}\
|
||||
term.setCursorPos(self.x1,({term.getCursorPos()})[2])\
|
||||
print(days[t.wday]..\", \"..months[t.month]..\" \"..t.day..\", \"..t.year)",
|
||||
name = "time.lua",
|
||||
},
|
||||
[ "init.lua" ] = {
|
||||
id = 4,
|
||||
content = "local w,h = 27,13\
|
||||
local tw,th = lOS.wAll.getSize()\
|
||||
if th >= 40 then\
|
||||
w,h = 32,36\
|
||||
end\
|
||||
LevelOS.setWin(w,h,\"widget\")\
|
||||
LevelOS.self.window.win.reposition(tw-w,th-(h-1+lOS.tbSize))",
|
||||
name = "init.lua",
|
||||
},
|
||||
[ "offset_down.lua" ] = {
|
||||
id = 6,
|
||||
content = "lOS.settings.timeOffset = lOS.settings.timeOffset - 0.5",
|
||||
name = "offset_down.lua",
|
||||
},
|
||||
}
|
||||
|
||||
local nAssets = {}
|
||||
for key,value in pairs(assets) do nAssets[key] = value nAssets[assets[key].id] = assets[key] end
|
||||
assets = nAssets
|
||||
nAssets = nil
|
||||
|
||||
local slides = {
|
||||
{
|
||||
y = 21,
|
||||
x = 61,
|
||||
h = 19,
|
||||
w = 51,
|
||||
objs = {
|
||||
{
|
||||
x2 = 51,
|
||||
y2 = 19,
|
||||
y1 = 1,
|
||||
x1 = 1,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = 4,
|
||||
},
|
||||
},
|
||||
ox2 = 0,
|
||||
color = 128,
|
||||
border = {
|
||||
color = 256,
|
||||
type = 1,
|
||||
},
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap right",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap bottom",
|
||||
},
|
||||
oy2 = 0,
|
||||
},
|
||||
{
|
||||
x2 = 26,
|
||||
y2 = 4,
|
||||
border = {
|
||||
color = 128,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 3,
|
||||
txt = "",
|
||||
type = "text",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = 0,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 1,
|
||||
color = 128,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap left",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
y1 = 2,
|
||||
},
|
||||
{
|
||||
x2 = 50,
|
||||
y2 = 8,
|
||||
y1 = 7,
|
||||
x1 = 2,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
ox2 = 1,
|
||||
color = 128,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap right",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
border = {
|
||||
color = 256,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
x2 = 50,
|
||||
y2 = 8,
|
||||
y1 = 8,
|
||||
x1 = 2,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
ox2 = 1,
|
||||
color = 128,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap right",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "rect",
|
||||
color = 128,
|
||||
y2 = 7,
|
||||
y1 = 7,
|
||||
x1 = 2,
|
||||
x2 = 2,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap left",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
x2 = 50,
|
||||
y2 = 7,
|
||||
y1 = 7,
|
||||
x1 = 50,
|
||||
ox1 = 1,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
ox2 = 1,
|
||||
color = 128,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap right",
|
||||
Left = "Snap right",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 128,
|
||||
y2 = 8,
|
||||
y1 = 8,
|
||||
x1 = 11,
|
||||
txt = "Use real time",
|
||||
type = "text",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 1,
|
||||
input = false,
|
||||
x2 = 23,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 1,
|
||||
y2 = 12,
|
||||
y1 = 10,
|
||||
x1 = 3,
|
||||
txt = "+0",
|
||||
type = "text",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = 3,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 32768,
|
||||
input = false,
|
||||
x2 = 9,
|
||||
border = {
|
||||
color = 256,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
x2 = 9,
|
||||
y2 = 10,
|
||||
y1 = 10,
|
||||
x1 = 3,
|
||||
txt = " ",
|
||||
type = "text",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = 5,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 1,
|
||||
input = false,
|
||||
color = 256,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap left",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 256,
|
||||
y2 = 12,
|
||||
y1 = 12,
|
||||
x1 = 3,
|
||||
txt = " ",
|
||||
type = "text",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = 6,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 1,
|
||||
input = false,
|
||||
x2 = 9,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 128,
|
||||
y2 = 11,
|
||||
y1 = 11,
|
||||
x1 = 11,
|
||||
txt = "Offset (hours)",
|
||||
type = "text",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 1,
|
||||
input = false,
|
||||
x2 = 26,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "window",
|
||||
color = 32768,
|
||||
y2 = 8,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 3,
|
||||
y1 = 8,
|
||||
x2 = 9,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap left",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = 2,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 128,
|
||||
y2 = 15,
|
||||
border = {
|
||||
color = 256,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 2,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
ox2 = 1,
|
||||
x2 = 50,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap right",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
y1 = 14,
|
||||
},
|
||||
{
|
||||
type = "rect",
|
||||
x2 = 2,
|
||||
y2 = 14,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 2,
|
||||
color = 128,
|
||||
y1 = 14,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap left",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 128,
|
||||
y2 = 14,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 50,
|
||||
ox1 = 1,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
ox2 = 1,
|
||||
x2 = 50,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap right",
|
||||
Left = "Snap right",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
y1 = 14,
|
||||
},
|
||||
{
|
||||
color = 128,
|
||||
y2 = 15,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 2,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Initialize = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
selected = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
ox2 = 1,
|
||||
x2 = 50,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap right",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap top",
|
||||
},
|
||||
y1 = 15,
|
||||
},
|
||||
{
|
||||
x2 = 49,
|
||||
y2 = 18,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 3,
|
||||
type = "window",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = 7,
|
||||
},
|
||||
},
|
||||
ox2 = 2,
|
||||
color = 32768,
|
||||
y1 = 15,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap right",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap bottom",
|
||||
},
|
||||
oy2 = 1,
|
||||
},
|
||||
},
|
||||
c = 1,
|
||||
},
|
||||
{
|
||||
y = 21,
|
||||
x = 61,
|
||||
h = 19,
|
||||
w = 51,
|
||||
objs = {},
|
||||
c = 2,
|
||||
},
|
||||
}
|
||||
|
||||
for s=1,#slides do
|
||||
local slide = slides[s]
|
||||
for o=1,#slide.objs do
|
||||
local obj = slide.objs[o]
|
||||
for key,value in pairs(obj.event) do
|
||||
if assets[ value[2] ] then
|
||||
lUtils.shapescape.addScript(obj,value[2],key,assets,LevelOS,slides)
|
||||
else
|
||||
obj.event[key] = {function() end,-1}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local tArgs = {...}
|
||||
if tArgs[1] and tArgs[1] == "load" then
|
||||
return {assets=assets,slides=slides}
|
||||
end
|
||||
|
||||
|
||||
lUtils.shapescape.run(slides,...)
|
||||
2063
LevelOS/Global_Login.lua
Normal file
2063
LevelOS/Global_Login.lua
Normal file
File diff suppressed because it is too large
Load Diff
1734
LevelOS/Login_screen.sgui
Normal file
1734
LevelOS/Login_screen.sgui
Normal file
File diff suppressed because it is too large
Load Diff
124
LevelOS/Notification.lua
Normal file
124
LevelOS/Notification.lua
Normal file
@ -0,0 +1,124 @@
|
||||
local tArgs = {...}
|
||||
if not tArgs then return end
|
||||
local sID = #lOS.notifWins+1
|
||||
lOS.notifWins[sID] = LevelOS.self.window
|
||||
local function count(tbl)
|
||||
local c = 0
|
||||
for k,v in pairs(tbl) do
|
||||
c = c+1
|
||||
end
|
||||
return c
|
||||
end
|
||||
local nAmount = count(lOS.notifWins)
|
||||
term.setBackgroundColor(colors.gray)
|
||||
term.clear()
|
||||
local x,y = 2,2
|
||||
local icon
|
||||
if type(tArgs[3]) == "string" and fs.exists(tArgs[3]) and lOS.getIcon then
|
||||
icon = lOS.getIcon(tArgs[3])
|
||||
end
|
||||
if icon then
|
||||
lUtils.renderImg(icon,x,y)
|
||||
x = x+4
|
||||
end
|
||||
if type(tArgs[1]) == "string" then
|
||||
term.setCursorPos(x,y)
|
||||
term.setTextColor(colors.white)
|
||||
local w,h = term.getSize()
|
||||
local nw = w-x
|
||||
local txt = lUtils.wordwrap(tArgs[1],nw-1)
|
||||
if y+#txt > h then
|
||||
local dif = y+#txt-h
|
||||
local wX,wY = LevelOS.self.window.win.getPosition()
|
||||
wY = wY-dif
|
||||
h = h+dif
|
||||
LevelOS.self.window.win.reposition(wX,wY,w,h)
|
||||
end
|
||||
for t=1,#txt do
|
||||
term.setCursorPos(x,y)
|
||||
term.write(txt[t])
|
||||
y = y+1
|
||||
end
|
||||
end
|
||||
if type(tArgs[2]) == "string" then
|
||||
term.setCursorPos(x,y)
|
||||
term.setTextColor(colors.lightGray)
|
||||
local w,h = term.getSize()
|
||||
local nw = w-x
|
||||
local txt = lUtils.wordwrap(tArgs[2],nw)
|
||||
if y+#txt > h then
|
||||
local dif = y+#txt-h
|
||||
local wX,wY = LevelOS.self.window.win.getPosition()
|
||||
wY = wY-dif
|
||||
h = h+dif
|
||||
LevelOS.self.window.win.reposition(wX,wY,w,h)
|
||||
end
|
||||
for t=1,#txt do
|
||||
term.setCursorPos(x,y)
|
||||
term.write(txt[t])
|
||||
y = y+1
|
||||
end
|
||||
end
|
||||
local w,h = term.getSize()
|
||||
term.setCursorPos(w-1,2)
|
||||
term.setTextColor(colors.lightGray)
|
||||
term.write("×")
|
||||
local timer = 3
|
||||
if type(tArgs[4]) == "string" and tonumber(tArgs[4]) then
|
||||
timer = tonumber(tArgs[4])
|
||||
end
|
||||
local tID = os.startTimer(timer)
|
||||
local tID2
|
||||
local sel = false
|
||||
while true do
|
||||
local e = {os.pullEvent()}
|
||||
if e[1] == "timer" and e[2] == tID then
|
||||
break
|
||||
elseif e[1]:find("mouse") and e[3] and e[4] then
|
||||
if e[3] == w-1 and e[4] == 2 then
|
||||
if e[1] == "mouse_hover" then
|
||||
term.setCursorPos(w-1,2)
|
||||
term.setTextColor(colors.white)
|
||||
term.write("×")
|
||||
sel = true
|
||||
elseif e[1] == "mouse_click" then
|
||||
term.setCursorPos(w-1,2)
|
||||
term.setTextColor(colors.red)
|
||||
term.write("×")
|
||||
sel = true
|
||||
elseif e[1] == "mouse_up" and sel then
|
||||
break
|
||||
end
|
||||
end
|
||||
if e[1] == "mouse_up" and sel then
|
||||
term.setCursorPos(w-1,2)
|
||||
term.setTextColor(colors.lightGray)
|
||||
term.write("×")
|
||||
sel = false
|
||||
end
|
||||
end
|
||||
--if count(lOS.notifWins) ~= nAmount then
|
||||
nAmount = count(lOS.notifWins)
|
||||
local tW,tH = lOS.wAll.getSize()
|
||||
local w,h = term.getSize()
|
||||
local newY = tH-h-lOS.tbSize
|
||||
local x,y = LevelOS.self.window.win.getPosition()
|
||||
for k,v in pairs(lOS.notifWins) do
|
||||
--if v ~= LevelOS.self.window then
|
||||
local tx,ty = v.win.getPosition()
|
||||
if ty-h-1 <= newY and ty > y then -- use actual height
|
||||
newY = ty-h-1
|
||||
end
|
||||
--end
|
||||
end
|
||||
if newY > y then
|
||||
if not tID2 then
|
||||
tID2 = os.startTimer(0.3)
|
||||
elseif tID2 and e[1] == "timer" and e[2] == tID2 then
|
||||
LevelOS.self.window.win.reposition(x,newY)
|
||||
tID2 = nil
|
||||
end
|
||||
end
|
||||
--end
|
||||
end
|
||||
lOS.notifWins[sID] = nil
|
||||
725
LevelOS/Notifications.lua
Normal file
725
LevelOS/Notifications.lua
Normal file
@ -0,0 +1,725 @@
|
||||
local assets = {}
|
||||
|
||||
local nAssets = {}
|
||||
for key,value in pairs(assets) do nAssets[key] = value nAssets[assets[key].id] = assets[key] end
|
||||
assets = nAssets
|
||||
nAssets = nil
|
||||
|
||||
local slides = {
|
||||
{
|
||||
y = 21,
|
||||
x = 70,
|
||||
w = 32,
|
||||
h = 19,
|
||||
objs = {
|
||||
{
|
||||
type = "rect",
|
||||
color = 32768,
|
||||
y2 = 19,
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
x1 = 1,
|
||||
x2 = 32,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
y1 = 1,
|
||||
},
|
||||
{
|
||||
type = "rect",
|
||||
color = 128,
|
||||
y2 = 6,
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
x1 = 2,
|
||||
y1 = 2,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x2 = 31,
|
||||
},
|
||||
{
|
||||
x2 = 19,
|
||||
y2 = 3,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 8,
|
||||
txt = "Notification",
|
||||
type = "text",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 1,
|
||||
input = false,
|
||||
color = 0,
|
||||
y1 = 3,
|
||||
},
|
||||
{
|
||||
type = "rect",
|
||||
color = 16384,
|
||||
y2 = 5,
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
x1 = 4,
|
||||
y1 = 3,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x2 = 6,
|
||||
},
|
||||
{
|
||||
x2 = 30,
|
||||
y2 = 5,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 8,
|
||||
txt = "This is a notification to tell you things yes.",
|
||||
type = "text",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 256,
|
||||
input = false,
|
||||
color = 0,
|
||||
y1 = 4,
|
||||
},
|
||||
{
|
||||
x2 = 30,
|
||||
y2 = 3,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 30,
|
||||
txt = "×",
|
||||
type = "text",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 256,
|
||||
input = false,
|
||||
color = 0,
|
||||
y1 = 3,
|
||||
},
|
||||
},
|
||||
c = 1,
|
||||
},
|
||||
{
|
||||
y = 21,
|
||||
x = 70,
|
||||
c = 2,
|
||||
objs = {
|
||||
{
|
||||
type = "rect",
|
||||
color = 128,
|
||||
y2 = 6,
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
x1 = 2,
|
||||
x2 = 31,
|
||||
y1 = 2,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "rect",
|
||||
color = 16384,
|
||||
y2 = 5,
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
x1 = 3,
|
||||
x2 = 5,
|
||||
y1 = 3,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 0,
|
||||
y2 = 3,
|
||||
y1 = 3,
|
||||
x1 = 7,
|
||||
txt = "Notification",
|
||||
type = "text",
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 1,
|
||||
input = false,
|
||||
x2 = 18,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 0,
|
||||
y2 = 5,
|
||||
y1 = 4,
|
||||
x1 = 7,
|
||||
txt = "This is a notification to tell you things yes.",
|
||||
type = "text",
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 256,
|
||||
input = false,
|
||||
x2 = 30,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 0,
|
||||
y2 = 3,
|
||||
y1 = 3,
|
||||
x1 = 30,
|
||||
txt = "×",
|
||||
type = "text",
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 256,
|
||||
input = false,
|
||||
x2 = 30,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "rect",
|
||||
color = 128,
|
||||
y2 = 12,
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
x1 = 2,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x2 = 31,
|
||||
y1 = 8,
|
||||
},
|
||||
{
|
||||
color = 0,
|
||||
y2 = 9,
|
||||
y1 = 9,
|
||||
x1 = 3,
|
||||
txt = "Notification",
|
||||
type = "text",
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 1,
|
||||
input = false,
|
||||
x2 = 14,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
x2 = 30,
|
||||
y2 = 11,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 3,
|
||||
txt = "This notification has no icon available.",
|
||||
type = "text",
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 256,
|
||||
input = false,
|
||||
color = 0,
|
||||
y1 = 10,
|
||||
},
|
||||
{
|
||||
x2 = 30,
|
||||
y2 = 9,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 30,
|
||||
txt = "×",
|
||||
type = "text",
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 256,
|
||||
input = false,
|
||||
color = 0,
|
||||
y1 = 9,
|
||||
},
|
||||
{
|
||||
type = "rect",
|
||||
color = 128,
|
||||
y2 = 19,
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
x1 = 2,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
y1 = 14,
|
||||
x2 = 31,
|
||||
},
|
||||
{
|
||||
type = "rect",
|
||||
color = 16384,
|
||||
y2 = 17,
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
x1 = 3,
|
||||
x2 = 5,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
y1 = 15,
|
||||
},
|
||||
{
|
||||
color = 0,
|
||||
y2 = 15,
|
||||
y1 = 15,
|
||||
x1 = 7,
|
||||
txt = "Notification",
|
||||
type = "text",
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 1,
|
||||
input = false,
|
||||
x2 = 18,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 0,
|
||||
y2 = 18,
|
||||
y1 = 16,
|
||||
x1 = 7,
|
||||
txt = "This notification does not have enough space so it expands downwards.",
|
||||
type = "text",
|
||||
event = {
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 256,
|
||||
input = false,
|
||||
x2 = 30,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
x2 = 30,
|
||||
y2 = 15,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 30,
|
||||
txt = "×",
|
||||
type = "text",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
txtcolor = 256,
|
||||
input = false,
|
||||
color = 0,
|
||||
y1 = 15,
|
||||
},
|
||||
},
|
||||
w = 32,
|
||||
h = 19,
|
||||
},
|
||||
}
|
||||
|
||||
for s=1,#slides do
|
||||
local slide = slides[s]
|
||||
for o=1,#slide.objs do
|
||||
local obj = slide.objs[o]
|
||||
for key,value in pairs(obj.event) do
|
||||
if assets[ value[2] ] then
|
||||
lUtils.shapescape.addScript(obj,value[2],key,assets,LevelOS,slides)
|
||||
else
|
||||
obj.event[key] = {function() end,-1}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local tArgs = {...}
|
||||
if tArgs[1] and tArgs[1] == "load" then
|
||||
return {assets=assets,slides=slides}
|
||||
end
|
||||
|
||||
|
||||
lUtils.shapescape.run(slides,...)
|
||||
327
LevelOS/Start_Menu.sgui
Normal file
327
LevelOS/Start_Menu.sgui
Normal file
@ -0,0 +1,327 @@
|
||||
local assets = {
|
||||
[ "programs.lua" ] = {
|
||||
id = 0,
|
||||
content = "local scrollY = 0\
|
||||
local programs = {}\
|
||||
local found = fs.list(\"Program_Files\")\
|
||||
local icons = lUtils.asset.load(\"LevelOS/assets/Compact_Icons.limg\")\
|
||||
local A = string.byte(\"A\")\
|
||||
local Z = string.byte(\"Z\")\
|
||||
for f=1,#found do\
|
||||
local l = string.byte(found[f]:sub(1,1):upper())\
|
||||
local dest\
|
||||
if l >= A and l <= Z then\
|
||||
if not programs[l] then programs[l] = {} end\
|
||||
dest = programs[l]\
|
||||
else\
|
||||
if not programs[A-1] then programs[A-1] = {} end\
|
||||
dest = programs[A-1]\
|
||||
end\
|
||||
local program = {path=fs.combine(\"Program_Files\",found[f]),name=found[f]:sub(1,1):upper()..lUtils.getFileName(found[f]:sub(2))}\
|
||||
--program.icon = whatever\
|
||||
table.insert(dest,program)\
|
||||
end\
|
||||
local function render()\
|
||||
local y = 2\
|
||||
term.setBackgroundColor(colors.gray)\
|
||||
term.setTextColor(colors.white)\
|
||||
term.clear()\
|
||||
for l=A-1,Z do\
|
||||
if programs[l] then\
|
||||
local letter\
|
||||
if l == A-1 then\
|
||||
letter = \"#\"\
|
||||
else\
|
||||
letter = string.char(l)\
|
||||
end\
|
||||
term.setCursorPos(1,y)\
|
||||
term.write(letter)\
|
||||
y = y+2\
|
||||
for t=1,#programs[l] do\
|
||||
lUtils.renderImg(icons[8],1,y)\
|
||||
term.setCursorPos(5,y)\
|
||||
term.setTextColor(colors.white)\
|
||||
term.write(programs[l][t].name)\
|
||||
y = y+1\
|
||||
term.setTextColor(colors.lightGray)\
|
||||
term.write( -- creator\
|
||||
end\
|
||||
end\
|
||||
end",
|
||||
name = "programs.lua",
|
||||
},
|
||||
}
|
||||
|
||||
local nAssets = {}
|
||||
for key,value in pairs(assets) do nAssets[key] = value nAssets[assets[key].id] = assets[key] end
|
||||
assets = nAssets
|
||||
nAssets = nil
|
||||
|
||||
local slides = {
|
||||
{
|
||||
y = 21,
|
||||
x = 61,
|
||||
w = 51,
|
||||
h = 19,
|
||||
objs = {
|
||||
{
|
||||
color = 128,
|
||||
y2 = 19,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 1,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
x2 = 5,
|
||||
y1 = 1,
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap left",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap bottom",
|
||||
},
|
||||
oy2 = 0,
|
||||
},
|
||||
{
|
||||
color = 128,
|
||||
y2 = 18,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 2,
|
||||
image = {
|
||||
{
|
||||
"",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
{
|
||||
"
",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
oy1 = 2,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
oy2 = 1,
|
||||
x2 = 4,
|
||||
y1 = 17,
|
||||
snap = {
|
||||
Top = "Snap bottom",
|
||||
Right = "Snap left",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap bottom",
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 128,
|
||||
y2 = 15,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 2,
|
||||
image = {
|
||||
{
|
||||
"",
|
||||
"TT0",
|
||||
"00T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"00T",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
oy1 = 5,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
oy2 = 4,
|
||||
x2 = 4,
|
||||
y1 = 14,
|
||||
snap = {
|
||||
Top = "Snap bottom",
|
||||
Right = "Snap left",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap bottom",
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 128,
|
||||
y2 = 12,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
x1 = 2,
|
||||
image = {
|
||||
{
|
||||
"",
|
||||
"TT0",
|
||||
"00T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"00T",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
oy1 = 8,
|
||||
type = "rect",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
oy2 = 7,
|
||||
x2 = 4,
|
||||
y1 = 11,
|
||||
snap = {
|
||||
Top = "Snap bottom",
|
||||
Right = "Snap left",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap bottom",
|
||||
},
|
||||
},
|
||||
{
|
||||
color = 128,
|
||||
y2 = 19,
|
||||
y1 = 1,
|
||||
x1 = 6,
|
||||
type = "window",
|
||||
event = {
|
||||
mouse_up = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
mouse_click = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
focus = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
render = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
update = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
Coroutine = {
|
||||
[ 2 ] = -1,
|
||||
},
|
||||
},
|
||||
ox2 = 0,
|
||||
x2 = 51,
|
||||
border = {
|
||||
color = 0,
|
||||
type = 1,
|
||||
},
|
||||
snap = {
|
||||
Top = "Snap top",
|
||||
Right = "Snap right",
|
||||
Left = "Snap left",
|
||||
Bottom = "Snap bottom",
|
||||
},
|
||||
oy2 = 0,
|
||||
},
|
||||
},
|
||||
c = 1,
|
||||
},
|
||||
}
|
||||
|
||||
for s=1,#slides do
|
||||
local slide = slides[s]
|
||||
for o=1,#slide.objs do
|
||||
local obj = slide.objs[o]
|
||||
for key,value in pairs(obj.event) do
|
||||
if assets[ value[2] ] then
|
||||
lUtils.shapescape.addScript(obj,value[2],key,assets,LevelOS,slides)
|
||||
else
|
||||
obj.event[key] = {function() end,-1}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local tArgs = {...}
|
||||
if tArgs[1] and tArgs[1] == "load" then
|
||||
return {assets=assets,slides=slides}
|
||||
end
|
||||
|
||||
|
||||
lUtils.shapescape.run(slides,...)
|
||||
1970
LevelOS/SystemUI.lua
Normal file
1970
LevelOS/SystemUI.lua
Normal file
File diff suppressed because it is too large
Load Diff
451
LevelOS/Task_Manager.lua
Normal file
451
LevelOS/Task_Manager.lua
Normal file
@ -0,0 +1,451 @@
|
||||
local scroll = 0
|
||||
local procs = lOS.processes
|
||||
local sel = {}
|
||||
local pSel = {}
|
||||
local expanded = {}
|
||||
local cEnd = false
|
||||
local scrollable = false
|
||||
local display = 1
|
||||
local function percentage(part,full)
|
||||
if display == 1 then
|
||||
local f = math.min(math.ceil((part/full)*1000)/10,100)
|
||||
return f.."%"
|
||||
else
|
||||
return math.floor(part+0.5).." ms"
|
||||
end
|
||||
end
|
||||
function _G.invWrite(txt)
|
||||
local fg = lUtils.toBlit(term.getTextColor()):rep(#txt)
|
||||
local bg = lUtils.toBlit(term.getBackgroundColor()):rep(#txt)
|
||||
term.blit(txt,bg,fg)
|
||||
end
|
||||
|
||||
local function drawProcs(x1,y1,x2,y2,e)
|
||||
if e[1] == "mouse_scroll" then
|
||||
if scroll+e[2] >= 0 and (e[2] <= -1 or scrollable) then
|
||||
scroll = scroll+e[2]
|
||||
end
|
||||
end
|
||||
term.setBackgroundColor(colors.yellow)
|
||||
term.setTextColor(colors.lightGray)
|
||||
--lOS.boxClear(x2-9,y1,x2,y2-2)
|
||||
for y=y1,y2-2 do
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setCursorPos(x2-10,y)
|
||||
invWrite("\149")
|
||||
term.setBackgroundColor(colors.yellow)
|
||||
term.write(string.rep(" ",10))
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.write("\149")
|
||||
end
|
||||
scrollable = false
|
||||
cY = y1-scroll
|
||||
local pr = {}
|
||||
local bg = {}
|
||||
|
||||
y2 = y2-2
|
||||
|
||||
for p=1,#procs do
|
||||
if procs[p].path then
|
||||
if procs[p].win and procs[p].winMode ~= "background" then
|
||||
if not pr[procs[p].path] then
|
||||
if expanded[procs[p].path] == nil then
|
||||
expanded[procs[p].path] = false
|
||||
end
|
||||
pr[#pr+1] = {expanded=expanded[procs[p].path],path=procs[p].path,pr={procs[p]},yieldTime=procs[p].yieldTime}
|
||||
pr[procs[p].path] = pr[#pr]
|
||||
else
|
||||
for t=1,#pr do
|
||||
if pr[t].path == procs[p].path then
|
||||
pr[t].pr[#pr[t].pr+1] = procs[p]
|
||||
if procs[p].yieldTime then
|
||||
pr[t].yieldTime = pr[t].yieldTime+procs[p].yieldTime
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
bg[#bg+1] = procs[p]
|
||||
end
|
||||
end
|
||||
end
|
||||
local clickmenu = {}
|
||||
-- TEMP
|
||||
|
||||
if type(pSel) == "table" then
|
||||
sel = pSel
|
||||
elseif type(pSel) == "number" then
|
||||
sel = pr[pSel]
|
||||
else
|
||||
sel = {}
|
||||
end
|
||||
--if pr[2] then
|
||||
--pr[2].expanded = true
|
||||
--end
|
||||
if cY+1 >= y1 and cY+1 <= y2 then
|
||||
term.setTextColor(colors.blue)
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setCursorPos(x1,cY+1)
|
||||
term.write("Programs ("..#pr..")")
|
||||
end
|
||||
cY = cY+2
|
||||
local previousColor1
|
||||
local previousColor2
|
||||
for p=1,#pr+1 do
|
||||
local fg1
|
||||
local bg1
|
||||
local fg2
|
||||
local bg2
|
||||
|
||||
local WARN = colors.yellow
|
||||
if p <= #pr and pr[p].yieldTime then
|
||||
local f = pr[p].yieldTime/lOS.yieldTime
|
||||
if f > 0.7 then
|
||||
WARN = colors.red
|
||||
elseif f > 0.4 then
|
||||
WARN = colors.orange
|
||||
end
|
||||
end
|
||||
fg1 = previousColor1 or colors.white
|
||||
fg2 = previousColor2 or colors.yellow
|
||||
if p > #pr or sel ~= pr[p] then
|
||||
bg1 = colors.white
|
||||
bg2 = WARN
|
||||
else
|
||||
bg1 = colors.lightBlue
|
||||
bg2 = colors.cyan
|
||||
end
|
||||
previousColor1 = bg1
|
||||
previousColor2 = bg2
|
||||
if cY >= y1 and cY <= y2 then
|
||||
term.setTextColor(fg1)
|
||||
term.setBackgroundColor(bg1)
|
||||
term.setCursorPos(x1,cY)
|
||||
term.write(string.rep("\131",x2-(x1-1)-11))
|
||||
|
||||
term.setTextColor(colors.lightGray)
|
||||
term.setBackgroundColor(colors.white)
|
||||
invWrite("\149")
|
||||
term.setBackgroundColor(bg1)
|
||||
term.setTextColor(fg2)
|
||||
term.setBackgroundColor(bg2)
|
||||
term.write(string.rep("\131",10))
|
||||
end
|
||||
term.setTextColor(fg1)
|
||||
term.setBackgroundColor(bg1)
|
||||
if p > #pr then
|
||||
break
|
||||
end
|
||||
cY = cY+1
|
||||
if cY >= y1 and cY <= y2 then
|
||||
--term.setTextColor(colors.black)
|
||||
clickmenu[cY] = p
|
||||
term.setCursorPos(x1,cY)
|
||||
term.write(string.rep(" ",x2-(x1-1)-11))
|
||||
term.setTextColor(colors.lightGray)
|
||||
term.setBackgroundColor(colors.white)
|
||||
invWrite("\149")
|
||||
term.setBackgroundColor(bg2)
|
||||
term.write(string.rep(" ",10))
|
||||
term.setCursorPos(x1+1,cY)
|
||||
term.setBackgroundColor(bg1)
|
||||
if not pr[p].expanded then
|
||||
term.setTextColor(colors.lightGray)
|
||||
term.write("\16 ")
|
||||
else
|
||||
term.setTextColor(colors.gray)
|
||||
term.write("\31 ")
|
||||
end
|
||||
term.setTextColor(colors.black)
|
||||
local path = pr[p].path
|
||||
if fs.getName(path) == "main.lua" then
|
||||
path = fs.getDir(path)
|
||||
end
|
||||
local t = lUtils.getFileName(path)
|
||||
t = t:sub(1,1):upper()..t:sub(2)
|
||||
term.write(t.." ("..#pr[p].pr..")")
|
||||
local txt
|
||||
if pr[p].yieldTime then
|
||||
txt = percentage(pr[p].yieldTime,lOS.yieldTime)
|
||||
else
|
||||
txt = "???"
|
||||
end
|
||||
term.setCursorPos(x2-#txt,cY)
|
||||
term.setBackgroundColor(bg2)
|
||||
term.write(txt)
|
||||
end
|
||||
cY = cY+1
|
||||
if pr[p].expanded then
|
||||
for t=1,#pr[p].pr do
|
||||
if cY >= y1 and cY <= y2 then
|
||||
clickmenu[cY] = pr[p].pr[t]
|
||||
local bg3
|
||||
local bg4
|
||||
if sel == pr[p].pr[t] or sel == pr[p] then
|
||||
bg3 = colors.lightBlue
|
||||
bg4 = colors.cyan
|
||||
else
|
||||
bg3 = colors.white
|
||||
bg4 = WARN
|
||||
end
|
||||
term.setBackgroundColor(bg3)
|
||||
if not (sel == pr[p]) then
|
||||
term.setCursorPos(x1+3,cY)
|
||||
term.write(string.rep(" ",(x2)-(x1+2)-11))
|
||||
else
|
||||
term.setCursorPos(x1,cY)
|
||||
term.write(string.rep(" ",x2-(x1-1)-11))
|
||||
end
|
||||
term.setTextColor(colors.lightGray)
|
||||
term.setBackgroundColor(colors.white)
|
||||
invWrite("\149")
|
||||
term.setBackgroundColor(bg4)
|
||||
term.write(string.rep(" ",10))
|
||||
term.setBackgroundColor(bg3)
|
||||
term.setTextColor(colors.black)
|
||||
term.setCursorPos(x1+4,cY)
|
||||
term.write(pr[p].pr[t].title)
|
||||
local txt
|
||||
if pr[p].pr[t].yieldTime then
|
||||
txt = percentage(pr[p].pr[t].yieldTime,lOS.yieldTime)
|
||||
else
|
||||
txt = "???"
|
||||
end
|
||||
term.setCursorPos(x2-#txt,cY)
|
||||
term.setBackgroundColor(bg4)
|
||||
term.write(txt)
|
||||
end
|
||||
cY = cY+1
|
||||
end
|
||||
end
|
||||
end
|
||||
-- draw bg processes (no extended)
|
||||
if cY+1 >= y1 and cY+1 <= y2 then
|
||||
term.setTextColor(colors.blue)
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setCursorPos(x1,cY+1)
|
||||
term.write("Background Processes ("..#bg..")")
|
||||
end
|
||||
cY = cY+2
|
||||
local previousColor1
|
||||
local previousColor2
|
||||
for p=1,#bg+1 do
|
||||
local fg1
|
||||
local bg1
|
||||
local fg2
|
||||
local bg2
|
||||
|
||||
local WARN = colors.yellow
|
||||
if p <= #bg and bg[p].yieldTime then
|
||||
local f = bg[p].yieldTime/lOS.yieldTime
|
||||
if f > 0.7 then
|
||||
WARN = colors.red
|
||||
elseif f > 0.4 then
|
||||
WARN = colors.orange
|
||||
end
|
||||
end
|
||||
fg1 = previousColor1 or colors.white
|
||||
fg2 = previousColor2 or colors.yellow
|
||||
if p > #bg or sel ~= bg[p] then
|
||||
bg1 = colors.white
|
||||
bg2 = WARN
|
||||
else
|
||||
bg1 = colors.lightBlue
|
||||
bg2 = colors.cyan
|
||||
end
|
||||
previousColor1 = bg1
|
||||
previousColor2 = bg2
|
||||
if cY >= y1 and cY <= y2 then
|
||||
term.setTextColor(fg1)
|
||||
term.setBackgroundColor(bg1)
|
||||
term.setCursorPos(x1,cY)
|
||||
term.write(string.rep("\131",x2-(x1-1)-11))
|
||||
|
||||
term.setTextColor(colors.lightGray)
|
||||
term.setBackgroundColor(colors.white)
|
||||
invWrite("\149")
|
||||
term.setBackgroundColor(bg1)
|
||||
term.setTextColor(fg2)
|
||||
term.setBackgroundColor(bg2)
|
||||
term.write(string.rep("\131",10))
|
||||
end
|
||||
term.setTextColor(fg1)
|
||||
term.setBackgroundColor(bg1)
|
||||
if p > #bg then
|
||||
break
|
||||
end
|
||||
cY = cY+1
|
||||
if cY >= y1 and cY <= y2 then
|
||||
--term.setTextColor(colors.black)
|
||||
clickmenu[cY] = bg[p]
|
||||
term.setCursorPos(x1,cY)
|
||||
term.write(string.rep(" ",x2-(x1-1)-11))
|
||||
term.setTextColor(colors.lightGray)
|
||||
term.setBackgroundColor(colors.white)
|
||||
invWrite("\149")
|
||||
term.setBackgroundColor(bg2)
|
||||
term.write(string.rep(" ",10))
|
||||
term.setCursorPos(x1+1,cY)
|
||||
term.setBackgroundColor(bg1)
|
||||
if sel ~= bg[p] then
|
||||
term.setBackgroundColor(colors.white)
|
||||
else
|
||||
term.setBackgroundColor(colors.lightBlue)
|
||||
end
|
||||
term.write(" ")
|
||||
term.setTextColor(colors.black)
|
||||
local t = ""
|
||||
if bg[p].title then
|
||||
t = bg[p].title
|
||||
else
|
||||
t = bg[p].path
|
||||
end
|
||||
term.write(t)
|
||||
local txt
|
||||
if bg[p].yieldTime then
|
||||
txt = percentage(bg[p].yieldTime,lOS.yieldTime)
|
||||
else
|
||||
txt = "???"
|
||||
end
|
||||
term.setCursorPos(x2-#txt,cY)
|
||||
term.setBackgroundColor(bg2)
|
||||
term.write(txt)
|
||||
end
|
||||
cY = cY+1
|
||||
end
|
||||
if cY > y2 then
|
||||
scrollable = true
|
||||
end
|
||||
term.setCursorPos(1,y2+1)
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setTextColor(colors.gray)
|
||||
local w,h = term.getSize()
|
||||
term.write(string.rep("\131",w))
|
||||
--term.setCursorPos(x1,y2+2)
|
||||
local txt = "End Task"
|
||||
term.setCursorPos(x2-(string.len(txt)),y2+2)
|
||||
if sel.path then
|
||||
if not cEnd then
|
||||
term.setTextColor(colors.blue)
|
||||
else
|
||||
term.setTextColor(colors.lightBlue)
|
||||
end
|
||||
else
|
||||
term.setTextColor(colors.lightGray)
|
||||
end
|
||||
term.write(txt)
|
||||
|
||||
if e[1] == "mouse_click" then
|
||||
if e[3] >= x1 and e[3] <= x2 and e[4] >= y1 and e[4] <= y2 then
|
||||
sel = {}
|
||||
pSel = {}
|
||||
end
|
||||
if sel.path and e[4] == y2+2 and e[3] >= x2-string.len(txt) and e[3] <= x2-1 then
|
||||
term.setCursorPos(x2-(string.len(txt)),y2+2)
|
||||
term.setTextColor(colors.lightBlue)
|
||||
term.write(txt)
|
||||
cEnd = true
|
||||
end
|
||||
if clickmenu[e[4]] then
|
||||
pSel = clickmenu[e[4]]
|
||||
if type(pSel) == "number" and e[3] == x1+1 then
|
||||
if expanded[pr[pSel].path] == false then
|
||||
expanded[pr[pSel].path] = true
|
||||
else
|
||||
expanded[pr[pSel].path] = false
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif e[1] == "mouse_up" then
|
||||
cEnd = false
|
||||
if sel.path and e[4] == y2+2 and e[3] >= x2-string.len(txt) and e[3] <= x2-1 then
|
||||
local t = 1
|
||||
while true do
|
||||
if lOS.processes[t] == nil then break end
|
||||
if type(sel[1]) == "thread" then
|
||||
if lOS.processes[t] == sel then
|
||||
for i=1,#lOS.wins do
|
||||
if lOS.wins[i] == lOS.processes[t] then
|
||||
table.remove(lOS.wins,i)
|
||||
end
|
||||
end
|
||||
table.remove(lOS.processes,t)
|
||||
break
|
||||
else
|
||||
t = t+1
|
||||
end
|
||||
else
|
||||
if lOS.processes[t].path == sel.path then
|
||||
for i=1,#lOS.wins do
|
||||
if lOS.wins[i] == lOS.processes[t] then
|
||||
table.remove(lOS.wins,i)
|
||||
end
|
||||
end
|
||||
table.remove(lOS.processes,t)
|
||||
else
|
||||
t = t+1
|
||||
end
|
||||
end
|
||||
end
|
||||
sel = {}
|
||||
pSel = {}
|
||||
end
|
||||
end
|
||||
end
|
||||
-- sel wont work since pr gets regenerated every time
|
||||
-- it will work for subprocesses tho
|
||||
local w,h = term.getSize()
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.clear()
|
||||
while true do
|
||||
e = {os.pullEvent()}
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.clear()
|
||||
local w,h = term.getSize()
|
||||
term.setCursorPos(2,3)
|
||||
term.setTextColor(colors.blue)
|
||||
term.write("Name")
|
||||
term.setCursorPos(w-6,3)
|
||||
term.write("Yield")
|
||||
term.setTextColor(colors.black)
|
||||
local txt
|
||||
if lOS.yieldTime then
|
||||
txt = math.ceil(lOS.yieldTime).." ms"
|
||||
else
|
||||
txt = "???"
|
||||
end
|
||||
term.setCursorPos((w-1)-#txt,2)
|
||||
term.write(txt)
|
||||
term.setCursorPos(1,4)
|
||||
term.setTextColor(colors.lightGray)
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.write(string.rep("\131",w))
|
||||
for y=1,3 do
|
||||
term.setCursorPos(w-11,y)
|
||||
invWrite("\149")
|
||||
term.setCursorPos(w,y)
|
||||
term.write("\149")
|
||||
end
|
||||
term.setCursorPos(w-11,4)
|
||||
invWrite("\148")
|
||||
term.setBackgroundColor(colors.yellow)
|
||||
term.write(string.rep("\131",10))
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setCursorPos(w,4)
|
||||
term.write("\151")
|
||||
drawProcs(2,5,w-1,h,e)
|
||||
if e[1] == "key_up" and e[2] == keys.t and lUtils.isHolding(keys.leftShift) then
|
||||
term.setBackgroundColor(colors.black)
|
||||
term.clear()
|
||||
term.setCursorPos(1,1)
|
||||
term.setTextColor(colors.red)
|
||||
print("Terminated")
|
||||
return
|
||||
elseif e[1] == "mouse_click" and e[2] == 2 and lUtils.isInside(e[3],e[4],{x1=w-10,y1=1,x2=w-1,y2=4}) then
|
||||
if display == 1 then
|
||||
lOS.contextmenu(e[3],e[4],0,{{txt="Switch to ms",action=function() display = 2 end}})
|
||||
else
|
||||
lOS.contextmenu(e[3],e[4],0,{{txt="Switch to %",action=function() display = 1 end}})
|
||||
end
|
||||
end
|
||||
end
|
||||
37
LevelOS/assets/Circle_Symbols.limg
Normal file
37
LevelOS/assets/Circle_Symbols.limg
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TT0Tb",
|
||||
"bbbbT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"T000b",
|
||||
"bbbbT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"b00bb",
|
||||
"TbbTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TTTTb",
|
||||
"bbbbT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"T000b",
|
||||
"bbbbT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"b0Tbb",
|
||||
"TbbTT",
|
||||
},
|
||||
},
|
||||
type = "lImg",
|
||||
}
|
||||
110
LevelOS/assets/Compact_Icons.limg
Normal file
110
LevelOS/assets/Compact_Icons.limg
Normal file
@ -0,0 +1,110 @@
|
||||
{
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TT0",
|
||||
"00T",
|
||||
},
|
||||
{
|
||||
"
",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TT0",
|
||||
"00T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TTT",
|
||||
"000",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TTT",
|
||||
"000",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"00T",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"00T",
|
||||
"TTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"T00",
|
||||
"0TT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TT0",
|
||||
"00T",
|
||||
},
|
||||
{
|
||||
"
",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"0TT",
|
||||
"T00",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TTT",
|
||||
"T00",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
}
|
||||
1
LevelOS/assets/Desktop_Icons.limg
Normal file
1
LevelOS/assets/Desktop_Icons.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," 9 ","9bb",},{""," ","999",},{""," ","999",},},{{""," 9 ","9bb",},{""," ","999",},{"lua","000","bbb",},},{{""," ","777",},{"","8b ","b88",},{"","888"," ",},},{{""," 8 ","877",},{""," ","888",},{""," ","888",},},{{""," 8 ","877",},{""," ","888",},{"txt","000","777",},},{{""," 8 ","877",},{""," ","888",},{"cfg","000","777",},},{{""," 4","44 ",},{""," ","444",},{""," ","444",},},{{""," e ","e11",},{""," ","eee",},{"gui","000","111",},},{{""," 5 ","5dd",},{""," ","555",},{"sml","000","ddd",},},{{""," ","ccc",},{"","c43","3dc",},{"","ccc"," ",},},{{"","afa","faf",},{"","faf","afa",},{"","faf"," ",},},{{"","bb "," b",},{"","b b"," b ",},{"","bb "," b",},},{{""," ","888",},{"","8 b","bb8",},{""," ","888",},},{{"","00 ","988",},{"","999","000",},{"
","999","000",},},{{""," "," b ",},{""," ","bbb",},{"","bbb"," ",},},{{""," ","88 ",},{"
","888"," ",},{"","88 "," ",},},{{""," ","000",},{"","03d","3d0",},{"","000"," ",},},{{""," b"," b ",},{""," b"," b ",},{""," b ","b ",},},{{""," 9","9 ",},{"","9 "," 9",},{"","9 9"," ",},},{{"","4b4","b4 ",},{"","bb9","494",},{""," ","444",},},{{""," "," ",},{"
","888","eee",},{"","e78","88e",},},}
|
||||
1
LevelOS/assets/QR_Code.limg
Normal file
1
LevelOS/assets/QR_Code.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," 000b b00 b 000b0","0bbb000bb000bbb0b",},{""," b0bb00b0bbbb0bb0","00b00bb0b0000b00b",},{"
"," 00000000000000b0","0bbbbbbbbbbbbbb0b",},{""," 0bbbb0bbbbb0b0 0","0b0000b00000b0b0b",},{""," b00 bb0 0b0b b0","00bbb00900b0b000b",},{""," 0b0bbb00 0bbbbb0","0b0b000990b00000b",},{""," 0b00000b00 b0bb0","0b0bbbbb0bb00b00b",},{"
"," bbbb0b0b0bbb0bb0","00000b0b0b000b00b",},{"
"," b0bbb00000000b 0","00b000bbbbbbbb00b",},{"
"," bbbbb000bb0b0bb0","000000bbb00b0b00b",},{""," bbbbb b bbbbb 0","0000000000000000b",},},{{""," 000bb 00b b000b ","0bbb000bb000bbb00",},{"
"," b0bb0bb0bbbb0bb ","00b00b00b0000b000",},{""," 000bbbbbbbb000b ","0bbb00000000bbb00",},{""," b00bbb0bb000bbb ","00bb000b00bbb0000",},{""," bbbbb00b000000b ","000000bb0bbbbbb00",},{""," bb0b00bb00bbb0 ","000b0bb00bb000b00",},{""," bbbbbb00bbbb0 b ","0000000bb0000bb00",},{"
"," bbbbbb00b0bb0b ","0000000bb0b00b000",},{""," b0bb0b0bb0000bb ","00b00b0b00bbbb000",},{"
"," bbbbb0bb00b00bb ","000000b00bb0bb000",},{""," bbbbb bbbbbbb ","00000000000000000",},},}
|
||||
172
LevelOS/assets/circProgress.limg
Normal file
172
LevelOS/assets/circProgress.limg
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
{
|
||||
{
|
||||
"",
|
||||
"T8TT",
|
||||
"8T8T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"8TT8",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"888T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"T0TT",
|
||||
"8T8T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"8TT8",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"888T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"T0TT",
|
||||
"8T0T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"8TT8",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"888T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"T0TT",
|
||||
"8T0T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"8TT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"888T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"T0TT",
|
||||
"8T0T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"8TT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"880T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"T0TT",
|
||||
"8T0T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"8TT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"800T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"T0TT",
|
||||
"8T0T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"8TT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"000T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"T0TT",
|
||||
"8T0T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"0TT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"000T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"T0TT",
|
||||
"0T0T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"0TT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"000T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TTTT",
|
||||
"bbbT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"Tb0b",
|
||||
"b0bT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"bbbT",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -1,241 +1,241 @@
|
||||
{
|
||||
{
|
||||
{
|
||||
"-<2D>-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"0TTT",
|
||||
},
|
||||
{
|
||||
"-ْ-ا-ا-ا",
|
||||
"",
|
||||
"0TTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-ا-ل-ا-ا",
|
||||
"",
|
||||
"T0TT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ْ-ا-ا-ا",
|
||||
"",
|
||||
"0TTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-<2D>-ي-ا-ا",
|
||||
"",
|
||||
"T0TT",
|
||||
"0TTT",
|
||||
},
|
||||
{
|
||||
"-<2D>-ا-ا-ا",
|
||||
"",
|
||||
"0TTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-ا-ل-ل-ا",
|
||||
"",
|
||||
"T00T",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ـ-ا-ا-ا",
|
||||
"
",
|
||||
"0TTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-<2D>-ي-<2D>-ا",
|
||||
"",
|
||||
"T0TT",
|
||||
"0T0T",
|
||||
},
|
||||
{
|
||||
"-<2D>-ا-ا-ا",
|
||||
"",
|
||||
"0TTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-<2D>-ي-<2D>-ا",
|
||||
"",
|
||||
"T0TT",
|
||||
"0T0T",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ا-ل",
|
||||
"",
|
||||
"TTT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-ا-ل-ل-ا",
|
||||
"",
|
||||
"T00T",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ا-<2D>",
|
||||
"",
|
||||
"TTT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ى-ا",
|
||||
"",
|
||||
"TT0T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-ا-ي-<2D>-ا",
|
||||
"",
|
||||
"T0TT",
|
||||
"TT0T",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ا-ة",
|
||||
"",
|
||||
"TTT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ل-ا",
|
||||
"",
|
||||
"TT0T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-ا-ا-<2D>-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TT0T",
|
||||
},
|
||||
{
|
||||
"-ا-ا-ا-ة",
|
||||
"",
|
||||
"TTT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ى-ا-ل-ا",
|
||||
"",
|
||||
"0T0T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ة-ا-ا-ل",
|
||||
"",
|
||||
"0TT0",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ل-ل-ا",
|
||||
"",
|
||||
"T00T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ل-ا-ا-ا",
|
||||
"",
|
||||
"0TTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ى-ي-ى-ا",
|
||||
"",
|
||||
"000T",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ـ-ا-ا-ا",
|
||||
"
",
|
||||
"0TTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ى-ي-ا-ا",
|
||||
"",
|
||||
"00TT",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ْ-ا-ا-ا",
|
||||
"",
|
||||
"0TTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ا-ل-ا-ا",
|
||||
"",
|
||||
"T0TT",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"-ا-ا-ا-ا",
|
||||
"",
|
||||
"TTTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ْ-ا-ا-ا",
|
||||
"",
|
||||
"0TTT",
|
||||
"TTTT",
|
||||
},
|
||||
{
|
||||
"-ى-ا-ا-ا",
|
||||
"",
|
||||
"0TTT",
|
||||
"TTTT",
|
||||
},
|
||||
},
|
||||
type = "lImg",
|
||||
}
|
||||
}
|
||||
40
LevelOS/assets/logo_christmas.limg
Normal file
40
LevelOS/assets/logo_christmas.limg
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TeTTTTTT",
|
||||
"eTTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TeTTTTTT",
|
||||
"eTTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TdTTTTTT",
|
||||
"dTTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TdTTTTTT",
|
||||
"dTTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TeTTTTTT",
|
||||
"eTTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TeTTTTTT",
|
||||
"eTTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TTdTTTTd",
|
||||
"ddeeeddT",
|
||||
},
|
||||
},
|
||||
type = "lImg",
|
||||
}
|
||||
40
LevelOS/assets/logo_pride.limg
Normal file
40
LevelOS/assets/logo_pride.limg
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
{
|
||||
{
|
||||
"",
|
||||
"TeTTTTTT",
|
||||
"eTTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TeTTTTTT",
|
||||
"eTTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"T1TTTTTT",
|
||||
"1TTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"T1TTTTTT",
|
||||
"1TTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"T4TTTTTT",
|
||||
"4TTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"T4TTTTTT",
|
||||
"4TTTTTTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TTdTTTTa",
|
||||
"ddbbbaaT",
|
||||
},
|
||||
},
|
||||
type = "lImg",
|
||||
}
|
||||
71
LevelOS/assets/wifi.limg
Normal file
71
LevelOS/assets/wifi.limg
Normal file
@ -0,0 +1,71 @@
|
||||
{
|
||||
{
|
||||
{
|
||||
"",
|
||||
"0TT",
|
||||
"T0T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"000",
|
||||
"TTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TTT",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"8TT",
|
||||
"T8T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"008",
|
||||
"TTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TTT",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"8TT",
|
||||
"T8T",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"888",
|
||||
"TTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TTT",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
"",
|
||||
"eTT",
|
||||
"TeT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"eee",
|
||||
"TTT",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"TTT",
|
||||
"TTT",
|
||||
},
|
||||
},
|
||||
type = "lImg",
|
||||
}
|
||||
324
LevelOS/data/changelog.lconf
Normal file
324
LevelOS/data/changelog.lconf
Normal file
@ -0,0 +1,324 @@
|
||||
{
|
||||
{
|
||||
date = "01-06-2021",
|
||||
version = "2.2.5",
|
||||
description = "It's pride month! To show support, the LevelOS logo has been replaced by a rainbow variant throughout June.",
|
||||
added = {
|
||||
"Added changelog",
|
||||
},
|
||||
fixed = {
|
||||
"lOS.execute now properly takes a window mode argument",
|
||||
"Loading assets through lUtils no longer errors on invalid file path",
|
||||
"lUtils.renderImg now handles transparency slightly better",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "01-06-2021",
|
||||
version = "2.2.6",
|
||||
fixed = {
|
||||
"Modified changelog design and resizing",
|
||||
"Fixed startup erroring after update",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "02-06-2021",
|
||||
version = "2.2.7",
|
||||
added = {
|
||||
"Integrated global login into the LevelOS system",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "02-06-2021",
|
||||
version = "2.2.8",
|
||||
fixed = {
|
||||
"Global login now only appears when LevelCloud is enabled, as was intended",
|
||||
"Shapescape programs no longer crash on versions with mouse_move events",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "03-06-2021",
|
||||
version = "2.2.9",
|
||||
description = "The LevelOS search feature is currently disabled until input boxes are added.",
|
||||
added = {
|
||||
"LevelOS start menu is now an overlay and can be opened by both mouse buttons",
|
||||
"Shapescape programs now clear their window when exited",
|
||||
},
|
||||
fixed = {
|
||||
"Fixed LevelOS infinite-looping when booted without internet",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "03-06-2021",
|
||||
version = "2.2.10",
|
||||
description = "Mouse simulator will be added to LevelOS in the future",
|
||||
added = {
|
||||
"LevelOS can now run on classic computers when an external mouse simulator is used",
|
||||
},
|
||||
fixed = {
|
||||
"Fixed the login screen getting stuck on boot until it received an event",
|
||||
"Fixed the LevelCloud GUI showing an error when booted without internet",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "16-06-2021",
|
||||
version = "2.2.11",
|
||||
description = "This took too long but I finally fixed a bunch of issues in the OS. Input boxes coming soon.",
|
||||
fixed = {
|
||||
"Shutdown fade restored (broke in 2.2.9)",
|
||||
"Fixed startup processes not being able to execute programs before their first yield",
|
||||
"Fixed term_resize events being sent to every process instead of only the resizing one",
|
||||
"Only the focused window has constant thread resuming now to improve performance",
|
||||
"LevelOS now properly reports errors in System and SystemUI processes",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "19-06-2021",
|
||||
version = "2.2.12",
|
||||
description = "Some temporary fixes until the desktop and system are rewritten",
|
||||
added = {
|
||||
"New desktop icons for .lua files, files without extension, files with unknown extensions and LevelOS executables",
|
||||
},
|
||||
fixed = {
|
||||
"LevelOS can now resize itself",
|
||||
"Desktop no longer has weird dragging limits",
|
||||
"Icon creation from the explorer and using lOS.genIco now works properly",
|
||||
"Pigeon icon has been restored",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "22-11-2021",
|
||||
version = "2.3.0",
|
||||
description = "It's been a while, but LevelOS is back. And it's better than ever! Sorry for the long wait! The window manager has been rewritten entirely, and all sorts of cool functionality has been added. Desktop icons have been renewed but don't refresh automatically, so if you want those you have to delete desktop.lconf in LevelOS/data and hold ctrl + r.",
|
||||
added = {
|
||||
"The window manager now has animations on resizing, closing, opening and minimizing of windows",
|
||||
"A tab menu (like Window's alt tab) has been added. Instead of alt, ctrl is used in LevelOS",
|
||||
"Shell and Lua have new icons",
|
||||
"Windows can now be in fullscreen mode by pressing f5",
|
||||
"There's a new login screen and register screen, remember me can be toggled by logging out through the LevelCloud interface and pressing remember me in the prompt that comes up",
|
||||
"Taskbar icons are now actual icons. Custom icons coming soon",
|
||||
"When multiple windows of a certain program are open, they appear in the same taskbar icon",
|
||||
"Taskbar icons can now be right clicked",
|
||||
"Right click menu's are now overlays meaning they can go beyond their window's border",
|
||||
"Bootup now displays what it's currently doing",
|
||||
"The pride LevelOS icon is back due to popular demand",
|
||||
},
|
||||
fixed = {
|
||||
"Desktop auto generation now works properly, may require deleting desktop.lconf in LevelOS/data and holding ctrl + r to work",
|
||||
"The LevelOS start menu (opened by clicking the L in the bottom left corner) now appears on top of other windows",
|
||||
},
|
||||
major = true,
|
||||
},
|
||||
{
|
||||
date = "26-12-2021",
|
||||
version = "2.3.1",
|
||||
description = "Merry Christmas! More changes are on the way for premium users.",
|
||||
added = {
|
||||
"Premium users now have an auto updater for dev builds",
|
||||
"LevelOS now has an integrity check at startup",
|
||||
"Replaced asterisks in login screen with circles",
|
||||
},
|
||||
fixed = {
|
||||
"Minimizing widgets no longer causes a bluescreen",
|
||||
"Clicks on the taskbar now also close widgets",
|
||||
"Desktop shortcuts to program folders now execute properly",
|
||||
"Start screen now properly resizes",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "22-05-2022",
|
||||
version = "2.3.2",
|
||||
description = "I seem to make a habit out of incredibly long delays between updates. Sorry about that. This update contains some very necessary bugfixes and some API rewrites, in wait of a bigger update with rewritten GUIs for several components in LevelOS. Stay tuned!",
|
||||
added = {
|
||||
"Redesigned and improved notifications",
|
||||
"The clock now has a calendar as well",
|
||||
"The window manager now uses a window_focus event",
|
||||
"Shapescape now displays proper error messages when a script errors",
|
||||
},
|
||||
fixed = {
|
||||
"Improved lUtils.renderImg transparency handling",
|
||||
"Cursor no longer displays outside of window",
|
||||
"The certificate error in the login screen has been fixed",
|
||||
"Cursor no longer keeps blinking when a popup opens",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "22-05-2022",
|
||||
version = "2.3.3",
|
||||
description = "Wow! Two updates in one day!",
|
||||
fixed = {
|
||||
"Fixed another occurence of the certificate error in lUtils.login that I missed earlier",
|
||||
},
|
||||
},
|
||||
{
|
||||
major = true,
|
||||
date = "04-08-2022",
|
||||
version = "2.4.0",
|
||||
description = "Version 2.4 is here! This version is all about the rewrites. LevelOS has gotten a completely new and rewritten desktop, which is now bound to the actual folder User/Desktop. There is also a completely new explorer, which together with the desktop supports a new shortcut system. Alongside with these big new changes, there have also been several fixes and other new features, and more will follow.",
|
||||
added = {
|
||||
"Rewrote the desktop, now has custom background support (right click any .nfp, .bimg or .limg image using explorer)",
|
||||
"There is now a new shortcut system (right click any file or folder using explorer and click create shortcut)",
|
||||
"Rewrote the explorer, now comes with a file tree, search function, icon view (icon in the bottom right) and more",
|
||||
"Created the advanced lOS.contextmenu function, documentation will come soon",
|
||||
"Made better taskbar icons",
|
||||
"Changed the LevelOS file structure, LevelOS programs are now in Program_Files/LevelOS",
|
||||
"Replaced openWith.lconf with formats.lconf, which has a better stucture",
|
||||
"There is now a 'Yield' column in Task Manager",
|
||||
"Added 'abort()' function to the LevelOS.close() callback function, to abort closing the program",
|
||||
"Shutting down/rebooting now shows an interface to be able to save your work if apps have LevelOS.close() set",
|
||||
"Added an early version of the Store",
|
||||
"Replaced the lua repl with a custom version",
|
||||
"Added 1 character icon support to the window manager",
|
||||
"Added bimg support across LevelOS",
|
||||
"Added a new program folder structure which is HIGHLY recommended you use for LevelOS programs as it allows setting custom icons: main.lua for file that gets executed when the program is ran, taskbar.bimg for the icon appearing on the taskbar (must be mostly white!) and icon.bimg for the icon appearing on desktop and more"
|
||||
},
|
||||
fixed = {
|
||||
"Shapescape windows now resize properly",
|
||||
"Fixed numerous bugs with CraftOS-PC",
|
||||
"Solved some incompatibility issues with 1.12.2 (may not have caught all, please report if there are more)",
|
||||
"Fixed some bugs in the login screen",
|
||||
}
|
||||
},
|
||||
{
|
||||
date = "08-08-2022",
|
||||
version = "2.4.1",
|
||||
description = "Thanks for the bug reports everyone! All bugs reported have been fixed, and the desktop got some necessary additions as well.",
|
||||
added = {
|
||||
"Right clicking an empty space on the desktop now opens a context menu for creating files and refreshing",
|
||||
"Files can now be renamed directly from the desktop",
|
||||
},
|
||||
fixed = {
|
||||
"Changed fs.combine into a vararg function on 1.12.2 to fix compatibility issues",
|
||||
"Modified lUtils.wordwrap to account for the extra empty line that appears on CraftOS-PC",
|
||||
"Prepared URLs for porting to a different server",
|
||||
}
|
||||
},
|
||||
{
|
||||
date = "11-08-2022",
|
||||
version = "2.4.2",
|
||||
added = {
|
||||
"The text color of icons on the desktop can now be changed through the desktop context menu",
|
||||
},
|
||||
fixed = {
|
||||
"Trying to perform operations on a shortcut of a deleted file no longer errors"
|
||||
}
|
||||
},
|
||||
{
|
||||
date = "01-09-2022",
|
||||
version = "2.4.3",
|
||||
description = "The new servers are finally here! Expect a lot of new features to follow soon that have become possible thanks to the migration.",
|
||||
added = {
|
||||
"Added 3x3 icons to some system folders",
|
||||
"Migrated to new servers",
|
||||
},
|
||||
fixed = {
|
||||
"Improved LevelCloud efficiency",
|
||||
"Fixed a number of issues in the login screen",
|
||||
}
|
||||
},
|
||||
{
|
||||
date = "17-09-2022",
|
||||
version = "2.4.4",
|
||||
description = "Finally implemented some much needed LevelCloud features. Sync conflicts now have a proper interface and you can see the status of file synchronization in the LevelOS file explorer.",
|
||||
added = {
|
||||
"Explorer now shows synchronization status of cloud files",
|
||||
"Sync conflicts in LevelCloud can now be resolved through the interface",
|
||||
"Old context menus in LevelOS now have scrolling like the new ones",
|
||||
}
|
||||
},
|
||||
{
|
||||
date = "18-09-2022",
|
||||
version = "2.4.5",
|
||||
description = "It seems I broke something big last update. Sorry guys, fixed it now.",
|
||||
fixed = {
|
||||
"Fixed a recursion issue in the LevelOS Desktop generation that caused a crash on startup",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "12-02-2023",
|
||||
version = "2.4.6",
|
||||
description = "This update is all about bugfixes. The entire list of bugs has been worked through except for one, so thanks for all of the reports!",
|
||||
fixed = {
|
||||
"Explorer no longer crashes when the opened folder is deleted",
|
||||
"LevelOS no longer displays a warning about LuaJIT when not using LuaJIT",
|
||||
"LevelOS no longer crashes when being ran again after being terminated",
|
||||
"Pressing space during a blue screen actually restarts now",
|
||||
"The Lua REPL no longer crashes when documentation is not found",
|
||||
"Icons no longer go under the taskbar",
|
||||
},
|
||||
added = {
|
||||
"The store now displays icons of apps that use the recommended LevelOS program structure (a main.lua file with a 3x3 icon.bimg file in a folder)",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "25-11-2023",
|
||||
version = "2.4.7",
|
||||
description = "A small update to fix some things in the lUtils API. LevelOS 3 is in development and coming soon!",
|
||||
fixed = {
|
||||
"The lUtils text editor (used by the Lua REPL and Slime Text) now recognizes indenting as a change to be saved and undone",
|
||||
"The lUtils.popup function now automatically sets width and/or height if not provided",
|
||||
"The lUtils.popup function now uses a better word wrapping algorithm so text doesn't go outside of the box anymore",
|
||||
"The start menu on the taskbar now opens instantly without having to receive another event",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "28-11-2023",
|
||||
version = "2.4.8",
|
||||
description = "Another small update with some bugfixes that were reported a while ago.",
|
||||
fixed = {
|
||||
"Resizing the entirety of LevelOS now works correctly",
|
||||
"Trying to execute LevelOS within itself no longer causes a bluescreen",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "09-12-2023",
|
||||
version = "2.4.9",
|
||||
added = {
|
||||
"You can now copy/paste text within the lUtils text editor using ctrl+c and ctrl+v outside of emulators as well, as long as you have some kind of text in your clipboard",
|
||||
"Autocomplete in the lUtils text editor can now list nil values",
|
||||
"Added lOS.getRunningProcess()",
|
||||
}
|
||||
},
|
||||
{
|
||||
date = "09-04-2024",
|
||||
version = "2.5.0",
|
||||
major = true,
|
||||
description = "LevelOS 2 is finally completely compatible with CC: Tweaked 1.109! Apologies it took so long!",
|
||||
added = {
|
||||
"HTTP requests are now private to the programs sending them and can't conflict with eachother",
|
||||
"The tabs and search in the store are now functional, and creator names are displayed below the program titles",
|
||||
},
|
||||
fixed = {
|
||||
"LevelOS is now compatible with CC 1.109 and above",
|
||||
"lOS.getRunningProcess() now returns the correct process at all times",
|
||||
}
|
||||
},
|
||||
{
|
||||
date = "11-04-2024",
|
||||
version = "2.5.1",
|
||||
fixed = {
|
||||
"Restored compatibility with 1.12.2 versions of CC: Tweaked",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "18-04-2024",
|
||||
version = "2.5.2",
|
||||
fixed = {
|
||||
"Added compatibility with the newest CraftOS-PC Accelerated",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "10-08-2024",
|
||||
version = "2.5.3",
|
||||
fixed = {
|
||||
"Fixed the bluescreen upon closing the changelog on newer versions of ComputerCraft",
|
||||
"Fixed a bug with UTF-8 decoding",
|
||||
},
|
||||
},
|
||||
{
|
||||
date = "11-08-2024",
|
||||
version = "2.5.4",
|
||||
fixed = {
|
||||
"Resolved an error in the updater with the newer versions of ComputerCraft",
|
||||
},
|
||||
},
|
||||
}
|
||||
3
LevelOS/data/settings.lconf
Normal file
3
LevelOS/data/settings.lconf
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
package = "Full",
|
||||
}
|
||||
1
LevelOS/data/version.txt
Normal file
1
LevelOS/data/version.txt
Normal file
@ -0,0 +1 @@
|
||||
1723386918734
|
||||
1608
LevelOS/desktop.lua
Normal file
1608
LevelOS/desktop.lua
Normal file
File diff suppressed because it is too large
Load Diff
85
LevelOS/imageviewer.lua
Normal file
85
LevelOS/imageviewer.lua
Normal file
@ -0,0 +1,85 @@
|
||||
local format
|
||||
|
||||
local function getLines(str)
|
||||
local lines = {}
|
||||
local w = 0
|
||||
for potato in str:gmatch("[^\n]+") do
|
||||
table.insert(lines,potato)
|
||||
if #potato > w then
|
||||
w = #potato
|
||||
end
|
||||
end
|
||||
return lines,w
|
||||
end
|
||||
|
||||
--[[local function render(spr)
|
||||
term.setBackgroundColor(colors.black)
|
||||
term.clear()
|
||||
if format == "lImg" then
|
||||
local sW,sH = #spr[1][1],#spr
|
||||
local w,h = term.getSize()
|
||||
for l=1,#spr do
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(sW/2),math.ceil(h/2)-math.floor(sH/2)+(l-1))
|
||||
local bl = {}
|
||||
bl[1] = spr[l][1]
|
||||
bl[2] = string.gsub(spr[l][2],"T",lUtils.toBlit(term.getBackgroundColor()))
|
||||
bl[3] = string.gsub(spr[l][3],"T",lUtils.toBlit(term.getBackgroundColor()))
|
||||
term.blit(unpack(bl))
|
||||
end
|
||||
elseif format == "nfp" or format == "nfg" then
|
||||
local b,e = string.find(spr,"\n")
|
||||
local sW,sH
|
||||
local w,h = term.getSize()
|
||||
local lines,sW = getLines(spr)
|
||||
sH = #lines
|
||||
for l=1,sH do
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(sW/2),math.ceil(h/2)-math.floor(sH/2)+(l-1))
|
||||
term.blit(string.rep(" ",#lines[l]),lines[l],lines[l])
|
||||
end
|
||||
end
|
||||
end]]
|
||||
local render = lUtils.renderImg
|
||||
|
||||
local tArgs = {...}
|
||||
local filepath
|
||||
if tArgs[1] ~= nil and fs.exists(tArgs[1]) then
|
||||
filepath = tArgs[1]
|
||||
end
|
||||
while not filepath do
|
||||
filepath = lUtils.explorer("User","SelFile false")
|
||||
end
|
||||
|
||||
local sprite = {}
|
||||
local ext = lUtils.getFileType(filepath)
|
||||
if ext == ".nfp" then
|
||||
format = "nfp"
|
||||
sprite[1] = lUtils.fread(filepath)
|
||||
elseif ext == ".nfg" then
|
||||
format = "nfg"
|
||||
sprite = lUtils.asset.load(filepath)
|
||||
elseif ext == ".limg" or ext == ".bimg" then
|
||||
format = "lImg"
|
||||
sprite = lUtils.asset.load(filepath)
|
||||
else
|
||||
lUtils.popup("Error","This file type is not supported!",22,9,{"OK"})
|
||||
return
|
||||
end
|
||||
|
||||
local tID = os.startTimer(0.5)
|
||||
render(sprite[1])
|
||||
local spr = 1
|
||||
while true do
|
||||
local e = {os.pullEvent()}
|
||||
if #sprite > 1 and e[1] == "timer" and e[2] == tID then
|
||||
tID = os.startTimer(0.1)
|
||||
spr = spr+1
|
||||
if spr > #sprite then
|
||||
spr = 1
|
||||
end
|
||||
term.clear()
|
||||
render(sprite[spr])
|
||||
elseif e[1] == "term_resize" then
|
||||
term.clear()
|
||||
render(sprite[spr])
|
||||
end
|
||||
end
|
||||
258
LevelOS/lStore.lua
Normal file
258
LevelOS/lStore.lua
Normal file
@ -0,0 +1,258 @@
|
||||
local cookie
|
||||
if lOS and lOS.userID then
|
||||
cookie = {Cookie=lOS.userID}
|
||||
end
|
||||
|
||||
local function printUsage()
|
||||
local programName = arg[0] or fs.getName(shell.getRunningProgram())
|
||||
print("Usages:")
|
||||
print(programName .. " put <path> <project name> [listing]")
|
||||
print(programName .. " get <project name> <path>")
|
||||
print(programName .. " run <project name> <arguments>")
|
||||
end
|
||||
|
||||
local tArgs = { ... }
|
||||
if #tArgs < 2 then
|
||||
printUsage()
|
||||
return
|
||||
end
|
||||
|
||||
if not http then
|
||||
printError("LevelStore requires the http API")
|
||||
printError("Set http.enabled to true in CC: Tweaked's config")
|
||||
return
|
||||
end
|
||||
|
||||
local function fread(file)
|
||||
local f = fs.open(file,"r")
|
||||
local o = f.readAll()
|
||||
f.close()
|
||||
return o
|
||||
end
|
||||
|
||||
local function fwrite(file,content)
|
||||
local f = fs.open(file,"w")
|
||||
f.write(content)
|
||||
f.close()
|
||||
return true
|
||||
end
|
||||
|
||||
local hpost = http.post
|
||||
|
||||
local function getField(thing,fieldname)
|
||||
if string.find(thing,"<"..fieldname..">",1,true) ~= nil and string.find(thing,"</"..fieldname..">",1,true) ~= nil then
|
||||
begin = nil
|
||||
ending = nil
|
||||
trash,begin = string.find(thing,"<"..fieldname..">",1,true)
|
||||
ending,ending2 = string.find(thing,"</"..fieldname..">",begin+1,true)
|
||||
if begin ~= nil and ending ~= nil then
|
||||
return string.sub(thing,begin+1,ending-1),string.sub(thing,1,trash-1)..string.sub(thing,ending2+1,string.len(thing))
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local rType
|
||||
|
||||
local function download(name,pth,saveto,run)
|
||||
local f = hpost("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode(pth).."&"..rType.."="..textutils.urlEncode(name),cookie).readAll()
|
||||
if f and f ~= "409" and f ~= "403" and f ~= "401" then
|
||||
if run then
|
||||
return f
|
||||
else
|
||||
fwrite(saveto,f)
|
||||
return true
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function get(name)
|
||||
|
||||
write("Connecting to LevelStore... ")
|
||||
|
||||
rType = "code"
|
||||
local response, err = http.post("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode("").."&code="..textutils.urlEncode(name),cookie)
|
||||
|
||||
if not response then
|
||||
rType = "name"
|
||||
response, err = http.post("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode("").."&name="..textutils.urlEncode(name),cookie)
|
||||
end
|
||||
|
||||
if response then
|
||||
local tree = {}
|
||||
local folders = {}
|
||||
local function searchFolder(folder)
|
||||
--print("Searching folder root/"..folder)
|
||||
local f = hpost("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode(folder).."&"..rType.."="..textutils.urlEncode(name),cookie).readAll()
|
||||
--print(f)
|
||||
local f2 = f
|
||||
while true do
|
||||
local file = nil
|
||||
file,f = getField(f,"file")
|
||||
if not file then
|
||||
break
|
||||
else
|
||||
local name = getField(file,"name")
|
||||
tree[#tree+1] = fs.combine(folder,name)
|
||||
--print("Found "..fs.combine(folder,name))
|
||||
end
|
||||
end
|
||||
f = f2
|
||||
while true do
|
||||
local file = nil
|
||||
file,f = getField(f,"folder")
|
||||
if not file then
|
||||
break
|
||||
else
|
||||
local name = getField(file,"name")
|
||||
--if not fs.exists(fs.combine(folder,name)) then
|
||||
--fs.makeDir(fs.combine(folder,name))
|
||||
--end
|
||||
folders[#folders+1] = fs.combine(folder,name)
|
||||
searchFolder(fs.combine(folder,name))
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
searchFolder("")
|
||||
print("Success.")
|
||||
|
||||
return tree,folders
|
||||
else
|
||||
printError("Failed.")
|
||||
print(err)
|
||||
end
|
||||
end
|
||||
|
||||
local sCommand = tArgs[1]
|
||||
if sCommand == "put" then
|
||||
if #tArgs < 3 then
|
||||
printUsage()
|
||||
return
|
||||
end
|
||||
local listings = {"unlisted","public"}
|
||||
for t=1,#listings do
|
||||
listings[listings[t]] = true
|
||||
end
|
||||
local listing
|
||||
if tArgs[4] then
|
||||
if not listings[tArgs[4]] then
|
||||
error(tArgs[4].." is not a valid listing. Choose one of the following: "..table.concat( listings, ", "),0)
|
||||
else
|
||||
listing = tArgs[4]
|
||||
end
|
||||
end
|
||||
if not lOS.userID then
|
||||
print("Not logged in")
|
||||
print("Please have an active instance of LevelCloud running")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
local sFile = tArgs[2]
|
||||
local sPath = shell.resolve(fs.combine("User/Cloud",sFile))
|
||||
if not fs.exists(sPath) or not string.find(sPath,"User/Cloud") then
|
||||
print("Path not found")
|
||||
print("Note: provide a relative path to a file or folder starting from cloud")
|
||||
return
|
||||
end
|
||||
|
||||
local sName = string.gsub(tArgs[3]," ","_")
|
||||
|
||||
local list = ""
|
||||
if listing then
|
||||
list = "&listing="..textutils.urlEncode(listing)
|
||||
end
|
||||
write("Connecting to LevelStore... ")
|
||||
local response = http.post(
|
||||
"https://os.leveloper.cc/sProject.php",
|
||||
"path="..textutils.urlEncode(tArgs[2])..
|
||||
"&title="..textutils.urlEncode(sName)..
|
||||
"×tamp="..textutils.urlEncode(tostring(os.epoch("utc")))..
|
||||
"&direct="..textutils.urlEncode("false")..
|
||||
list,
|
||||
{
|
||||
Cookie = lOS.userID
|
||||
}
|
||||
)
|
||||
|
||||
if response then
|
||||
print("Success.")
|
||||
|
||||
local sResponse = response.readAll()
|
||||
response.close()
|
||||
|
||||
print("Uploaded as " .. sResponse)
|
||||
print("Run \"lStore get " .. sName .. "\" or \"lStore get " .. sResponse .. "\" to download anywhere")
|
||||
|
||||
else
|
||||
printError("Failed.")
|
||||
end
|
||||
|
||||
elseif sCommand == "get" then
|
||||
|
||||
if #tArgs < 3 then
|
||||
printUsage()
|
||||
return
|
||||
end
|
||||
|
||||
-- Determine file to download
|
||||
local sCode = tArgs[2]
|
||||
local sFile = tArgs[3]
|
||||
local sPath = shell.resolve(sFile)
|
||||
if fs.exists(sPath) then
|
||||
print("Path already exists")
|
||||
return
|
||||
end
|
||||
|
||||
local tree,folders = get(sCode)
|
||||
if not tree then return end
|
||||
term.write("Downloading... ")
|
||||
local x,y = term.getCursorPos()
|
||||
term.write("0%")
|
||||
if #tree > 1 or #folders > 0 then
|
||||
fs.makeDir(sPath)
|
||||
for f=1,#folders do
|
||||
fs.makeDir(fs.combine(sPath,folders[f]))
|
||||
end
|
||||
for f=1,#tree do
|
||||
download(sCode,tree[f],fs.combine(sPath,tree[f]))
|
||||
term.setCursorPos(x,y)
|
||||
term.write(math.ceil((f/#tree)*100+0.5).."%")
|
||||
end
|
||||
else
|
||||
download(sCode,tree[1],sPath)
|
||||
end
|
||||
term.setCursorPos(x,y)
|
||||
print("100%")
|
||||
print("Downloaded as " .. sFile)
|
||||
elseif sCommand == "run" then
|
||||
local sCode = tArgs[2]
|
||||
local res
|
||||
local tree,folders = get(sCode)
|
||||
if not tree then return end
|
||||
if #tree > 1 or #folders > 0 then
|
||||
print("This project must be downloaded to run.")
|
||||
return
|
||||
else
|
||||
--print(textutils.serialize(tree))
|
||||
res = download(sCode,tree[1],"",true)
|
||||
end
|
||||
if res then
|
||||
local func, err = load(res, sCode, "t", _ENV)
|
||||
if not func then
|
||||
printError(err)
|
||||
return
|
||||
end
|
||||
local success, msg = pcall(func, select(3, ...))
|
||||
if not success then
|
||||
printError(msg)
|
||||
end
|
||||
end
|
||||
else
|
||||
printUsage()
|
||||
return
|
||||
end
|
||||
396
LevelOS/login.lua
Normal file
396
LevelOS/login.lua
Normal file
@ -0,0 +1,396 @@
|
||||
|
||||
local bg = term.getBackgroundColor()
|
||||
local fg = term.getTextColor()
|
||||
|
||||
if fs.exists("bigfont") then
|
||||
os.loadAPI("bigfont")
|
||||
end
|
||||
|
||||
local register = false
|
||||
|
||||
local rememberme = false
|
||||
|
||||
local w,h = term.getSize()
|
||||
|
||||
local userbox = lUtils.makeEditBox("username",w,1)
|
||||
local pwbox = lUtils.makeEditBox("password",w,1)
|
||||
local pwconfirm = lUtils.makeEditBox("pwconfirm",w,1)
|
||||
|
||||
|
||||
if fs.exists("LevelOS/data/account.txt") then
|
||||
userbox.lines[1] = lUtils.fread("LevelOS/data/account.txt")
|
||||
end
|
||||
|
||||
if fs.exists("LevelOS/data/account2.txt") then
|
||||
--pwbox.lines[1] = lUtils.fread("LevelOS/data/account2.txt")
|
||||
token = lUtils.fread("LevelOS/data/account2.txt")
|
||||
--rememberme = true
|
||||
local res = http.post("https://www.old.leveloper.cc/auth.php","username="..userbox.lines[1].."&token="..token)
|
||||
local str = res.readAll()
|
||||
if str:find("Welcome") then
|
||||
local userID = res.getResponseHeaders()["Set-Cookie"]
|
||||
return userID,userbox.lines[1]
|
||||
end
|
||||
end
|
||||
|
||||
local trysub = false
|
||||
|
||||
local continue = true
|
||||
|
||||
local boxes = {}
|
||||
|
||||
local e = {}
|
||||
|
||||
local webresponse
|
||||
|
||||
local userID = ""
|
||||
|
||||
local pause = false
|
||||
|
||||
local function submit()
|
||||
trysub = true
|
||||
continue = true
|
||||
os.sleep(0.5)
|
||||
if continue == true then
|
||||
saveuser = fs.open("LevelOS/data/account.txt","w")
|
||||
saveuser.write(userbox.lines[1])
|
||||
saveuser.close()
|
||||
if rememberme then
|
||||
--lUtils.fwrite("LevelOS/data/account2.txt",pwbox.lines[1])
|
||||
else
|
||||
fs.delete("LevelOS/data/account2.txt")
|
||||
end
|
||||
if register then
|
||||
response = {http.post("https://www.old.leveloper.cc/register.php","username="..userbox.lines[1].."&password="..pwbox.lines[1])}
|
||||
local webres = response[1].readAll()
|
||||
if webres == "200" then
|
||||
local xtra = ""
|
||||
if rememberme then
|
||||
xtra = "&rememberme=true"
|
||||
end
|
||||
response2 = {http.post("https://www.old.leveloper.cc/auth.php","username="..userbox.lines[1].."&password="..pwbox.lines[1]..xtra)}
|
||||
userID = response2[1].getResponseHeaders()["Set-Cookie"]
|
||||
webresponse = webres
|
||||
if rememberme then
|
||||
token = lUtils.getField(response2[1].readAll(),"token")
|
||||
lUtils.fwrite("LevelOS/data/account2.txt",token)
|
||||
end
|
||||
end
|
||||
else
|
||||
local xtra = ""
|
||||
if rememberme then
|
||||
xtra = "&rememberme=true"
|
||||
end
|
||||
response = {http.post("https://www.old.leveloper.cc/auth.php","username="..userbox.lines[1].."&password="..pwbox.lines[1]..xtra)}
|
||||
webresponse = response[1].readAll()
|
||||
userID = response[1].getResponseHeaders()["Set-Cookie"]
|
||||
if rememberme then
|
||||
token = lUtils.getField(webresponse,"token")
|
||||
lUtils.fwrite("LevelOS/data/account2.txt",token)
|
||||
end
|
||||
end
|
||||
--print("username="..userbox.lines[1].."&password="..pwbox.lines[1])
|
||||
-- check if things are present communicate with PHP
|
||||
end
|
||||
end
|
||||
|
||||
local regsel = false
|
||||
|
||||
local function draw()
|
||||
boxes = {}
|
||||
local cY = 1
|
||||
local w,h = term.getSize()
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.clear()
|
||||
term.setBackgroundColor(colors.white)
|
||||
if h < 19 then
|
||||
-- absolutely fkin nothin
|
||||
elseif h < 25 or w < 26 or not bigfont then
|
||||
for t=0,2 do
|
||||
term.setCursorPos(1,cY+t)
|
||||
term.clearLine()
|
||||
end
|
||||
term.setCursorPos(2,cY+2)
|
||||
term.setTextColor(colors.white)
|
||||
term.setBackgroundColor(colors.lightGray)
|
||||
term.write(string.rep("\143",w-2))
|
||||
term.setTextColor(colors.blue)
|
||||
term.setBackgroundColor(colors.white)
|
||||
cY = cY+1
|
||||
term.setCursorPos(1,cY)
|
||||
if register then
|
||||
lUtils.centerText("Register")
|
||||
else
|
||||
lUtils.centerText("Log in")
|
||||
end
|
||||
cY = cY+2
|
||||
else
|
||||
if h < 50 or w < 90 then
|
||||
for t=0,4 do
|
||||
term.setCursorPos(1,cY+t)
|
||||
term.clearLine()
|
||||
end
|
||||
term.setCursorPos(2,cY+4)
|
||||
else
|
||||
for t=0,10 do
|
||||
term.setCursorPos(1,cY+t)
|
||||
term.clearLine()
|
||||
end
|
||||
term.setCursorPos(2,cY+10)
|
||||
end
|
||||
term.setTextColor(colors.white)
|
||||
term.setBackgroundColor(colors.lightGray)
|
||||
term.write(string.rep("\143",w-2))
|
||||
term.setTextColor(colors.blue)
|
||||
term.setBackgroundColor(colors.white)
|
||||
cY = cY+1
|
||||
local size = 1
|
||||
--cY = cY+4
|
||||
if h >= 50 and w >= 90 then
|
||||
size = 2
|
||||
cY = cY+10
|
||||
else
|
||||
cY = cY+4
|
||||
end
|
||||
if register then
|
||||
bigfont.writeOn(term.current(),size,"Register",nil,2)
|
||||
else
|
||||
bigfont.writeOn(term.current(),size,"Log in",nil,2)
|
||||
end
|
||||
end
|
||||
term.setBackgroundColor(colors.white)
|
||||
for y=cY,h do
|
||||
term.setCursorPos(1,y)
|
||||
term.clearLine()
|
||||
end
|
||||
cY = cY+1
|
||||
term.setTextColor(colors.lightGray)
|
||||
local offset = math.ceil(w/30)
|
||||
local spacing = 0
|
||||
if h > 50 then
|
||||
spacing = 5
|
||||
elseif h > 45 then
|
||||
spacing = 4
|
||||
elseif h > 40 then
|
||||
spacing = 3
|
||||
elseif h > 35 then
|
||||
spacing = 2
|
||||
elseif h > 30 then
|
||||
spacing = 1
|
||||
end
|
||||
cY = cY+spacing
|
||||
if (register and trysub and userbox.lines[1] and userbox.lines[1] ~= "" and string.len(userbox.lines[1]) >= 3 and #userbox.lines[1] <= 15 and not string.find(userbox.lines[1],"[^a-zA-Z0-9]")) then -- also check for special characters
|
||||
term.setTextColor(colors.lime)
|
||||
elseif register and trysub then
|
||||
term.setTextColor(colors.red)
|
||||
term.setCursorPos(1,cY+3)
|
||||
if #userbox.lines[1] < 3 or #userbox.lines[1] > 15 then
|
||||
lUtils.centerText("Username must be between 3-15 characters.")
|
||||
else
|
||||
lUtils.centerText("Username can not contain special characters.")
|
||||
end
|
||||
continue = false
|
||||
else
|
||||
term.setTextColor(colors.lightGray)
|
||||
end
|
||||
lUtils.border(1+offset,cY,w-offset,cY+2)
|
||||
userbox.x = 2+offset
|
||||
userbox.y = cY+1
|
||||
userbox.width = ((w-offset)-1)-(1+offset)
|
||||
boxes[#boxes+1] = {x1=1+offset,y1=cY,x2=w-offset,y2=cY+2,func=function() lUtils.drawEditBox(userbox,nil,nil,nil,nil,nil,nil,true,false) end}
|
||||
cY = cY+1
|
||||
term.setCursorPos(2+offset,cY)
|
||||
if userbox.lines[1] and userbox.lines[1] ~= "" then
|
||||
term.setTextColor(colors.gray)
|
||||
term.write(string.sub(userbox.lines[1],1,userbox.width))
|
||||
else
|
||||
term.write("Username")
|
||||
end
|
||||
cY = cY+3+spacing
|
||||
if (register and trysub and pwbox.lines[1] and pwbox.lines[1] ~= "" and string.len(pwbox.lines[1]) >= 5) then
|
||||
term.setTextColor(colors.lime)
|
||||
elseif register and trysub then
|
||||
term.setTextColor(colors.red)
|
||||
continue = false
|
||||
else
|
||||
term.setTextColor(colors.lightGray)
|
||||
end
|
||||
lUtils.border(1+offset,cY,w-offset,cY+2)
|
||||
pwbox.x = 2+offset
|
||||
pwbox.y = cY+1
|
||||
pwbox.width = ((w-offset)-1)-(1+offset)
|
||||
boxes[#boxes+1] = {x1=1+offset,y1=cY,x2=w-offset,y2=cY+2,func=function() lUtils.drawEditBox(pwbox,nil,nil,nil,nil,nil,nil,true,false,"*") end}
|
||||
cY = cY+1
|
||||
term.setCursorPos(2+offset,cY)
|
||||
if pwbox.lines[1] and pwbox.lines[1] ~= "" then
|
||||
term.setTextColor(colors.gray)
|
||||
term.write(string.rep("*",string.len(string.sub(pwbox.lines[1],1,pwbox.width))))
|
||||
else
|
||||
term.write("Password")
|
||||
end
|
||||
if register then
|
||||
cY = cY+3+spacing
|
||||
if (register and trysub and pwconfirm.lines[1] and pwconfirm.lines[1] ~= "" and string.len(pwconfirm.lines[1]) > 3 and pwconfirm.lines[1] == pwbox.lines[1]) then
|
||||
term.setTextColor(colors.lime)
|
||||
elseif register and trysub then
|
||||
term.setTextColor(colors.red)
|
||||
if spacing > 0 then
|
||||
term.setCursorPos(1,cY+3)
|
||||
lUtils.centerText("Passwords don't match.")
|
||||
end
|
||||
continue = false
|
||||
else
|
||||
term.setTextColor(colors.lightGray)
|
||||
end
|
||||
lUtils.border(1+offset,cY,w-offset,cY+2)
|
||||
pwconfirm.x = 2+offset
|
||||
pwconfirm.y = cY+1
|
||||
pwconfirm.width = ((w-offset)-1)-(1+offset)
|
||||
boxes[#boxes+1] = {x1=1+offset,y1=cY,x2=w-offset,y2=cY+2,func=function() lUtils.drawEditBox(pwconfirm,nil,nil,nil,nil,nil,nil,true,false,"*") end}
|
||||
cY = cY+1
|
||||
term.setCursorPos(2+offset,cY)
|
||||
if pwconfirm.lines[1] and pwconfirm.lines[1] ~= "" then
|
||||
term.setTextColor(colors.gray)
|
||||
term.write(string.rep("*",string.len(string.sub(pwconfirm.lines[1],1,pwconfirm.width))))
|
||||
else
|
||||
term.write("Confirm Password")
|
||||
end
|
||||
end
|
||||
cY = cY+3+spacing
|
||||
term.setTextColor(colors.white)
|
||||
if e[1] == "mouse_click" and e[3] >= 1+(offset+2) and e[4] >= cY and e[3] <= w-(offset+2) and e[4] <= cY+2 then
|
||||
regsel = true
|
||||
elseif e[1] == "mouse_up" then
|
||||
regsel = false
|
||||
end
|
||||
if regsel or trysub then
|
||||
term.setBackgroundColor(colors.lightBlue)
|
||||
else
|
||||
term.setBackgroundColor(colors.blue)
|
||||
end
|
||||
lUtils.border(1+(offset+2),cY,w-(offset+2),cY+2,"fill")
|
||||
boxes[#boxes+1] = {x1=1+(offset+2),y1=cY,x2=w-(offset+2),y2=cY+2,func=submit}
|
||||
cY = cY+1
|
||||
term.setCursorPos(1,cY)
|
||||
if register then
|
||||
lUtils.centerText("Register")
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setTextColor(colors.lightBlue)
|
||||
term.setCursorPos(1,cY-2)
|
||||
local w,h = term.getSize()
|
||||
if w < string.len("Already have an account? Log in.") then
|
||||
lUtils.centerText("Log in")
|
||||
else
|
||||
lUtils.centerText("Already have an account? Log in.")
|
||||
end
|
||||
boxes[#boxes+1] = {x1=math.ceil(w/2)-16,x2=math.ceil(w/2)+16,y1=cY-2,y2=cY-2,func=function() register = false end}
|
||||
else
|
||||
lUtils.centerText("Log in")
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setTextColor(colors.lightBlue)
|
||||
term.setCursorPos(1,cY+2)
|
||||
local w,h = term.getSize()
|
||||
if w < string.len("Don't have an account yet? Register.") then
|
||||
lUtils.centerText("Register")
|
||||
else
|
||||
lUtils.centerText("Don't have an account yet? Register.")
|
||||
end
|
||||
boxes[#boxes+1] = {x1=math.ceil(w/2)-18,x2=math.ceil(w/2)+18,y1=cY+2,y2=cY+2,func=function() register = true end}
|
||||
end
|
||||
cY = cY+4
|
||||
local bl = {
|
||||
{
|
||||
"",
|
||||
"00f",
|
||||
"ff0",
|
||||
},
|
||||
{
|
||||
" ",
|
||||
"0ff",
|
||||
"f00",
|
||||
},
|
||||
{
|
||||
"",
|
||||
"fff",
|
||||
"000",
|
||||
},
|
||||
}
|
||||
if rememberme then
|
||||
bl[2][1] = "x"
|
||||
end
|
||||
local txt = " Auto-login" -- 4 spaces for the box
|
||||
local rX = math.ceil(w/2)-math.floor(#txt/2)
|
||||
term.setCursorPos(rX,cY)
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setTextColor(colors.gray)
|
||||
term.write(txt)
|
||||
for b=1,#bl do
|
||||
term.setCursorPos(rX,(cY-2)+b)
|
||||
term.blit(unpack(bl[b]))
|
||||
end
|
||||
table.insert(boxes,{x1=rX,y1=cY,x2=rX+2,y2=cY,func=function() local f = function() rememberme = not rememberme end pause = true f() pause = false end})
|
||||
end
|
||||
local function textboxes()
|
||||
while true do
|
||||
local e = {os.pullEvent()}
|
||||
term.setCursorPos(1,1)
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setTextColor(colors.black)
|
||||
--term.write(table.concat(e,", "))
|
||||
if e[1] == "mouse_up" and e[2] == 1 then
|
||||
for b=1,#boxes do
|
||||
local box = boxes[b]
|
||||
if e[3] >= box.x1 and e[4] >= box.y1 and e[3] <= box.x2 and e[4] <= box.y2 then
|
||||
trysub = false
|
||||
box.func()
|
||||
os.startTimer(0.1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local txtbox = coroutine.create(textboxes)
|
||||
if rememberme then submit() end
|
||||
draw()
|
||||
while true do
|
||||
e = {os.pullEvent()}
|
||||
local w,h = term.getSize()
|
||||
local pW,pH
|
||||
if w < 29 then
|
||||
pW = 19
|
||||
pH = 15
|
||||
else
|
||||
pW = 29
|
||||
pH = 9
|
||||
end
|
||||
if not webresponse then
|
||||
if not pause then
|
||||
draw()
|
||||
end
|
||||
coroutine.resume(txtbox,table.unpack(e))
|
||||
while pause do
|
||||
local e = {os.pullEvent()}
|
||||
coroutine.resume(txtbox,table.unpack(e))
|
||||
end
|
||||
else
|
||||
if (register and webresponse ~= "200") or (not register and not string.find(webresponse,"Welcome")) then
|
||||
lUtils.popup("LevelOS",lUtils.getField(webresponse,"msg"),pW,pH,{"OK"})
|
||||
term.setTextColor(fg)
|
||||
term.setBackgroundColor(bg)
|
||||
if rememberme then
|
||||
rememberme = false
|
||||
fs.delete("LevelOS/data/account2.txt")
|
||||
end
|
||||
return false
|
||||
elseif register then
|
||||
lUtils.popup("LevelOS","You have successfully registered! You are now logged in.",pW,pH,{"OK"})
|
||||
term.setTextColor(fg)
|
||||
term.setBackgroundColor(bg)
|
||||
return userID,userbox.lines[1]
|
||||
else
|
||||
term.setTextColor(fg)
|
||||
term.setBackgroundColor(bg)
|
||||
return userID,userbox.lines[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
713
LevelOS/modules/lex.lua
Normal file
713
LevelOS/modules/lex.lua
Normal file
@ -0,0 +1,713 @@
|
||||
-- Lex, by LoganDark
|
||||
-- Can be loaded using os.loadAPI, has only a single function: lex.lex('code here')
|
||||
-- If loaded using dofile(), it returns the lex function (for environments outside ComputerCraft)
|
||||
-- It returns a list of lists, where each list is one line.
|
||||
-- Each line contains tokens (in the order they are found), where each token is formatted like this:
|
||||
-- {
|
||||
-- type = one of the token types below,
|
||||
-- data = the source code that makes up the token,
|
||||
-- posFirst = the position (inclusive) within THAT LINE that the token starts
|
||||
-- posLast = the position (inclusive) within THAT LINE that the token ends
|
||||
-- }
|
||||
|
||||
-- Possible token types:
|
||||
-- whitespace: Self-explanatory. Can match spaces, newlines, tabs, and carriage returns (although I don't know why anyone would use those... WINDOWS)
|
||||
-- comment: Either multi-line or single-line comments.
|
||||
-- string: A string. Usually the part of the string that is not an escape.
|
||||
-- escape: Can only be found within strings (although they are separate tokens)
|
||||
-- keyword: Keywords. Like "while", "end", "do", etc
|
||||
-- value: Special values. Only true, false, and nil.
|
||||
-- ident: Identifier. Variables, function names, etc..
|
||||
-- number: Numbers!
|
||||
-- symbol: Symbols, like brackets, parenthesis, ., .., ... etc
|
||||
-- operator: Operators, like =, ==, >=, <=, ~=, etc
|
||||
-- unidentified: Anything that isn't one of the above tokens. Consider them ERRORS.
|
||||
|
||||
local chars = {
|
||||
whitespace = {
|
||||
[' '] = true,
|
||||
['\n'] = true,
|
||||
['\t'] = true,
|
||||
['\r'] = true
|
||||
},
|
||||
|
||||
validEscapes = {
|
||||
['a'] = true,
|
||||
['b'] = true,
|
||||
['f'] = true,
|
||||
['n'] = true,
|
||||
['r'] = true,
|
||||
['t'] = true,
|
||||
['v'] = true,
|
||||
['"'] = true,
|
||||
['\''] = true,
|
||||
['\\'] = true,
|
||||
['\n'] = true
|
||||
},
|
||||
|
||||
ident = {
|
||||
['a'] = true,
|
||||
['b'] = true,
|
||||
['c'] = true,
|
||||
['d'] = true,
|
||||
['e'] = true,
|
||||
['f'] = true,
|
||||
['g'] = true,
|
||||
['h'] = true,
|
||||
['i'] = true,
|
||||
['j'] = true,
|
||||
['k'] = true,
|
||||
['l'] = true,
|
||||
['m'] = true,
|
||||
['n'] = true,
|
||||
['o'] = true,
|
||||
['p'] = true,
|
||||
['q'] = true,
|
||||
['r'] = true,
|
||||
['s'] = true,
|
||||
['t'] = true,
|
||||
['u'] = true,
|
||||
['v'] = true,
|
||||
['w'] = true,
|
||||
['x'] = true,
|
||||
['y'] = true,
|
||||
['z'] = true,
|
||||
['A'] = true,
|
||||
['B'] = true,
|
||||
['C'] = true,
|
||||
['D'] = true,
|
||||
['E'] = true,
|
||||
['F'] = true,
|
||||
['G'] = true,
|
||||
['H'] = true,
|
||||
['I'] = true,
|
||||
['J'] = true,
|
||||
['K'] = true,
|
||||
['L'] = true,
|
||||
['M'] = true,
|
||||
['N'] = true,
|
||||
['O'] = true,
|
||||
['P'] = true,
|
||||
['Q'] = true,
|
||||
['R'] = true,
|
||||
['S'] = true,
|
||||
['T'] = true,
|
||||
['U'] = true,
|
||||
['V'] = true,
|
||||
['W'] = true,
|
||||
['X'] = true,
|
||||
['Y'] = true,
|
||||
['Z'] = true,
|
||||
['_'] = true,
|
||||
['0'] = true,
|
||||
['1'] = true,
|
||||
['2'] = true,
|
||||
['3'] = true,
|
||||
['4'] = true,
|
||||
['5'] = true,
|
||||
['6'] = true,
|
||||
['7'] = true,
|
||||
['8'] = true,
|
||||
['9'] = true,
|
||||
|
||||
start = {
|
||||
['a'] = true,
|
||||
['b'] = true,
|
||||
['c'] = true,
|
||||
['d'] = true,
|
||||
['e'] = true,
|
||||
['f'] = true,
|
||||
['g'] = true,
|
||||
['h'] = true,
|
||||
['i'] = true,
|
||||
['j'] = true,
|
||||
['k'] = true,
|
||||
['l'] = true,
|
||||
['m'] = true,
|
||||
['n'] = true,
|
||||
['o'] = true,
|
||||
['p'] = true,
|
||||
['q'] = true,
|
||||
['r'] = true,
|
||||
['s'] = true,
|
||||
['t'] = true,
|
||||
['u'] = true,
|
||||
['v'] = true,
|
||||
['w'] = true,
|
||||
['x'] = true,
|
||||
['y'] = true,
|
||||
['z'] = true,
|
||||
['A'] = true,
|
||||
['B'] = true,
|
||||
['C'] = true,
|
||||
['D'] = true,
|
||||
['E'] = true,
|
||||
['F'] = true,
|
||||
['G'] = true,
|
||||
['H'] = true,
|
||||
['I'] = true,
|
||||
['J'] = true,
|
||||
['K'] = true,
|
||||
['L'] = true,
|
||||
['M'] = true,
|
||||
['N'] = true,
|
||||
['O'] = true,
|
||||
['P'] = true,
|
||||
['Q'] = true,
|
||||
['R'] = true,
|
||||
['S'] = true,
|
||||
['T'] = true,
|
||||
['U'] = true,
|
||||
['V'] = true,
|
||||
['W'] = true,
|
||||
['X'] = true,
|
||||
['Y'] = true,
|
||||
['Z'] = true,
|
||||
['_'] = true
|
||||
},
|
||||
},
|
||||
|
||||
digits = {
|
||||
['0'] = true,
|
||||
['1'] = true,
|
||||
['2'] = true,
|
||||
['3'] = true,
|
||||
['4'] = true,
|
||||
['5'] = true,
|
||||
['6'] = true,
|
||||
['7'] = true,
|
||||
['8'] = true,
|
||||
['9'] = true,
|
||||
|
||||
hex = {
|
||||
['0'] = true,
|
||||
['1'] = true,
|
||||
['2'] = true,
|
||||
['3'] = true,
|
||||
['4'] = true,
|
||||
['5'] = true,
|
||||
['6'] = true,
|
||||
['7'] = true,
|
||||
['8'] = true,
|
||||
['9'] = true,
|
||||
['a'] = true,
|
||||
['b'] = true,
|
||||
['c'] = true,
|
||||
['d'] = true,
|
||||
['e'] = true,
|
||||
['f'] = true,
|
||||
['A'] = true,
|
||||
['B'] = true,
|
||||
['C'] = true,
|
||||
['D'] = true,
|
||||
['E'] = true,
|
||||
['F'] = true
|
||||
}
|
||||
},
|
||||
|
||||
symbols = {
|
||||
['+'] = true,
|
||||
['-'] = true,
|
||||
['*'] = true,
|
||||
['/'] = true,
|
||||
['^'] = true,
|
||||
['%'] = true,
|
||||
[','] = true,
|
||||
['{'] = true,
|
||||
['}'] = true,
|
||||
['['] = true,
|
||||
[']'] = true,
|
||||
['('] = true,
|
||||
[')'] = true,
|
||||
[';'] = true,
|
||||
['#'] = true,
|
||||
['.'] = true,
|
||||
[':'] = true,
|
||||
|
||||
equality = {
|
||||
['~'] = true,
|
||||
['='] = true,
|
||||
['>'] = true,
|
||||
['<'] = true
|
||||
},
|
||||
|
||||
operators = {
|
||||
['+'] = true,
|
||||
['-'] = true,
|
||||
['*'] = true,
|
||||
['/'] = true,
|
||||
['^'] = true,
|
||||
['%'] = true,
|
||||
['#'] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local keywords = {
|
||||
structure = {
|
||||
['and'] = true,
|
||||
['break'] = true,
|
||||
['do'] = true,
|
||||
['else'] = true,
|
||||
['elseif'] = true,
|
||||
['end'] = true,
|
||||
['for'] = true,
|
||||
['function'] = true,
|
||||
['goto'] = true,
|
||||
['if'] = true,
|
||||
['in'] = true,
|
||||
['local'] = true,
|
||||
['not'] = true,
|
||||
['or'] = true,
|
||||
['repeat'] = true,
|
||||
['return'] = true,
|
||||
['then'] = true,
|
||||
['until'] = true,
|
||||
['while'] = true
|
||||
},
|
||||
|
||||
values = {
|
||||
['true'] = true,
|
||||
['false'] = true,
|
||||
['nil'] = true,
|
||||
['self'] = true,
|
||||
}
|
||||
}
|
||||
|
||||
function lex(text)
|
||||
local pos = 1
|
||||
local start = 1
|
||||
local len = #text
|
||||
local buffer = {}
|
||||
local lines = {}
|
||||
|
||||
local function look(delta)
|
||||
delta = pos + (delta or 0)
|
||||
|
||||
return text:sub(delta, delta)
|
||||
end
|
||||
|
||||
local function get()
|
||||
local char = text:sub(pos, pos)
|
||||
|
||||
pos = pos + 1
|
||||
|
||||
return char
|
||||
end
|
||||
|
||||
local function getLevel()
|
||||
local num = 0
|
||||
|
||||
while look(num) == '=' do
|
||||
num = num + 1
|
||||
end
|
||||
|
||||
if look(num) == '[' then
|
||||
pos = pos + num
|
||||
|
||||
return num
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local function getToken()
|
||||
return text:sub(start, pos - 1)
|
||||
end
|
||||
|
||||
local currentLineLength = 0
|
||||
local lineoffset = 0
|
||||
|
||||
local function token(type, text)
|
||||
local tk = buffer[#buffer]
|
||||
|
||||
if not tk or tk.type ~= type then
|
||||
local tk = {
|
||||
type = type,
|
||||
data = text or getToken(),
|
||||
posFirst = start - lineoffset,
|
||||
posLast = pos - 1 - lineoffset
|
||||
}
|
||||
|
||||
if tk.data ~= '' then
|
||||
buffer[#buffer + 1] = tk
|
||||
end
|
||||
else
|
||||
tk.data = tk.data .. (text or getToken())
|
||||
tk.posLast = tk.posFirst + #tk.data - 1
|
||||
--tk.posLast = getCol(pos - 1)
|
||||
end
|
||||
|
||||
currentLineLength = currentLineLength + (text or getToken()):len()
|
||||
|
||||
start = pos
|
||||
return tk
|
||||
end
|
||||
|
||||
local function newline()
|
||||
lines[#lines + 1] = buffer
|
||||
buffer = {}
|
||||
get()
|
||||
token('newline')
|
||||
buffer[1] = nil
|
||||
lineoffset = lineoffset + currentLineLength
|
||||
currentLineLength = 0
|
||||
end
|
||||
|
||||
local function getData(level, type)
|
||||
while true do
|
||||
local char = get()
|
||||
|
||||
if char == '' then
|
||||
return
|
||||
elseif char == '\n' then
|
||||
pos = pos - 1
|
||||
token(type)
|
||||
newline()
|
||||
elseif char == ']' then
|
||||
local valid = true
|
||||
|
||||
for i = 1, level do
|
||||
if look() == '=' then
|
||||
pos = pos + 1
|
||||
else
|
||||
valid = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if valid and look() == ']' then
|
||||
pos = pos + 1
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
while true do
|
||||
while true do
|
||||
local char = look()
|
||||
|
||||
if char == '\n' then
|
||||
token('whitespace')
|
||||
newline()
|
||||
elseif chars.whitespace[char] then
|
||||
pos = pos + 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
token('whitespace')
|
||||
|
||||
local char = get()
|
||||
|
||||
if char == '' then
|
||||
break
|
||||
elseif char == '-' and look() == '-' then
|
||||
pos = pos + 1
|
||||
|
||||
if look() == '[' then
|
||||
pos = pos + 1
|
||||
|
||||
local level = getLevel()
|
||||
|
||||
if level then
|
||||
getData(level, 'comment')
|
||||
else
|
||||
while true do
|
||||
local char2 = get()
|
||||
|
||||
if char2 == '' or char2 == '\n' then
|
||||
pos = pos - 1
|
||||
token('comment')
|
||||
|
||||
if char2 == '\n' then
|
||||
newline()
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
while true do
|
||||
local char2 = get()
|
||||
|
||||
if char2 == '' or char2 == '\n' then
|
||||
pos = pos - 1
|
||||
token('comment')
|
||||
|
||||
if char2 == '\n' then
|
||||
newline()
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
token('comment')
|
||||
elseif char == '\'' or char == '"' then
|
||||
local cbuf = #buffer
|
||||
while true do
|
||||
if not buffer[cbuf] then
|
||||
break
|
||||
elseif buffer[cbuf].type == "whitespace" then
|
||||
cbuf = cbuf-1
|
||||
elseif buffer[cbuf].type == "ident" then
|
||||
buffer[cbuf].type = "function"
|
||||
break
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
while true do
|
||||
local char2 = get()
|
||||
|
||||
if char2 == '\\' then
|
||||
pos = pos - 1
|
||||
token('string')
|
||||
get()
|
||||
|
||||
local char3 = get()
|
||||
|
||||
if chars.digits[char3] then
|
||||
for i = 1, 2 do
|
||||
if chars.digits[look()] then
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
elseif char3 == 'x' then
|
||||
if chars.digits.hex[look()] and chars.digits.hex[look(1)] then
|
||||
pos = pos + 2
|
||||
else
|
||||
token('unidentified')
|
||||
end
|
||||
elseif char3 == '\n' then
|
||||
pos = pos - 1
|
||||
token('escape')
|
||||
newline()
|
||||
elseif not chars.validEscapes[char3] then
|
||||
token('unidentified')
|
||||
end
|
||||
|
||||
token('escape')
|
||||
elseif char2 == '\n' then
|
||||
pos = pos - 1
|
||||
token('string')
|
||||
newline()
|
||||
|
||||
break
|
||||
elseif char2 == char or char2 == '' then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
token('string')
|
||||
elseif chars.ident.start[char] then
|
||||
while chars.ident[look()] do
|
||||
pos = pos + 1
|
||||
end
|
||||
|
||||
local word = getToken()
|
||||
if word == 'self' or word == '_ENV' or word == "_G" then
|
||||
token('arg')
|
||||
elseif word == 'function' then
|
||||
local findBracket = false
|
||||
local c = 0
|
||||
while true do
|
||||
_G.debugstr = ""
|
||||
local lChar = look(c)
|
||||
_G.debugstr = debugstr..lChar
|
||||
if lChar == " " or lChar == "\t" then
|
||||
c = c+1
|
||||
elseif lChar == "(" then
|
||||
findBracket = true
|
||||
break
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
if findBracket then
|
||||
local cbuf = #buffer
|
||||
local findEquals = false
|
||||
while true do
|
||||
--_G.debugstr = debugstr..buffer[cbuf].type
|
||||
if not buffer[cbuf] then
|
||||
break
|
||||
elseif buffer[cbuf].type == "whitespace" then
|
||||
cbuf = cbuf-1
|
||||
elseif buffer[cbuf].data == "=" and not findEquals then
|
||||
cbuf = cbuf-1
|
||||
findEquals = true
|
||||
elseif buffer[cbuf].type == "ident" and findEquals then
|
||||
buffer[cbuf].type = "nfunction"
|
||||
break
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
token('function')
|
||||
elseif keywords.structure[word] then
|
||||
token('keyword')
|
||||
elseif keywords.values[word] then
|
||||
token('value')
|
||||
else
|
||||
local findBracket = false
|
||||
local c = 0
|
||||
while true do
|
||||
local lChar = look(c)
|
||||
if lChar == " " or lChar == "\t" then
|
||||
c = c+1
|
||||
elseif lChar == "(" then
|
||||
findBracket = true
|
||||
break
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
if findBracket then
|
||||
if buffer[#buffer-1] and buffer[#buffer-1].data == "function" and buffer[#buffer].type == "whitespace" then
|
||||
token('nfunction')
|
||||
else
|
||||
token('function')
|
||||
end
|
||||
else
|
||||
local b = #buffer
|
||||
local isArg = true
|
||||
local closedArgs = false
|
||||
while true do
|
||||
local buf = buffer[b]
|
||||
if not buf then
|
||||
isArg = false
|
||||
break
|
||||
elseif buf.data == "(" or buf.type == "whitespace" or buf.data == "," or buf.type == "arg" then
|
||||
if buf.data == "(" then
|
||||
closedArgs = true
|
||||
end
|
||||
b = b-1
|
||||
elseif (buf.data == "function" or buf.type == "nfunction") and closedArgs then
|
||||
token('arg')
|
||||
break
|
||||
else
|
||||
isArg = false
|
||||
break
|
||||
end
|
||||
end
|
||||
if not isArg then
|
||||
token('ident')
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif chars.digits[char] or (char == '.' and chars.digits[look()]) then
|
||||
if char == '0' and look() == 'x' then
|
||||
pos = pos + 1
|
||||
|
||||
while chars.digits.hex[look()] do
|
||||
pos = pos + 1
|
||||
end
|
||||
else
|
||||
while chars.digits[look()] do
|
||||
pos = pos + 1
|
||||
end
|
||||
|
||||
if look() == '.' then
|
||||
pos = pos + 1
|
||||
|
||||
while chars.digits[look()] do
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
|
||||
if look():lower() == 'e' then
|
||||
pos = pos + 1
|
||||
|
||||
if look() == '-' then
|
||||
pos = pos + 1
|
||||
end
|
||||
|
||||
while chars.digits[look()] do
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
token('number')
|
||||
elseif char == '[' then
|
||||
local level = getLevel()
|
||||
|
||||
if level then
|
||||
local cbuf = #buffer
|
||||
while true do
|
||||
if not buffer[cbuf] then
|
||||
break
|
||||
elseif buffer[cbuf].type == "whitespace" then
|
||||
cbuf = cbuf-1
|
||||
elseif buffer[cbuf].type == "ident" then
|
||||
buffer[cbuf].type = "function"
|
||||
break
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
getData(level, 'string')
|
||||
token('string')
|
||||
else
|
||||
token('symbol')
|
||||
end
|
||||
elseif char == '.' then
|
||||
if look() == '.' then
|
||||
pos = pos + 1
|
||||
|
||||
if look() == '.' then
|
||||
pos = pos + 1
|
||||
token('value')
|
||||
else
|
||||
token('operator')
|
||||
end
|
||||
else
|
||||
token('symbol')
|
||||
end
|
||||
elseif chars.symbols.equality[char] then
|
||||
if look() == '=' then
|
||||
pos = pos + 1
|
||||
else
|
||||
|
||||
end
|
||||
|
||||
token('operator')
|
||||
elseif chars.symbols[char] then
|
||||
if chars.symbols.operators[char] then
|
||||
token('operator')
|
||||
else
|
||||
if char == "{" then
|
||||
local cbuf = #buffer
|
||||
while true do
|
||||
if not buffer[cbuf] then
|
||||
break
|
||||
elseif buffer[cbuf].type == "whitespace" then
|
||||
cbuf = cbuf-1
|
||||
elseif buffer[cbuf].type == "ident" then
|
||||
buffer[cbuf].type = "function"
|
||||
break
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
token('symbol')
|
||||
end
|
||||
else
|
||||
token('unidentified')
|
||||
end
|
||||
end
|
||||
|
||||
lines[#lines + 1] = buffer
|
||||
|
||||
return lines
|
||||
end
|
||||
|
||||
return lex
|
||||
0
LevelOS/modules/shapescape/animation.lua
Normal file
0
LevelOS/modules/shapescape/animation.lua
Normal file
147
LevelOS/modules/shapescape/class.lua
Normal file
147
LevelOS/modules/shapescape/class.lua
Normal file
@ -0,0 +1,147 @@
|
||||
local class = {}
|
||||
|
||||
local tAPI = {} -- local class API for objects
|
||||
|
||||
local shapescape
|
||||
|
||||
class.init = function(api)
|
||||
shapescape = api
|
||||
setmetatable(tAPI, {__index=api.group})
|
||||
api.generic.convertToClass = class.convertToClass
|
||||
end
|
||||
|
||||
tAPI.initialize = function(obj)
|
||||
|
||||
local scape = obj:getScape()
|
||||
local publicProperties = obj.publicProperties or {}
|
||||
setmetatable(obj, {__index=tAPI})
|
||||
obj.isClass = true
|
||||
local str = ""
|
||||
|
||||
for k,v in pairs(publicProperties) do
|
||||
if v == "" then
|
||||
table.remove(publicProperties,k)
|
||||
end
|
||||
end
|
||||
|
||||
if not shapescape.utils.locateEntry(publicProperties, "properties") then
|
||||
table.insert(publicProperties,"properties")
|
||||
end
|
||||
|
||||
for i,p in ipairs(publicProperties) do
|
||||
if p == "width" then
|
||||
str = str.."instance:resize(width or instance.width)\n"
|
||||
elseif p == "height" then
|
||||
str = str.."instance:resize(nil, height or instance.height)\n"
|
||||
elseif p == "x" then
|
||||
str = str.."instance:move(x or instance.x)\n" -- "or instance.x1" is already done by API when provided with nil value
|
||||
elseif p == "y" then
|
||||
str = str.."instance:move(nil, y or instance.y)\n"
|
||||
else
|
||||
str = str.."instance."..p.." = "..p.." or instance."..p.."\n"
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(publicProperties,1,"self")
|
||||
|
||||
local fStr = [[
|
||||
return function(]]..table.concat(publicProperties,",")..[[)
|
||||
local instance = shapescape.utils.instantiate(self)
|
||||
if instance.name then
|
||||
instance.class = instance.name
|
||||
instance.name = nil
|
||||
end
|
||||
]]..str..[[
|
||||
for k,v in pairs(properties or {}) do
|
||||
instance[k] = v
|
||||
end
|
||||
instance.isClass = nil
|
||||
return instance
|
||||
end]]
|
||||
|
||||
local func,err = load(fStr,"@instantiate",nil,{shapescape=shapescape,pairs=pairs})
|
||||
if func then
|
||||
obj.instantiate = func()
|
||||
else
|
||||
_G.debugstr = fStr
|
||||
error(err,0)
|
||||
end
|
||||
if obj.name then
|
||||
scape.variables[obj.name] = obj
|
||||
end
|
||||
end
|
||||
|
||||
tAPI.instantiateTo = function(self, target, ...)
|
||||
if not self.instantiate then
|
||||
self:initialize()
|
||||
end
|
||||
return target:addObject(self:instantiate(...))
|
||||
end
|
||||
|
||||
class.convertToClass = function(self, publicProperties, posProperties)
|
||||
publicProperties = publicProperties or {}
|
||||
if self.active then
|
||||
error("Cannot convert active objects",2)
|
||||
end
|
||||
local sl = self:getSlide()
|
||||
if sl then
|
||||
-- remove obj from slide
|
||||
self:destroy(false)
|
||||
end
|
||||
setmetatable(self, {__index=tAPI})
|
||||
self.isClass = true
|
||||
self.publicProperties = publicProperties
|
||||
local coords = {}
|
||||
if posProperties == 1 or posProperties == nil then -- if posProperties is false then no position
|
||||
coords = {"x1","y1","x2","y2"}
|
||||
elseif posProperties == 2 then
|
||||
coords = {"x","y","width","height"}
|
||||
elseif posProperties == 3 then
|
||||
coords = {"x","y"}
|
||||
elseif posProperties == 4 then
|
||||
coords = {"width","height"}
|
||||
end
|
||||
for i,c in ipairs(coords) do
|
||||
if not shapescape.utils.locateEntry(publicProperties, c) then
|
||||
table.insert(publicProperties, i, c)
|
||||
end
|
||||
end
|
||||
table.insert(self:getScape().classes,self)
|
||||
if self:getScape().active then
|
||||
self:initialize()
|
||||
end
|
||||
end
|
||||
|
||||
tAPI.convertToObject = function(self,slide)
|
||||
self.publicProperties = nil
|
||||
self.isClass = nil
|
||||
for k,v in ipairs(self:getScape().classes) do
|
||||
if v == self then
|
||||
table.remove(self:getScape().classes,k)
|
||||
end
|
||||
end
|
||||
slide:addObject(self)
|
||||
end
|
||||
|
||||
tAPI.destroy = function(self)
|
||||
-- remove from classes
|
||||
for k,v in ipairs(scape.classes) do
|
||||
if v == self then
|
||||
table.remove(scape.classes,k)
|
||||
end
|
||||
end
|
||||
shapescape.generic.destroy(self)
|
||||
end
|
||||
|
||||
class.load = function(classObj)
|
||||
setmetatable(classObj, {__index=tAPI})
|
||||
if classObj.children then
|
||||
for i,child in ipairs(classObj.children) do
|
||||
shapescape.loadObject(child)
|
||||
child.parent = classObj
|
||||
child.id = i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return class
|
||||
2228
LevelOS/modules/shapescape/init.lua
Normal file
2228
LevelOS/modules/shapescape/init.lua
Normal file
File diff suppressed because it is too large
Load Diff
1506
LevelOS/modules/shapescape/input.lua
Normal file
1506
LevelOS/modules/shapescape/input.lua
Normal file
File diff suppressed because it is too large
Load Diff
0
LevelOS/modules/shapescape/physics.lua
Normal file
0
LevelOS/modules/shapescape/physics.lua
Normal file
0
LevelOS/modules/shapescape/transition.lua
Normal file
0
LevelOS/modules/shapescape/transition.lua
Normal file
121
LevelOS/settings.lua
Normal file
121
LevelOS/settings.lua
Normal file
@ -0,0 +1,121 @@
|
||||
--ccvs = mwm.newCvs() -- config canvas aka settings canvas
|
||||
btns = {}
|
||||
function _G.btn(x,y,width,lines)
|
||||
btns[#btns+1] = {}
|
||||
thebtn = btns[#btns]
|
||||
thebtn.x = x
|
||||
thebtn.y = y
|
||||
thebtn.w = width
|
||||
thebtn.h = #lines+2
|
||||
function thebtn.render(px,py)
|
||||
if px == nil then
|
||||
px,py = thebtn.x,thebtn.y
|
||||
end
|
||||
thebtn.blit = {{"\151",tostring(lUtils.toBlit(colors.gray)),tostring(lUtils.toBlit(term.getBackgroundColor()))}}
|
||||
for t=1,thebtn.w-2 do
|
||||
thebtn.blit[1][1] = thebtn.blit[1][1].."\131"
|
||||
thebtn.blit[1][2] = thebtn.blit[1][2]..lUtils.toBlit(colors.gray)
|
||||
thebtn.blit[1][3] = thebtn.blit[1][3]..lUtils.toBlit(term.getBackgroundColor())
|
||||
end
|
||||
thebtn.blit[1][1] = thebtn.blit[1][1].."\148"
|
||||
thebtn.blit[1][2] = thebtn.blit[1][2]..lUtils.toBlit(term.getBackgroundColor())
|
||||
thebtn.blit[1][3] = thebtn.blit[1][3]..lUtils.toBlit(colors.gray)
|
||||
for t=1,#lines do
|
||||
thebtn.blit[t+1] = {"\149",tostring(lUtils.toBlit(colors.gray)),tostring(lUtils.toBlit(term.getBackgroundColor()))}
|
||||
for w=1,width-2 do
|
||||
thebtn.blit[t+1][1] = thebtn.blit[t+1][1].." "
|
||||
if t == 1 then
|
||||
thebtn.blit[t+1][2] = thebtn.blit[t+1][2]..lUtils.toBlit(term.getTextColor())
|
||||
else
|
||||
thebtn.blit[t+1][2] = thebtn.blit[t+1][2]..lUtils.toBlit(colors.lightGray)
|
||||
end
|
||||
thebtn.blit[t+1][3] = thebtn.blit[t+1][3]..lUtils.toBlit(term.getBackgroundColor())
|
||||
end
|
||||
local thetxt = ""
|
||||
if string.len(lines[t]) > thebtn.w-2 then
|
||||
thetxt = string.sub(lines[t],thebtn.w-2)
|
||||
else
|
||||
thetxt = lines[t]
|
||||
end
|
||||
thebtn.blit[t+1][1] = "\149"..thetxt..string.sub(thebtn.blit[t+1][1],2+string.len(thetxt),string.len(thebtn.blit[t+1][1]))
|
||||
thebtn.blit[t+1][1] = thebtn.blit[t+1][1].."\149"
|
||||
thebtn.blit[t+1][2] = thebtn.blit[t+1][2]..tostring(lUtils.toBlit(term.getBackgroundColor()))
|
||||
thebtn.blit[t+1][3] = thebtn.blit[t+1][3]..lUtils.toBlit(colors.gray)
|
||||
end
|
||||
thebtn.blit[#thebtn.blit+1] = {"\138",tostring(lUtils.toBlit(term.getBackgroundColor())),tostring(lUtils.toBlit(colors.gray))}
|
||||
local tempblit = thebtn.blit[#thebtn.blit]
|
||||
for t=1,thebtn.w-2 do
|
||||
tempblit[1] = tempblit[1].."\143"
|
||||
tempblit[2] = tempblit[2]..lUtils.toBlit(term.getBackgroundColor())
|
||||
tempblit[3] = tempblit[3]..lUtils.toBlit(colors.gray)
|
||||
end
|
||||
tempblit[1] = tempblit[1].."\133"
|
||||
tempblit[2] = tempblit[2]..lUtils.toBlit(term.getBackgroundColor())
|
||||
tempblit[3] = tempblit[3]..lUtils.toBlit(colors.gray)
|
||||
for t=1,#thebtn.blit do
|
||||
term.setCursorPos(px,py+(t-1))
|
||||
term.blit(table.unpack(thebtn.blit[t]))
|
||||
end
|
||||
end
|
||||
return thebtn
|
||||
end
|
||||
lSettings = {{"Peripherals","Monitors, Speakers,","Printers"},{"Personal Settings","Background, Welcome","Screen"},{"E","Fookin nonsense","aha"},{"Hello","How are you","Mr Valentine"},{"Hey","I am good thank",":)"}}
|
||||
btnW = 21
|
||||
btnH = 5
|
||||
scrl = 0
|
||||
function setrender(scr) -- settings render, scroll (Y)
|
||||
if scr == nil then
|
||||
scr = 0
|
||||
end
|
||||
term.setBackgroundColor(colors.black)
|
||||
term.clear()
|
||||
local w,h = term.getSize()
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(string.len("Settings")/2),2-scr)
|
||||
term.setTextColor(colors.white)
|
||||
term.write("Settings")
|
||||
local cX = math.ceil(w/2)+1
|
||||
local cY = 4
|
||||
while cX-(btnW+1) > 1 do
|
||||
cX = cX-(btnW+1)
|
||||
end
|
||||
local OGcX = cX
|
||||
btns = {}
|
||||
for t=1,#lSettings do
|
||||
--term.setCursorPos(cX,cY-scr)
|
||||
btn(cX,cY-scr,btnW,lSettings[t]).render()
|
||||
if cX+(btnW*2+2) <= w then
|
||||
cX = cX+(btnW+1)
|
||||
else
|
||||
cX = OGcX
|
||||
cY = cY+btnH+1
|
||||
end
|
||||
end
|
||||
end
|
||||
setrender()
|
||||
local aw,ah = term.getSize()
|
||||
local ow,oh = aw,ah
|
||||
while true do
|
||||
e = {os.pullEvent()}
|
||||
if e[1] == "mouse_scroll" then
|
||||
scrl = scrl+e[2]
|
||||
setrender(scrl)
|
||||
elseif e[1] == "mouse_click" then
|
||||
for t=1,#btns do
|
||||
if e[3] >= btns[t].x and e[4] >= btns[t].y and e[3] <= btns[t].x+(btns[t].w-1) and e[4] <= btns[t].y+(btns[t].h-1) then
|
||||
term.setCursorPos(1,1)
|
||||
print("Yey")
|
||||
term.setBackgroundColor(colors.gray)
|
||||
btns[t].render(btns[t].x,btns[t].y)
|
||||
end
|
||||
end
|
||||
elseif e[1] == "mouse_up" then
|
||||
term.setBackgroundColor(colors.black)
|
||||
setrender(scrl)
|
||||
end
|
||||
aw,ah = term.getSize()
|
||||
if aw ~= ow or ah ~= oh then
|
||||
setrender(scrl)
|
||||
ow,oh = aw,ah
|
||||
end
|
||||
end
|
||||
os.sleep(3)
|
||||
176
LevelOS/startup/MwMRender
Normal file
176
LevelOS/startup/MwMRender
Normal file
@ -0,0 +1,176 @@
|
||||
if mwm == nil then _G.mwm = {} end
|
||||
function tabletext(text)
|
||||
local tTable = {}
|
||||
for a=1,string.len(text) do
|
||||
tTable[a] = string.sub(text,a,a)
|
||||
end
|
||||
return tTable
|
||||
end
|
||||
to_colors, to_blit = {}, {}
|
||||
for i = 1, 16 do
|
||||
to_blit[2^(i-1)] = ("0123456789abcdef"):sub(i, i)
|
||||
to_colors[("0123456789abcdef"):sub(i, i)] = 2^(i-1)
|
||||
end
|
||||
function mwm.newCvs(tX,tY)
|
||||
local cvs = {}
|
||||
cvs.rCvs = {}
|
||||
cvs.oCvs = {}
|
||||
cvs.orCvs = {}
|
||||
cvs.color = colors.white
|
||||
if tX == nil or tY == nil then
|
||||
tX,tY = term.getSize()
|
||||
end
|
||||
for x=1,tX do
|
||||
cvs.rCvs[x] = {}
|
||||
for y=1,tY do
|
||||
cvs.rCvs[x][y] = {"",term.getBackgroundColor()} -- empty pixel = ""
|
||||
end
|
||||
end
|
||||
cvs.width = tX
|
||||
cvs.height = tY
|
||||
local function genCvs()
|
||||
cvs.rCvs = {}
|
||||
local tX,tY = cvs.width,cvs.height
|
||||
for x=1,tX do
|
||||
cvs.rCvs[x] = {}
|
||||
for y=1,tY do
|
||||
cvs.rCvs[x][y] = {"",term.getBackgroundColor()} -- empty pixel = ""
|
||||
end
|
||||
end
|
||||
end
|
||||
function cvs.setColor(color)
|
||||
cvs.color = color
|
||||
end
|
||||
function cvs.rect(x,y,w,h,text,txtcolor)
|
||||
if tonumber(x) == nil or tonumber(y) == nil or tonumber(w) == nil or tonumber(h) == nil then
|
||||
return
|
||||
end
|
||||
if text ~= nil then
|
||||
if txtcolor == nil then
|
||||
txtcolor = colors.white
|
||||
end
|
||||
if type(text) == "string" then
|
||||
text = {text}
|
||||
end
|
||||
for t=1,#text do
|
||||
if string.len(text[t]) > w then
|
||||
string.sub(text[t],1,w)
|
||||
end
|
||||
end
|
||||
end
|
||||
cvs.oCvs[#cvs.oCvs+1] = {type="rect",x=x,y=y,width=w,height=h,color=cvs.color,txt=text,txtcolor=txtcolor,ref=#cvs.oCvs+1}
|
||||
return cvs.oCvs[#cvs.oCvs],true
|
||||
end
|
||||
function cvs.print(text,x,y)
|
||||
if text == nil or tonumber(x) == nil or tonumber(y) == nil then
|
||||
return
|
||||
end
|
||||
cvs.oCvs[#cvs.oCvs+1] = {type="text",txt=text,x=x,y=y,color=cvs.color}
|
||||
return cvs.oCvs[#cvs.oCvs],true
|
||||
end
|
||||
cvs.write = cvs.print
|
||||
function cvs.sprite(file,x,y,w,h)
|
||||
if fs.exists(file) == false then
|
||||
return
|
||||
end
|
||||
opensprite = fs.open(file,"r")
|
||||
local sprite = opensprite.readAll()
|
||||
opensprite.close()
|
||||
sprite = textutils.unserialize(sprite)
|
||||
if sprite == nil then return end
|
||||
cvs.oCvs[#cvs.oCvs+1] = {type="sprite",texture=sprite,x=x,y=y,width=w,height=h}
|
||||
return cvs.oCvs[#cvs.oCvs]
|
||||
end
|
||||
-- Support circle rendering. This can be done by calculating with math.cos how many pixels it is from one side of one y coord to the other side of the same y coord and putting that in a string. repeat this for every y coord then draw
|
||||
function cvs.clear()
|
||||
cvs.oCvs = {}
|
||||
end
|
||||
function cvs.render(trans,x1,y1,x2,y2)
|
||||
if x1 == nil then x1 = 1 end
|
||||
if y1 == nil then y1 = 1 end
|
||||
if x2 == nil then x2 = cvs.width end
|
||||
if y2 == nil then y2 = cvs.height end
|
||||
genCvs()
|
||||
bgcolor = term.getBackgroundColor()
|
||||
for a=1,#cvs.oCvs do
|
||||
local o = cvs.oCvs[a]
|
||||
cvs.oCvs[a].ref = a
|
||||
o.x = math.floor(o.x+0.5)
|
||||
o.y = math.floor(o.y+0.5)
|
||||
if o.type == "rect" then
|
||||
for b=1,o.height do
|
||||
for c=1,o.width do
|
||||
local tX,tY = term.getSize()
|
||||
if o.x+(c-1) <= tX and o.y+(b-1) <= tY and o.x+(c-1) > 0 and o.y+(b-1) > 0 then
|
||||
cvs.rCvs[o.x+(c-1)][o.y+(b-1)] = {" ",o.color}
|
||||
end
|
||||
end
|
||||
end
|
||||
if o.txt ~= nil and o.txtcolor ~= nil then
|
||||
for b=1,o.height do
|
||||
if o.txt[b] ~= nil then
|
||||
dObj = tabletext(o.txt[b])
|
||||
for c=1,string.len(o.txt[b]) do
|
||||
cvs.rCvs[o.x+(c-1)][o.y+(b-1)] = {dObj[c],o.color,o.txtcolor}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif o.type == "sprite" then
|
||||
for b=1,o.height do
|
||||
for c=1,o.width do
|
||||
if o.texture[c] ~= nil then
|
||||
local tX,tY = term.getSize()
|
||||
if o.x+(c-1) <= tX and o.y+(b-1) <= tY and o.x+(c-1) > 0 and o.y+(b-1) > 0 and o.texture[c][b] ~= nil then
|
||||
cvs.rCvs[o.x+(c-1)][o.y+(b-1)] = o.texture[c][b]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif o.type == "text" then
|
||||
dObj = tabletext(o.txt)
|
||||
for b=1,#dObj do
|
||||
local tX,tY = term.getSize()
|
||||
if o.x+(b-1) <= tX and o.y <= tY and o.x+(b-1) > 0 and o.y > 0 then
|
||||
cvs.rCvs[o.x+(b-1)][o.y][1] = dObj[b]
|
||||
cvs.rCvs[o.x+(b-1)][o.y][3] = o.color
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for y=y1,y2 do
|
||||
bl1 = ""
|
||||
bl2 = ""
|
||||
bl3 = ""
|
||||
for x=x1,x2 do
|
||||
if not (cvs.orCvs[x] ~= nil and cvs.orCvs[x][y] == cvs.rCvs[x][y]) then
|
||||
if cvs.rCvs[x][y][1] == "" then
|
||||
if term.current().getLine and trans then
|
||||
local theline = {term.current().getLine(y)}
|
||||
bl1 = bl1..string.sub(theline[1],x,x)
|
||||
bl2 = bl2..string.sub(theline[2],x,x)
|
||||
bl3 = bl3..string.sub(theline[3],x,x)
|
||||
else
|
||||
bl1 = bl1.." "
|
||||
bl2 = bl2..0
|
||||
bl3 = bl3..to_blit[cvs.rCvs[x][y][2]]
|
||||
end
|
||||
else
|
||||
if cvs.rCvs[x][y][3] ~= nil then
|
||||
bl2 = bl2..to_blit[cvs.rCvs[x][y][3]]
|
||||
else
|
||||
bl2 = bl2..0
|
||||
end
|
||||
bl1 = bl1..tostring(cvs.rCvs[x][y][1])
|
||||
bl3 = bl3..to_blit[cvs.rCvs[x][y][2]]
|
||||
end
|
||||
end
|
||||
end
|
||||
term.setCursorPos(x1,y)
|
||||
term.blit(bl1,bl2,bl3)
|
||||
end
|
||||
cvs.orCvs = cvs.rCvs
|
||||
term.setBackgroundColor(bgcolor)
|
||||
end
|
||||
return cvs
|
||||
end
|
||||
@ -4384,9 +4384,9 @@ function lUtils.openWin(title,filepath,x,y,width,height,canresize,canmaximize)
|
||||
end
|
||||
term.setTextColor(colors.white)
|
||||
if canmaximize == false then
|
||||
term.write(" × ")
|
||||
term.write(" × ")
|
||||
else
|
||||
term.write(" + × ")
|
||||
term.write(" + × ")
|
||||
end
|
||||
term.setCursorPos(x+1,y)
|
||||
term.write(title)
|
||||
@ -4501,7 +4501,7 @@ function lUtils.openWin(title,filepath,x,y,width,height,canresize,canmaximize)
|
||||
term.setTextColor(colors.white)
|
||||
term.setBackgroundColor(colors.red)
|
||||
term.setCursorPos(x+(width-3),y)
|
||||
term.write(" × ")
|
||||
term.write(" × ")
|
||||
elseif e[1] == "mouse_up" then
|
||||
stop = true
|
||||
return false
|
||||
@ -4618,7 +4618,7 @@ function lUtils.popup(title,msg,width,height,buttons,redrawscreen,colorScheme)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
|
||||
write(" "..title)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
|
||||
write(" × ")
|
||||
write(" × ")
|
||||
-- The line below is unreadable now but it just makes the text box for the popup message and then prints it
|
||||
term.setBackgroundColor(bg)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+1,math.ceil(h/2)-math.floor(height/2)+1)
|
||||
@ -4698,7 +4698,7 @@ function lUtils.popup(title,msg,width,height,buttons,redrawscreen,colorScheme)
|
||||
term.setTextColor(colors.white)
|
||||
term.setBackgroundColor(colors.red)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
|
||||
write(" × ")
|
||||
write(" × ")
|
||||
elseif event == "mouse_up" then
|
||||
if redrawscreen ~= nil and redrawscreen == true then
|
||||
OGwin.render()
|
||||
@ -4721,7 +4721,7 @@ function lUtils.popup(title,msg,width,height,buttons,redrawscreen,colorScheme)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
|
||||
write(" "..title)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
|
||||
write(" × ")
|
||||
write(" × ")
|
||||
os.sleep(0.1)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
|
||||
term.setBackgroundColor(tbbg)
|
||||
@ -4730,7 +4730,7 @@ function lUtils.popup(title,msg,width,height,buttons,redrawscreen,colorScheme)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
|
||||
write(" "..title)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
|
||||
write(" × ")
|
||||
write(" × ")
|
||||
os.sleep(0.1)
|
||||
end
|
||||
end
|
||||
@ -4772,7 +4772,7 @@ function lUtils.inputbox(title,msg,width,height,buttons)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
|
||||
write(" "..title)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
|
||||
write(" × ")
|
||||
write(" × ")
|
||||
-- The line below is unreadable now but it just makes the text box for the popup message and then prints it
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+1,math.ceil(h/2)-math.floor(height/2)+1)
|
||||
@ -4871,7 +4871,7 @@ function lUtils.inputbox(title,msg,width,height,buttons)
|
||||
term.setTextColor(colors.white)
|
||||
term.setBackgroundColor(colors.red)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
|
||||
write(" × ")
|
||||
write(" × ")
|
||||
elseif event == "mouse_up" then
|
||||
return false,0,""
|
||||
end
|
||||
@ -4892,7 +4892,7 @@ function lUtils.inputbox(title,msg,width,height,buttons)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
|
||||
write(" "..title)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
|
||||
write(" × ")
|
||||
write(" × ")
|
||||
os.sleep(0.1)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
|
||||
term.setBackgroundColor(colors.gray)
|
||||
@ -4901,7 +4901,7 @@ function lUtils.inputbox(title,msg,width,height,buttons)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2),math.ceil(h/2)-math.floor(height/2))
|
||||
write(" "..title)
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(width/2)+width-3,math.ceil(h/2)-math.floor(height/2))
|
||||
write(" × ")
|
||||
write(" × ")
|
||||
os.sleep(0.1)
|
||||
end
|
||||
end
|
||||
@ -5377,4 +5377,4 @@ function lUtils.isInside(x,y,object)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
1505
LevelOS/system.lua
Normal file
1505
LevelOS/system.lua
Normal file
File diff suppressed because it is too large
Load Diff
648
Program_Files/Common_Files/oop.lua
Normal file
648
Program_Files/Common_Files/oop.lua
Normal file
@ -0,0 +1,648 @@
|
||||
------------------------------------------------ LevelOOPer Library 2.2.6 ------------------------------------------------
|
||||
function _G.pairs(t)
|
||||
local mt = getmetatable(t)
|
||||
if mt and type(mt.__pairs) == "function" then
|
||||
return mt.__pairs(t)
|
||||
else
|
||||
return next, t, nil
|
||||
end
|
||||
end
|
||||
|
||||
local function fread(file)
|
||||
local f = fs.open(file,"r")
|
||||
local txt = f.readAll()
|
||||
f.close()
|
||||
return txt
|
||||
end
|
||||
|
||||
local env = _ENV
|
||||
local oop = {}
|
||||
|
||||
local classCache = {}
|
||||
local privCache = {}
|
||||
local publicCache = {}
|
||||
local objectCache = {}
|
||||
|
||||
local dir = fs.getDir(({...})[1] or shell.getRunningProgram())
|
||||
|
||||
local function typeRestriction(index, sType, value)
|
||||
if not oop.isType(value, sType) then
|
||||
return false, "cannot convert "..sType.." '"..index.."' to '"..oop.type(value, true).."'"
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function getNumberType(number)
|
||||
if number%1 == 0 then
|
||||
return "int"
|
||||
else
|
||||
return "double"
|
||||
end
|
||||
end
|
||||
|
||||
oop.setEnv = function(newEnv)
|
||||
env = newEnv
|
||||
end
|
||||
|
||||
oop.setDir = function(newDir)
|
||||
oop.expect(1, newDir, "string")
|
||||
dir = newDir
|
||||
end
|
||||
|
||||
oop.getDir = function()
|
||||
return dir
|
||||
end
|
||||
|
||||
local default = {
|
||||
int = 0,
|
||||
double = 0,
|
||||
number = 0,
|
||||
string = "",
|
||||
["function"] = function() end,
|
||||
table = {},
|
||||
boolean = false,
|
||||
}
|
||||
|
||||
local varTypes = {
|
||||
int = "int",
|
||||
double = "double",
|
||||
num = "number",
|
||||
str = "string",
|
||||
func = "function",
|
||||
tbl = "table",
|
||||
bool = "boolean",
|
||||
}
|
||||
|
||||
local newVar = {
|
||||
var = function(name)
|
||||
local tbl = {name=name}
|
||||
setmetatable(tbl, {
|
||||
__call = function(self, value)
|
||||
self.value = value
|
||||
return self
|
||||
end
|
||||
})
|
||||
return tbl
|
||||
end,
|
||||
obj = function(class)
|
||||
oop.expect(1, class, "class")
|
||||
local var = {type=classCache[class].name}
|
||||
setmetatable(var, {
|
||||
__call = function(self, name)
|
||||
self.name = name
|
||||
setmetatable(var, {
|
||||
__call = function(self, value)
|
||||
local ok,err = typeRestriction(name, var.type, value)
|
||||
if not ok then
|
||||
error(err, 2)
|
||||
else
|
||||
self.value = value
|
||||
return self
|
||||
end
|
||||
end,
|
||||
})
|
||||
return self
|
||||
end,
|
||||
})
|
||||
return var
|
||||
end,
|
||||
}
|
||||
|
||||
local const = function(name)
|
||||
if type(name) == "function" then
|
||||
return function(realname)
|
||||
local var = name(realname)
|
||||
var.const = true
|
||||
return var
|
||||
end
|
||||
elseif type(name) == "string" then
|
||||
local var = {name=name, const=true}
|
||||
setmetatable(var, {
|
||||
__call = function(self, value)
|
||||
self.value = value
|
||||
return self
|
||||
end,
|
||||
})
|
||||
return var
|
||||
end
|
||||
end
|
||||
|
||||
for k,v in pairs(varTypes) do
|
||||
newVar[k] = function(name)
|
||||
local tbl = {name=name, type=varTypes[k]}
|
||||
setmetatable(tbl, {
|
||||
__call = function(self, value)
|
||||
local stat,err = typeRestriction(name, tbl.type, value)
|
||||
if not stat then
|
||||
error(err, 2)
|
||||
else
|
||||
self.value = value
|
||||
return self
|
||||
end
|
||||
end,
|
||||
})
|
||||
return tbl
|
||||
end
|
||||
end
|
||||
|
||||
oop.injectEnv = function(env)
|
||||
env.oop = oop
|
||||
env.class = oop.class
|
||||
env.const = const
|
||||
env.import = oop.import
|
||||
env.type = oop.type
|
||||
env.getPublicObject = oop.getPublicObject
|
||||
for k,v in pairs(newVar) do
|
||||
env[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
local metamethods = {
|
||||
["__add"] = true,
|
||||
["__sub"] = true,
|
||||
["__mul"] = true,
|
||||
["__div"] = true,
|
||||
["__mod"] = true,
|
||||
["__pow"] = true,
|
||||
["__unm"] = true,
|
||||
["__concat"] = true,
|
||||
["__len"] = true,
|
||||
["__eq"] = true,
|
||||
["__lt"] = true,
|
||||
["__le"] = true,
|
||||
["__index"] = true,
|
||||
["__newindex"] = true,
|
||||
["__call"] = true,
|
||||
["__tostring"] = true,
|
||||
["__metatable"] = true,
|
||||
["__pairs"] = true,
|
||||
["__ipairs"] = true
|
||||
}
|
||||
|
||||
local function sanitizeArgs(...)
|
||||
local args = table.pack(...)
|
||||
for k,v in pairs(args) do
|
||||
if publicCache[v] then
|
||||
args[k] = publicCache[v]
|
||||
end
|
||||
end
|
||||
return table.unpack(args, nil, args.n)
|
||||
end
|
||||
|
||||
local function instantiate(orig)
|
||||
local function deepCopy(o, seen)
|
||||
seen = seen or {}
|
||||
if seen[o] then
|
||||
return seen[o]
|
||||
end
|
||||
local copy
|
||||
if type(o) == 'table' then
|
||||
copy = {}
|
||||
seen[o] = copy
|
||||
for k,v in pairs(o) do
|
||||
copy[deepCopy(k, seen)] = deepCopy(v, seen)
|
||||
end
|
||||
setmetatable(copy, deepCopy(getmetatable(o), seen))
|
||||
else
|
||||
copy = o
|
||||
end
|
||||
return copy
|
||||
end
|
||||
return deepCopy(orig)
|
||||
end
|
||||
|
||||
local function makeClass(name, classTbl, inherit)
|
||||
local class = {
|
||||
static = {
|
||||
},
|
||||
private = {
|
||||
},
|
||||
public = {
|
||||
},
|
||||
properties = {
|
||||
static = {
|
||||
},
|
||||
private = {
|
||||
},
|
||||
public = {
|
||||
},
|
||||
types = {
|
||||
},
|
||||
consts = {
|
||||
},
|
||||
},
|
||||
metatable = {
|
||||
public = {
|
||||
},
|
||||
private = {
|
||||
},
|
||||
},
|
||||
name = name,
|
||||
}
|
||||
|
||||
class.metatable.static = {
|
||||
__index = class.static,
|
||||
__newindex = function(tbl, k, v)
|
||||
if class.properties.static[k] then
|
||||
if class.properties.consts[k] then
|
||||
error("cannot modify const '"..tostring(k).."'", 2)
|
||||
elseif class.properties.types[k] then
|
||||
local stat,err = typeRestriction(k, class.properties.types[k], v)
|
||||
if not stat then
|
||||
error(err, 2)
|
||||
else
|
||||
class.static[k] = v
|
||||
end
|
||||
end
|
||||
elseif class.properties.private[k] then
|
||||
error("cannot modify private property '"..tostring(k).."' outside of class", 2)
|
||||
elseif class.properties.public[k] then
|
||||
error("cannot modify public property '"..tostring(k).."' outside of object", 2)
|
||||
end
|
||||
end,
|
||||
__call = function(self, ...)
|
||||
local privObj = {}
|
||||
local obj = {}
|
||||
|
||||
privCache[obj] = privObj
|
||||
publicCache[privObj] = obj
|
||||
|
||||
local properties = {}
|
||||
local privProperties = {}
|
||||
|
||||
setmetatable(properties, {__index=class.public})
|
||||
setmetatable(privProperties, {
|
||||
__index=function(t, k)
|
||||
return properties[k] or class.private[k]
|
||||
end
|
||||
})
|
||||
|
||||
local mt = {
|
||||
__index = function(t, k)
|
||||
local p = properties
|
||||
if t == privObj then
|
||||
p = privProperties
|
||||
end
|
||||
local v = p[k]
|
||||
if type(v) == "function" then
|
||||
local tEnv = {self=privObj}
|
||||
oop.injectEnv(tEnv)
|
||||
setmetatable(tEnv, {__index=env})
|
||||
setfenv(v, tEnv)
|
||||
end
|
||||
return v
|
||||
end
|
||||
}
|
||||
|
||||
local inConstructor = false
|
||||
|
||||
mt.__pairs = function(tbl)
|
||||
local loopThroughTables = {properties, class.public, class.static}
|
||||
if tbl == privObj then
|
||||
table.insert(loopThroughTables, 2, class.private)
|
||||
end
|
||||
local cls = class
|
||||
while cls.parent do -- this WONT WORK
|
||||
cls = cls.parent
|
||||
if tbl == privObj then
|
||||
table.insert(loopThroughTables, cls.private)
|
||||
end
|
||||
table.insert(loopThroughTables, cls.public)
|
||||
table.insert(loopThroughTables, cls.static)
|
||||
end
|
||||
|
||||
local currentIndex = 1
|
||||
|
||||
local had = {}
|
||||
|
||||
local function customIterator(_, prevKey)
|
||||
local key, value
|
||||
|
||||
while currentIndex <= #loopThroughTables do
|
||||
key, value = next(loopThroughTables[currentIndex], prevKey)
|
||||
while key ~= nil and had[key] do -- skip keys that were already found
|
||||
key, value = next(loopThroughTables[currentIndex], key)
|
||||
end
|
||||
|
||||
if key ~= nil then
|
||||
had[key] = true
|
||||
return key, tbl[key]
|
||||
else
|
||||
prevKey = nil
|
||||
currentIndex = currentIndex + 1
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
return customIterator, tbl, nil
|
||||
end
|
||||
|
||||
mt.__newindex = function(tbl, k, v)
|
||||
if class.properties.consts[k] and not inConstructor then
|
||||
error("cannot modify const '"..tostring(k).."'", 2)
|
||||
end
|
||||
if tbl ~= privObj and class.properties.private[k] then
|
||||
error("cannot modify private property '"..tostring(k).."' outside of class", 2)
|
||||
end
|
||||
if class.properties.types[k] then
|
||||
local stat,err = typeRestriction(k, class.properties.types[k], v)
|
||||
if not stat then
|
||||
error(err, 2)
|
||||
end
|
||||
end
|
||||
if class.properties.static[k] then
|
||||
-- change in whole class
|
||||
class.static[k] = v
|
||||
elseif class.properties.private[k] then
|
||||
privProperties[k] = v
|
||||
else
|
||||
properties[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
local mt2 = {}
|
||||
|
||||
for k,v in pairs(mt) do
|
||||
mt2[k] = v
|
||||
end
|
||||
|
||||
for k,v in pairs(class.metatable.public) do
|
||||
mt[k] = function(...)
|
||||
local tEnv = {self=privObj}
|
||||
oop.injectEnv(tEnv)
|
||||
setmetatable(tEnv, {__index=env})
|
||||
setfenv(v, tEnv)
|
||||
return v(sanitizeArgs(...))
|
||||
end
|
||||
end
|
||||
|
||||
for k,v in pairs(class.metatable.private) do
|
||||
mt2[k] = function(...)
|
||||
local tEnv = {self=privObj}
|
||||
oop.injectEnv(tEnv)
|
||||
setmetatable(tEnv, {__index=env})
|
||||
setfenv(v, tEnv)
|
||||
return v(sanitizeArgs(...))
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(obj, mt)
|
||||
setmetatable(privObj, mt2)
|
||||
|
||||
local constructors = {class.constructor}
|
||||
local cls = class
|
||||
while cls.parent do
|
||||
cls = cls.parent
|
||||
if cls.constructor then
|
||||
table.insert(constructors, 1, cls.constructor)
|
||||
end
|
||||
end
|
||||
for t=1,#constructors do
|
||||
inConstructor = true
|
||||
local tEnv = {self=privCache[obj] or obj}
|
||||
oop.injectEnv(tEnv)
|
||||
setmetatable(tEnv, {__index=env})
|
||||
setfenv(constructors[t], tEnv)
|
||||
local status,tObj = pcall(constructors[t],sanitizeArgs(...))
|
||||
if not status then
|
||||
error(tObj, 2)
|
||||
end
|
||||
if tObj == false then
|
||||
return false
|
||||
elseif tObj then
|
||||
obj = publicCache[tObj] or tObj
|
||||
end
|
||||
inConstructor = false
|
||||
end
|
||||
|
||||
objectCache[obj] = class
|
||||
objectCache[privObj] = class
|
||||
|
||||
for k,v in pairs(privObj) do
|
||||
if type(v) == "table" and v == class.private[k] then
|
||||
privObj[k] = instantiate(v)
|
||||
end
|
||||
end
|
||||
|
||||
return obj
|
||||
end,
|
||||
}
|
||||
|
||||
local iClass
|
||||
if inherit then
|
||||
iClass = classCache[inherit]
|
||||
class.parent = iClass
|
||||
setmetatable(class.static, {__index=iClass.static})
|
||||
setmetatable(class.public, {
|
||||
__index = function(tbl, key)
|
||||
if iClass.public[key] ~= nil then
|
||||
return iClass.public[key]
|
||||
else
|
||||
return class.static[key]
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
setmetatable(class.private, {
|
||||
__index = function(tbl, key)
|
||||
if iClass.private[key] ~= nil then
|
||||
return iClass.private[key]
|
||||
else
|
||||
return class.public[key]
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
for k,v in pairs(class.properties) do
|
||||
setmetatable(v, {__index=iClass.properties[k]})
|
||||
end
|
||||
|
||||
setmetatable(class, {__index=iClass})
|
||||
else
|
||||
setmetatable(class.public, {__index=class.static})
|
||||
setmetatable(class.private, {__index=class.public})
|
||||
end
|
||||
|
||||
loopThrough = {"static","private","public"}
|
||||
for i,l in ipairs(loopThrough) do
|
||||
if classTbl[l] then
|
||||
for k,v in pairs(classTbl[l]) do
|
||||
if type(k) == "number" then
|
||||
if type(v) == "table" and v.name then
|
||||
if v.const then
|
||||
class.properties.consts[v.name] = true
|
||||
end
|
||||
if v.type then
|
||||
class.properties.types[v.name] = v.type
|
||||
end
|
||||
if v.value or v.type then
|
||||
class[l][v.name] = v.value or default[v.type]
|
||||
end
|
||||
class.properties[l][v.name] = true -- now values can be generic typed starting with nil but still recognized
|
||||
elseif type(v) == "string" then
|
||||
class.properties[l][v] = true
|
||||
end
|
||||
elseif type(k) == "string" then
|
||||
if l == "public" and k == name then -- constructor
|
||||
if type(v) ~= "function" then
|
||||
error("invalid constructor: expected function, got "..type(v),2)
|
||||
end
|
||||
class.constructor = v
|
||||
elseif metamethods[k] then
|
||||
class.metatable[l][k] = v
|
||||
else
|
||||
class[l][k] = v
|
||||
class.properties[l][k] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local classObj = {}
|
||||
|
||||
classCache[classObj] = class
|
||||
class.obj = classObj
|
||||
|
||||
setmetatable(classObj, class.metatable.static)
|
||||
|
||||
env[name] = classObj
|
||||
end
|
||||
|
||||
function oop.class(name)
|
||||
return function(class)
|
||||
if classCache[class] then -- a class object was passed meaning we're gonna inherit
|
||||
return function(realclass)
|
||||
makeClass(name, realclass, class)
|
||||
end
|
||||
else
|
||||
makeClass(name, class)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local oType = type
|
||||
function oop.type(value, numberType)
|
||||
if oType(value) == "table" then
|
||||
if objectCache[value] then
|
||||
return objectCache[value].name
|
||||
elseif classCache[value] then
|
||||
return "class"
|
||||
else
|
||||
return "table"
|
||||
end
|
||||
elseif numberType and oType(value) == "number" then
|
||||
return getNumberType(value)
|
||||
else
|
||||
return oType(value)
|
||||
end
|
||||
end
|
||||
|
||||
function oop.getClassName(class)
|
||||
oop.expect(1, class, "class")
|
||||
return classCache[class].name
|
||||
end
|
||||
|
||||
function oop.isType(value, ...)
|
||||
local types = {oop.type(value), oType(value), oop.type(value, true)}
|
||||
if types[1] ~= types[2] and types[3] ~= "class" then
|
||||
types[3] = "object"
|
||||
end
|
||||
local allowedTypes = {...}
|
||||
for i,t in ipairs(types) do
|
||||
for i=1, #allowedTypes do
|
||||
if allowedTypes[i] == t or (allowedTypes[i] == "double" and t == "number") then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function oop.expect(index, value, ...)
|
||||
local level = 3
|
||||
local allowedTypes = {...}
|
||||
if type(allowedTypes[1]) == "number" then
|
||||
level = allowedTypes[1]
|
||||
table.remove(allowedTypes, 1)
|
||||
end
|
||||
if type(allowedTypes[1]) ~= "string" then
|
||||
error("bad argument #3: expected string", 2)
|
||||
end
|
||||
if oop.isType(value, ...) then
|
||||
return value
|
||||
end
|
||||
|
||||
local expectlist
|
||||
local numbertype = false
|
||||
for t=1,#allowedTypes do
|
||||
if allowedTypes[t] == "int" then
|
||||
numbertype = true
|
||||
end
|
||||
end
|
||||
if #allowedTypes > 1 then
|
||||
local lastType = allowedTypes[#allowedTypes]
|
||||
allowedTypes[#allowedTypes] = nil
|
||||
expectlist = table.concat(allowedTypes, ", ").." or "..lastType
|
||||
else
|
||||
expectlist = allowedTypes[1]
|
||||
end
|
||||
local t = oop.type(value, numbertype)
|
||||
|
||||
error("bad argument #"..index..": expected "..expectlist.." got "..t.." ("..tostring(value)..")", level)
|
||||
end
|
||||
|
||||
function oop.getPublicObject(privateObject)
|
||||
return publicCache[privateObject] or privateObject
|
||||
end
|
||||
|
||||
function oop.import(filepath)
|
||||
oop.expect(1, filepath, "string")
|
||||
|
||||
local makePackage = require("cc.require")
|
||||
local tEnv = setmetatable({shell=shell, multishell=multishell},{__index=env})
|
||||
tEnv.require, tEnv.package = makePackage.make(tEnv, dir)
|
||||
tEnv.oop = oop
|
||||
|
||||
oop.injectEnv(tEnv)
|
||||
|
||||
local pathlog = filepath
|
||||
local filepath2 = filepath..".lua"
|
||||
pathlog = pathlog.."\n"..filepath2
|
||||
|
||||
if filepath:sub(1,1) ~= "/" then
|
||||
pathlog = pathlog.."\n"..fs.combine(dir, filepath)
|
||||
pathlog = pathlog.."\n"..fs.combine(dir, filepath2)
|
||||
if fs.exists(fs.combine(dir, filepath)) then
|
||||
filepath = fs.combine(dir, filepath)
|
||||
elseif fs.exists(fs.combine(dir, filepath2)) then
|
||||
filepath = fs.combine(dir, filepath2)
|
||||
end
|
||||
end
|
||||
|
||||
if fs.exists(filepath2) and not fs.exists(filepath) then
|
||||
filepath = filepath2
|
||||
end
|
||||
|
||||
if not fs.exists(filepath) then
|
||||
error("Could not find file:"..pathlog,2)
|
||||
end
|
||||
|
||||
local f = fread(filepath)
|
||||
|
||||
local func, err = load(f, "@"..filepath, nil, tEnv)
|
||||
|
||||
if not func then
|
||||
error(err, 2)
|
||||
else
|
||||
local ok,err = pcall(func)
|
||||
if not ok then
|
||||
error(err, 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return oop
|
||||
723
Program_Files/LevelOS/CMD/latch.lua
Normal file
723
Program_Files/LevelOS/CMD/latch.lua
Normal file
@ -0,0 +1,723 @@
|
||||
local tokens = {
|
||||
whitespace = {
|
||||
["\t"] = true,
|
||||
[" "] = true,
|
||||
["\n"] = true,
|
||||
[","] = true,
|
||||
},
|
||||
|
||||
line = {
|
||||
["\n"] = true,
|
||||
[","] = true,
|
||||
},
|
||||
|
||||
label = {
|
||||
[":"] = true,
|
||||
},
|
||||
|
||||
indexVar = {
|
||||
["%"] = true,
|
||||
},
|
||||
|
||||
operator = {},
|
||||
op = {
|
||||
add = {
|
||||
["+"] = true,
|
||||
},
|
||||
subtract = {
|
||||
["-"] = true,
|
||||
},
|
||||
multiply = {
|
||||
["*"] = true,
|
||||
},
|
||||
modulo = {
|
||||
["%"] = true,
|
||||
},
|
||||
power = {
|
||||
["^"] = true,
|
||||
},
|
||||
divide = {
|
||||
["/"] = true,
|
||||
},
|
||||
},
|
||||
|
||||
assign = {
|
||||
["="] = true,
|
||||
},
|
||||
|
||||
comparison = {},
|
||||
comp = {
|
||||
equals = {
|
||||
["=="] = true,
|
||||
},
|
||||
notEquals = {
|
||||
["~="] = true,
|
||||
},
|
||||
bigger = {
|
||||
[">"] = true,
|
||||
},
|
||||
biggerOrEquals = {
|
||||
[">="] = true,
|
||||
},
|
||||
smaller = {
|
||||
["<"] = true,
|
||||
},
|
||||
smallerOrEquals = {
|
||||
["<="] = true,
|
||||
},
|
||||
},
|
||||
|
||||
logic = {},
|
||||
logicAnd = {
|
||||
["and"] = true,
|
||||
["&&"] = true,
|
||||
},
|
||||
logicOr = {
|
||||
["or"] = true,
|
||||
["||"] = true,
|
||||
},
|
||||
logicNot = {
|
||||
["not"] = true,
|
||||
["!"] = true,
|
||||
},
|
||||
|
||||
keyword = {},
|
||||
ifStatement = {
|
||||
["if"] = true,
|
||||
},
|
||||
whileStatement = {
|
||||
["while"] = true,
|
||||
},
|
||||
forStatement = {
|
||||
["for"] = true,
|
||||
},
|
||||
elseStatement = {
|
||||
["else"] = true,
|
||||
},
|
||||
localStatement = {
|
||||
["local"] = true,
|
||||
},
|
||||
eof = {
|
||||
["end"] = true,
|
||||
["exit"] = true,
|
||||
},
|
||||
|
||||
boolean = {},
|
||||
boolTrue = {
|
||||
["true"] = true,
|
||||
},
|
||||
boolFalse = {
|
||||
["false"] = true,
|
||||
},
|
||||
|
||||
ident = {
|
||||
["_"] = true,
|
||||
},
|
||||
digits = {
|
||||
},
|
||||
|
||||
string = {
|
||||
["\""] = true,
|
||||
["'"] = true,
|
||||
},
|
||||
|
||||
symbol = {
|
||||
["("] = true,
|
||||
[")"] = true,
|
||||
},
|
||||
|
||||
escape = {
|
||||
["\\"] = true,
|
||||
}
|
||||
}
|
||||
|
||||
for c=("a"):byte(), ("z"):byte() do
|
||||
tokens.ident[string.char(c)] = true
|
||||
tokens.ident[string.char(c):upper()] = true
|
||||
end
|
||||
|
||||
for c=("0"):byte(), ("9"):byte() do
|
||||
tokens.ident[string.char(c)] = true
|
||||
tokens.digits[string.char(c)] = true
|
||||
end
|
||||
|
||||
local function addTo(root, ...)
|
||||
if not root then error("invalid argument #1: expected table, got nil",2) end
|
||||
local tbls = {...}
|
||||
for i,t in ipairs(tbls) do
|
||||
for k,v in pairs(t) do
|
||||
root[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k,v in pairs(tokens.comp) do
|
||||
addTo(tokens.comparison, v)
|
||||
end
|
||||
|
||||
for k,v in pairs(tokens.op) do
|
||||
addTo(tokens.operator, v)
|
||||
end
|
||||
|
||||
addTo(tokens.logic, tokens.logicAnd, tokens.logicOr, tokens.logicNot)
|
||||
|
||||
addTo(tokens.keyword, tokens.logic, tokens.ifStatement, tokens.whileStatement, tokens.forStatement, tokens.elseStatement, tokens.localStatement, tokens.eof)
|
||||
|
||||
addTo(tokens.boolean, tokens.boolTrue, tokens.boolFalse)
|
||||
|
||||
local statementValues = {
|
||||
["string"] = true,
|
||||
["number"] = true,
|
||||
["variable"] = true,
|
||||
["arg"] = true,
|
||||
["value"] = true,
|
||||
}
|
||||
|
||||
local validVarTypes = {
|
||||
["function"] = true,
|
||||
["arg"] = true,
|
||||
["variable"] = true,
|
||||
["escape"] = true,
|
||||
}
|
||||
|
||||
local function lex(text)
|
||||
local char = 1
|
||||
local function get(p)
|
||||
local tPos = p or char
|
||||
return text:sub(tPos,tPos)
|
||||
end
|
||||
local beginline = true
|
||||
local inStatement = false
|
||||
local isLabel = false
|
||||
local data = {{}}
|
||||
local line = data[1]
|
||||
local posOffset = 0
|
||||
|
||||
local function newline()
|
||||
posOffset = char
|
||||
table.insert(data,{})
|
||||
line = data[#data]
|
||||
end
|
||||
|
||||
local function addData(txt,type)
|
||||
if not txt then error("no txt",2) end
|
||||
if line[#line] and line[#line].type == type then
|
||||
line[#line].data = line[#line].data..txt
|
||||
line[#line].posLast = line[#line].posLast+#txt
|
||||
else
|
||||
table.insert(line,{data=txt,posFirst=(char-posOffset),posLast=(char-posOffset)+(#txt-1),type=type})
|
||||
end
|
||||
end
|
||||
|
||||
local function readWhitespace(acceptNewline)
|
||||
local txt = get()
|
||||
local oldchar = char
|
||||
while tokens.whitespace[txt] and (acceptNewline or not tokens.line[txt]) do
|
||||
char = char + 1
|
||||
addData(txt,"whitespace")
|
||||
isLabel = false
|
||||
txt = get()
|
||||
end
|
||||
if oldchar == char then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
while char <= #text do
|
||||
local txt = get()
|
||||
if tokens.whitespace[txt] and not tokens.line[txt] then
|
||||
addData(txt,"whitespace")
|
||||
isLabel = false
|
||||
|
||||
elseif tokens.escape[txt] then
|
||||
addData(txt..text:sub(char+1,char+1),"escape")
|
||||
char = char+1
|
||||
if tokens.whitespace[get(char+1)] then
|
||||
isLabel = false
|
||||
beginline = false
|
||||
end
|
||||
|
||||
elseif tokens.string[txt] then
|
||||
local bchar = txt
|
||||
local echar = bchar
|
||||
local stype = "string"
|
||||
if isLabel then
|
||||
stype = "label"
|
||||
elseif beginline then
|
||||
stype = "function"
|
||||
end
|
||||
isLabel = false
|
||||
beginline = false
|
||||
addData(txt,stype)
|
||||
char = char+1
|
||||
while char <= #text do
|
||||
local c = text:sub(char,char)
|
||||
if tokens.escape[c] then
|
||||
addData(c..get(char+1),"escape")
|
||||
char = char+1
|
||||
if tokens.digits[get()] then
|
||||
char = char+1
|
||||
for i=1,2 do
|
||||
if tokens.digits[get()] then
|
||||
addData(get(),"escape")
|
||||
char = char+1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
char = char+1
|
||||
end
|
||||
elseif tokens.indexVar[c] then
|
||||
local b2,e2 = text:find("^%%[A-Za-z0-9_]+%%", char)
|
||||
if b2 then
|
||||
addData(text:sub(b2,e2), "variable")
|
||||
char = e2
|
||||
else
|
||||
local b3,e3 = text:find("^%%[0-9]+", char)
|
||||
if not b3 then
|
||||
b3,e3 = text:find("^%%~[0-9]+", char)
|
||||
end
|
||||
if b3 then
|
||||
addData(text:sub(b3,e3), "arg")
|
||||
char = e3
|
||||
else
|
||||
addData(c, stype)
|
||||
end
|
||||
end
|
||||
char = char+1
|
||||
elseif c == echar then
|
||||
addData(c, stype)
|
||||
break
|
||||
else
|
||||
if c == "\n" then
|
||||
newline()
|
||||
else
|
||||
addData(c, stype)
|
||||
end
|
||||
char = char+1
|
||||
end
|
||||
end
|
||||
|
||||
elseif tokens.indexVar[txt] then
|
||||
if inStatement == 1 and line[#line] and line[#line].type == "whitespace" and line[#line-1] and statementValues[line[#line-1].type] then
|
||||
inStatement = false
|
||||
beginline = true
|
||||
end
|
||||
local b2,e2 = text:find("^%%[A-Za-z0-9_]+%%", char)
|
||||
if b2 then
|
||||
if isLabel and beginline then
|
||||
addData(text:sub(b2,e2), "unidentified")
|
||||
else
|
||||
addData(text:sub(b2,e2), "variable")
|
||||
end
|
||||
char = e2
|
||||
else
|
||||
local b3,e3 = text:find("^%%[0-9]+", char)
|
||||
if not b3 then
|
||||
b3,e3 = text:find("^%%~[0-9]+", char)
|
||||
end
|
||||
if b3 then
|
||||
if isLabel and beginline then
|
||||
addData(text:sub(b3,e3), "unidentified")
|
||||
else
|
||||
addData(text:sub(b3,e3), "arg")
|
||||
end
|
||||
char = e3
|
||||
elseif isLabel then
|
||||
addData(txt, "label")
|
||||
elseif beginline then
|
||||
addData(txt, "function")
|
||||
elseif not inStatement then
|
||||
addData(txt, "string")
|
||||
elseif tokens.operator[txt] then
|
||||
addData(txt, "operator")
|
||||
else
|
||||
addData(txt, "unidentified")
|
||||
end
|
||||
end
|
||||
if tokens.whitespace[get(char+1)] then
|
||||
beginline = false
|
||||
end
|
||||
|
||||
elseif tokens.ident[txt] or (not inStatement and not (tokens.line[txt] or tokens.label[txt] or tokens.assign[txt] or tokens.symbol[txt])) then
|
||||
local b,e
|
||||
if inStatement then
|
||||
b,e = text:find("^[A-Za-z0-9_.]+", char)
|
||||
else
|
||||
b,e = char,char+1
|
||||
local c = get(e)
|
||||
while e <= #text and not (tokens.line[c] or tokens.label[c] or tokens.assign[c] or tokens.indexVar[c] or tokens.whitespace[c] or tokens.symbol[c] or tokens.escape[c]) do
|
||||
e = e + 1
|
||||
c = get(e)
|
||||
end
|
||||
e = e - 1
|
||||
end
|
||||
local token = text:sub(b,e)
|
||||
local ltoken = token:lower()
|
||||
local statementValue = false
|
||||
if inStatement then
|
||||
if line[#line] and line[#line].type == "whitespace" and line[#line-1] and statementValues[line[#line-1].type] then
|
||||
if inStatement == 1 then
|
||||
inStatement = 0
|
||||
beginline = true
|
||||
end
|
||||
statementValue = true
|
||||
end
|
||||
end
|
||||
char = e
|
||||
if isLabel then
|
||||
addData(token, "label")
|
||||
if tokens.whitespace[get(char+1)] then
|
||||
isLabel = false
|
||||
beginline = false
|
||||
end
|
||||
|
||||
elseif tokens.localStatement[ltoken] and not inStatement then
|
||||
if not beginline then
|
||||
addData(token, "string")
|
||||
else
|
||||
addData(token, "keyword")
|
||||
end
|
||||
|
||||
elseif tokens.eof[ltoken] and (inStatement == 0 or not inStatement) then
|
||||
addData(token, "keyword")
|
||||
|
||||
elseif (tokens.ifStatement[ltoken] or tokens.whileStatement[ltoken]) and (inStatement == 0 or not inStatement) then
|
||||
addData(token, "keyword")
|
||||
inStatement = 1
|
||||
|
||||
elseif (tokens.elseStatement[ltoken] or tokens.eof[ltoken]) and (inStatement == 0 or not inStatement) then
|
||||
addData(token, "keyword")
|
||||
|
||||
elseif (tokens.logicAnd[ltoken] or tokens.logicOr[ltoken]) and statementValue then
|
||||
addData(token, "logic")
|
||||
if inStatement == 0 then
|
||||
inStatement = 1
|
||||
end
|
||||
|
||||
elseif tokens.logicNot[ltoken] and inStatement and not statementValue then
|
||||
addData(token, "logic")
|
||||
if inStatement == 0 then
|
||||
inStatement = 1
|
||||
end
|
||||
|
||||
elseif tokens.forStatement[ltoken] and (inStatement == 0 or not inStatement) then
|
||||
-- other handling
|
||||
|
||||
elseif tokens.boolean[ltoken] and inStatement and not statementValue then
|
||||
addData(token, "value")
|
||||
|
||||
elseif beginline and (inStatement == 0 or not inStatement) then
|
||||
addData(token, "function")
|
||||
if tokens.whitespace[get(char+1)] then
|
||||
beginline = false
|
||||
end
|
||||
|
||||
elseif tonumber(token) then
|
||||
addData(token, "number")
|
||||
if tokens.whitespace[get(char+1)] then
|
||||
beginline = false
|
||||
end
|
||||
|
||||
else
|
||||
addData(token, "string")
|
||||
|
||||
end
|
||||
if inStatement == 0 then
|
||||
inStatement = false
|
||||
end
|
||||
|
||||
elseif tokens.label[txt] then
|
||||
if char+1 > #text or tokens.whitespace[get(char+1)] then
|
||||
addData(txt, "string")
|
||||
else
|
||||
addData(txt, "label")
|
||||
isLabel = true
|
||||
end
|
||||
|
||||
elseif tokens.line[txt] then
|
||||
beginline = true
|
||||
inStatement = false
|
||||
if txt ~= "\n" then
|
||||
addData(txt, "symbol")
|
||||
end
|
||||
|
||||
elseif tokens.symbol[txt] then
|
||||
addData(txt, "symbol")
|
||||
|
||||
elseif txt:find("%p") then
|
||||
local b,e = text:find("^%p+", char)
|
||||
local token = text:sub(b,e)
|
||||
char = e
|
||||
if inStatement then
|
||||
if tokens.operator[token] then
|
||||
addData(token, "operator")
|
||||
elseif tokens.comparison[token] then
|
||||
addData(token, "comparison")
|
||||
elseif tokens.logic[token] then
|
||||
addData(token, "logic")
|
||||
else
|
||||
addData(token, "string")
|
||||
end
|
||||
else
|
||||
if tokens.assign[token] then
|
||||
local v = line[#line]
|
||||
if v and v.type == "whitespace" then
|
||||
v = line[#line-1]
|
||||
end
|
||||
if v and (validVarTypes[v.type]) then
|
||||
local it = #line-1
|
||||
while v and (validVarTypes[v.type]) do
|
||||
if v.type == "function" then
|
||||
v.type = "variable"
|
||||
end
|
||||
it = it-1
|
||||
v = line[it]
|
||||
end
|
||||
addData(token, "assign")
|
||||
inStatement = true
|
||||
elseif beginline then
|
||||
addData(token, "unidentified")
|
||||
else
|
||||
addData(token, "string")
|
||||
end
|
||||
elseif beginline then
|
||||
addData(token, "unidentified")
|
||||
else
|
||||
addData(token, "string")
|
||||
end
|
||||
end
|
||||
|
||||
elseif txt ~= "\n" then
|
||||
addData(txt, "unidentified")
|
||||
end
|
||||
if txt == "\n" then
|
||||
newline()
|
||||
end
|
||||
char = char+1
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
local function parse(data, filename)
|
||||
filename = filename or "latch"
|
||||
if type(data) == "string" then
|
||||
data = lex(data)
|
||||
end
|
||||
|
||||
local function err(lineNum, txt, txtafter)
|
||||
local err = filename..": "..txt.." on line "..lineNum
|
||||
if txtafter then
|
||||
err = err.." ("..txtafter..")"
|
||||
end
|
||||
error(err, 0)
|
||||
end
|
||||
|
||||
local function unexpectedToken(line, token, ...)
|
||||
_G.debugtoken = token
|
||||
local exp = {...}
|
||||
local expstr
|
||||
if #exp > 0 then
|
||||
expstr = "expected "..table.concat(exp, ", ")
|
||||
end
|
||||
err(line, "unexpected token '"..tostring(token.data).."' ("..tostring(token.type)..")", expstr)
|
||||
end
|
||||
|
||||
local function locateEntry(tbl, value)
|
||||
for k,v in pairs(tbl) do
|
||||
if v == value then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function parseToken(line, i, allowed, stopAt)
|
||||
local token = line[i]
|
||||
local data = {}
|
||||
|
||||
stopAt = stopAt or {"whitespace"}
|
||||
|
||||
while true do
|
||||
if locateEntry(allowed, token.type) then
|
||||
if token.type == "number" then
|
||||
table.insert(data, {type="number", data=token.data})
|
||||
elseif token.type == "operator" then
|
||||
table.insert(data, {type="operator", data=token.data})
|
||||
elseif token.type == "variable" and token.data:sub(1,1) == "%" then
|
||||
table.insert(data, {type="variable", data=token.data:sub(2,#token.data-1)})
|
||||
elseif token.type == "variable" then
|
||||
table.insert(data, {type="string", data=token.data})
|
||||
elseif token.type == "arg" then
|
||||
table.insert(data, {type="argument", data=token.data:sub(2)})
|
||||
elseif token.type == "label" then
|
||||
if tokens.string[token.data:sub(2,2)] then
|
||||
table.insert(data, {type="label", data=token.data:sub(2):gsub(token.data:sub(2,2),"")})
|
||||
else
|
||||
table.insert(data, {type="label", data=token.data:sub(2)})
|
||||
end
|
||||
elseif tokens.string[token.data:sub(1,1)] then
|
||||
table.insert(data, {type="string", data=token.data:gsub(token.data:sub(1,1),"")})
|
||||
else
|
||||
table.insert(data, {type="string", data=token.data})
|
||||
end
|
||||
elseif locateEntry(stopAt, token.type) then
|
||||
i = i - 1
|
||||
break
|
||||
else
|
||||
local expected = {}
|
||||
addTo(expected, stopAt)
|
||||
addTo(expected, allowed)
|
||||
unexpectedToken(ln, token, unpack(expected))
|
||||
end
|
||||
i = i + 1
|
||||
token = line[i]
|
||||
if not token then break end
|
||||
end
|
||||
|
||||
return data, i
|
||||
end
|
||||
|
||||
local function parseExpression(line, i, whitespaceConcat) -- this is all wrong FUCK, value (x+5) > comparison (x+5 == 8) > expression(x+5 == 8 and %potato%)
|
||||
-- expression structure
|
||||
local token = line[i]
|
||||
local conditions = {
|
||||
{
|
||||
{} -- current condition (value)
|
||||
-- more AND conditions
|
||||
}
|
||||
-- more OR conditions
|
||||
}
|
||||
local condition = conditions[1][1]
|
||||
local isValid = false
|
||||
while true do
|
||||
token = line[i]
|
||||
if not token then break end
|
||||
if token.type == "whitespace" then -- optional token
|
||||
elseif token.type == "logic" and tokens.logicNot[token.data] then -- optional token
|
||||
table.insert(condition, token)
|
||||
isValid = false
|
||||
elseif statementValues[token.type] then -- REQUIRED token, expression is invalid without it
|
||||
table.insert(condition, token)
|
||||
isValid = true
|
||||
i = i + 1
|
||||
token = line[i]
|
||||
if not token then break end
|
||||
if token.type == "whitespace" then
|
||||
i = i + 1
|
||||
token = line[i]
|
||||
end
|
||||
if not token then break end
|
||||
if token.type == "logic" and tokens.logicAnd[token.data] then
|
||||
condition = {}
|
||||
table.insert(conditions[#conditions], condition)
|
||||
isValid = false
|
||||
elseif token.type == "logic" and tokens.logicOr[token.data] then
|
||||
condition = {}
|
||||
table.insert(conditions, {})
|
||||
table.insert(conditions[#conditions], condition)
|
||||
isValid = false
|
||||
elseif token.type == "operator" then
|
||||
table.insert(condition, token)
|
||||
elseif whitespaceConcat then
|
||||
i = i - 1
|
||||
else
|
||||
i = i - 1
|
||||
break -- end of statement
|
||||
end
|
||||
else
|
||||
unexpectedToken(i, token, "expression")
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
if not isValid then
|
||||
err(i, "invalid statement")
|
||||
else
|
||||
return conditions, i
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local program = {
|
||||
arguments = {},
|
||||
env = {},
|
||||
commands = {},
|
||||
labels = {},
|
||||
code = {},
|
||||
}
|
||||
local scope = program.code
|
||||
for ln,line in ipairs(data) do
|
||||
local token
|
||||
local i = 1
|
||||
local beginline = true
|
||||
local function nextToken(includeWhitespace)
|
||||
if line[i+1] and (includeWhitespace or line[i+1].type ~= "whitespace") then
|
||||
return line[i+1]
|
||||
elseif line[i+2] then
|
||||
return line[i+2]
|
||||
end
|
||||
end
|
||||
local function nextTokenType(includeWhitespace)
|
||||
local nt = nextToken(includeWhitespace)
|
||||
if nt then
|
||||
return nt.type
|
||||
end
|
||||
end
|
||||
while i <= #line do
|
||||
token = line[i]
|
||||
if beginline then
|
||||
if token.type == "function" or token.type == "variable" or token.type == "arg" then
|
||||
local data
|
||||
data, i = parseToken(line, i, {"function", "variable", "arg", "escape"}, {"whitespace", "symbol", "assign"})
|
||||
local l
|
||||
if nextTokenType() == "assign" then
|
||||
l = {type="assign", data=data, value={}}
|
||||
while nextTokenType() == "assign" do
|
||||
i = i + 1
|
||||
end
|
||||
i = i + 1
|
||||
l.value, i = parseExpression(line, i, true)
|
||||
else
|
||||
l = {type="command", data=data, line=ln, params={}}
|
||||
beginline = false
|
||||
end
|
||||
table.insert(scope, l)
|
||||
|
||||
elseif token.type == "label" then
|
||||
program.labels[token.data] = {scope=scope, commandNum=#scope+1}
|
||||
|
||||
elseif token.type ~= "whitespace" then
|
||||
--unexpectedToken(ln, token, "whitespace", "function", "variable", "arg")
|
||||
end
|
||||
|
||||
else
|
||||
if token.type == "label" then
|
||||
if scope[#scope].type == "command" then
|
||||
local data
|
||||
data, i = parseToken(line, i, {"label", "variable", "arg", "escape"}, {"whitespace", "symbol"})
|
||||
table.insert(scope[#scope].params, data)
|
||||
else
|
||||
unexpectedToken(ln, token)
|
||||
end
|
||||
|
||||
elseif token.type == "string" or token.type == "number" then
|
||||
if scope[#scope].type == "command" then
|
||||
local data
|
||||
data, i = parseToken(line, i, {"string", "number", "variable", "arg", "escape"}, {"whitespace", "symbol"})
|
||||
table.insert(scope[#scope].params, data)
|
||||
end
|
||||
|
||||
elseif token.type ~= "whitespace" then
|
||||
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return program
|
||||
end
|
||||
|
||||
return {lex=lex,parse=parse}
|
||||
1
Program_Files/LevelOS/Cloud/icon.limg
Normal file
1
Program_Files/LevelOS/Cloud/icon.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," b ","b ",},{"","bb9"," 9 ",},{""," "," ",},},}
|
||||
1493
Program_Files/LevelOS/Cloud/main.lua
Normal file
1493
Program_Files/LevelOS/Cloud/main.lua
Normal file
File diff suppressed because it is too large
Load Diff
1
Program_Files/LevelOS/Cloud/taskbar.limg
Normal file
1
Program_Files/LevelOS/Cloud/taskbar.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," 0","00 ",},{"","000"," ",},},}
|
||||
1
Program_Files/LevelOS/Explorer/icon.limg
Normal file
1
Program_Files/LevelOS/Explorer/icon.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{"","1 ","444",},{"","499","944",},{""," "," ",},},}
|
||||
3685
Program_Files/LevelOS/Explorer/main.lua
Normal file
3685
Program_Files/LevelOS/Explorer/main.lua
Normal file
File diff suppressed because it is too large
Load Diff
1
Program_Files/LevelOS/Explorer/taskbar.limg
Normal file
1
Program_Files/LevelOS/Explorer/taskbar.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," 0","00 ",},{"
","000"," ",},},}
|
||||
1
Program_Files/LevelOS/Lua/icon.limg
Normal file
1
Program_Files/LevelOS/Lua/icon.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," b","bb ",},{""," 0b","bb ",},{"","bb "," ",},},}
|
||||
172
Program_Files/LevelOS/Lua/main.lua
Normal file
172
Program_Files/LevelOS/Lua/main.lua
Normal file
@ -0,0 +1,172 @@
|
||||
local tArgs = {...}
|
||||
if type(tArgs[1]) == "string" and fs.exists(tArgs[1]) then
|
||||
lOS.execute(table.concat(tArgs," "))
|
||||
return
|
||||
end
|
||||
if LevelOS then LevelOS.self.window.icon = {"\3","b"} end
|
||||
local lex = "LevelOS/modules/lex.lua"
|
||||
local docs = "Program_Files/Slime_Text/highlight/lua/docs.json"
|
||||
local docstable
|
||||
if not fs.exists(lex) then
|
||||
-- oh no
|
||||
end
|
||||
if not fs.exists(docs) then
|
||||
local webres = http.get("http://tweaked.cc/index.json")
|
||||
if webres then
|
||||
docstable = textutils.unserializeJSON(webres.readAll())
|
||||
end
|
||||
--[[if webres then
|
||||
lUtils.fwrite(docs,webres.readAll())
|
||||
end]]
|
||||
end
|
||||
if fs.exists(docs) then
|
||||
docstable = textutils.unserializeJSON(lUtils.fread(docs))
|
||||
end
|
||||
local pretty = require "cc.pretty"
|
||||
|
||||
local tCommandHistory = {}
|
||||
local hCur = 0
|
||||
local bRunning = true
|
||||
local tEnv = {
|
||||
["exit"] = setmetatable({}, {
|
||||
__tostring = function() return "Call exit() to exit." end,
|
||||
__call = function() bRunning = false end,
|
||||
__type = "function",
|
||||
}),
|
||||
["_echo"] = function(...)
|
||||
return ...
|
||||
end,
|
||||
}
|
||||
setmetatable(tEnv, { __index = _ENV })
|
||||
term.setTextColor(colors.yellow)
|
||||
print("LevelOS interactive Lua prompt.\nCall exit() to exit.")
|
||||
term.setTextColor(colors.white)
|
||||
while bRunning do
|
||||
hCur = #tCommandHistory+1
|
||||
write("lua> ")
|
||||
local w,h = term.getSize()
|
||||
local x,y = term.getCursorPos()
|
||||
local self = lUtils.input(x,y,w,y)
|
||||
self.opt.cursorColor = colors.white
|
||||
self.opt.overflowY = "scroll"
|
||||
self.scrollY = 0
|
||||
self.opt.syntax = {
|
||||
type="lua",
|
||||
keyword=colors.yellow,
|
||||
comment=colors.green,
|
||||
string=colors.red,
|
||||
number=colors.purple,
|
||||
symbol=colors.white,
|
||||
operator=colors.lightGray,
|
||||
value=colors.purple,
|
||||
ident=colors.white,
|
||||
["function"]=colors.cyan,
|
||||
nfunction=colors.lime,
|
||||
arg=colors.orange,
|
||||
lexer=lex,
|
||||
whitespace=colors.lightGray,
|
||||
}
|
||||
self.opt.complete = {
|
||||
docs = docstable,
|
||||
env = tEnv,
|
||||
overlay = true,
|
||||
LevelOS = LevelOS,
|
||||
}
|
||||
self.opt.selectColor=colors.gray
|
||||
self.opt.overflowY="stretch"
|
||||
self.opt.overflowX="scroll"
|
||||
_G.debugeditor = self
|
||||
while true do
|
||||
tCommandHistory[hCur] = self.txt
|
||||
self.state = true
|
||||
local doUpdate = true
|
||||
local e = {os.pullEvent()}
|
||||
if e[1] == "term_resize" then
|
||||
local w,h = term.getSize()
|
||||
self.x2 = w
|
||||
elseif e[1] == "key" and (e[2] == keys.up or e[2] == keys.down) and not self.opt.complete.list then
|
||||
doUpdate = false
|
||||
local o = 1
|
||||
if e[2] == keys.up then
|
||||
o = -1
|
||||
end
|
||||
if tCommandHistory[hCur+o] then
|
||||
hCur = hCur+o
|
||||
self.txt = tCommandHistory[hCur]
|
||||
self.cursor.x = #self.txt+1
|
||||
self.cursor.a = #self.txt+1
|
||||
end
|
||||
self.update("term_resize")
|
||||
elseif e[1] == "key" and e[2] == keys.enter and not lUtils.isHolding(keys.leftShift) then
|
||||
if hCur < #tCommandHistory then
|
||||
hCur = #tCommandHistory
|
||||
tCommandHistory[hCur] = self.txt
|
||||
end
|
||||
doUpdate = false
|
||||
term.setCursorBlink(false)
|
||||
LevelOS.overlay = nil
|
||||
print("")
|
||||
local s = self.txt
|
||||
local nForcePrint = 0
|
||||
local func, e = load(s, "=lua", "t", tEnv)
|
||||
local func2 = load("return _echo(" .. s .. ");", "=lua", "t", tEnv)
|
||||
if not func then
|
||||
if func2 then
|
||||
func = func2
|
||||
e = nil
|
||||
nForcePrint = 1
|
||||
end
|
||||
else
|
||||
if func2 then
|
||||
func = func2
|
||||
end
|
||||
end
|
||||
|
||||
if func then
|
||||
local tResults = table.pack(pcall(func))
|
||||
if tResults[1] then
|
||||
local n = 1
|
||||
while n < tResults.n or n <= nForcePrint do
|
||||
local value = tResults[n + 1]
|
||||
local ok, serialised = pcall(pretty.pretty, value, {
|
||||
function_args = settings.get("lua.function_args"),
|
||||
function_source = settings.get("lua.function_source"),
|
||||
})
|
||||
if ok then
|
||||
pretty.print(serialised)
|
||||
else
|
||||
print(tostring(value))
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
else
|
||||
printError(tResults[2])
|
||||
end
|
||||
else
|
||||
printError(e)
|
||||
end
|
||||
break
|
||||
elseif e[1] == "key" or e[1] == "char" or e[1] == "paste" then
|
||||
if hCur < #tCommandHistory then
|
||||
hCur = #tCommandHistory
|
||||
tCommandHistory[hCur] = self.txt
|
||||
end
|
||||
end
|
||||
if doUpdate then
|
||||
self.update(unpack(e))
|
||||
end
|
||||
local w,h = term.getSize()
|
||||
while self.y2 > h do
|
||||
if self.y1 > 1 then
|
||||
term.scroll(1)
|
||||
self.y2 = self.y2-1
|
||||
self.y1 = self.y1-1
|
||||
else
|
||||
self.y1 = 1
|
||||
self.y2 = h
|
||||
self.opt.overflowY = "scroll"
|
||||
end
|
||||
end
|
||||
self.render()
|
||||
end
|
||||
end
|
||||
1
Program_Files/LevelOS/Lua/taskbar.limg
Normal file
1
Program_Files/LevelOS/Lua/taskbar.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," 00","0 ",},{"","000"," ",},},}
|
||||
1
Program_Files/LevelOS/Notepad/icon.limg
Normal file
1
Program_Files/LevelOS/Notepad/icon.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," ","77 ",},{"","888","77 ",},{"","778","88 ",},},}
|
||||
273
Program_Files/LevelOS/Notepad/main.lua
Normal file
273
Program_Files/LevelOS/Notepad/main.lua
Normal file
@ -0,0 +1,273 @@
|
||||
local tArgs = {...}
|
||||
local tFilepath = ""
|
||||
if tArgs[1] ~= nil then
|
||||
tFilepath = tArgs[1]
|
||||
end
|
||||
local isReadOnly = false
|
||||
if tArgs[2] ~= nil and tArgs[2] == "true" then
|
||||
isReadOnly = true
|
||||
end
|
||||
local tCol = {bg=colors.white,txt=colors.black,misc=colors.lightGray,misc2=colors.gray}
|
||||
local btns = {{"File",{{"New","New window","Open...","Save","Save as..."},"Print","Quit"}},{"Edit",{"Undo",{"Search","Replace"},{"Time"}}},{"View",{"Dark Mode"}}}
|
||||
local function topbar()
|
||||
local w,h = term.getSize()
|
||||
theline = ""
|
||||
for t=1,w-1 do
|
||||
theline = theline.."\131"
|
||||
end
|
||||
term.setCursorPos(1,1)
|
||||
term.setBackgroundColor(tCol.bg)
|
||||
term.setTextColor(tCol.misc)
|
||||
term.clearLine()
|
||||
term.setCursorPos(1,2)
|
||||
term.write(theline)
|
||||
term.setCursorPos(1,1)
|
||||
term.setTextColor(tCol.txt)
|
||||
for t=1,#btns do
|
||||
btns[t].x = ({term.getCursorPos()})[1]
|
||||
btns[t].w = string.len(btns[t][1])+2
|
||||
term.write(" "..btns[t][1].." ")
|
||||
end
|
||||
end
|
||||
local w,h = term.getSize()
|
||||
local a = {}
|
||||
local function txt()
|
||||
a = {{width=w-1,height=h-4,sTable={},filepath="",lines={""},changed=false},0,0,1,1}
|
||||
if tFilepath ~= "" then
|
||||
if fs.exists(tFilepath) == true then
|
||||
local openfile = fs.open(tFilepath,"r")
|
||||
a[1].lines = {}
|
||||
for line in openfile.readLine do
|
||||
a[1].lines[#a[1].lines+1] = line
|
||||
end
|
||||
openfile.close()
|
||||
if a[1].lines[1] == nil then
|
||||
a[1].lines[1] = ""
|
||||
end
|
||||
end
|
||||
end
|
||||
while true do
|
||||
local w,h = term.getSize()
|
||||
a[1].width = w-1
|
||||
a[1].height = h-4
|
||||
a[1].sTable = {background={tCol.bg},text={tCol.txt},cursor={colors.red}}
|
||||
term.setCursorPos(1,5)
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.setTextColor(colors.black)
|
||||
--print("I am present.")
|
||||
local changesAllowed = true
|
||||
if isReadOnly == true or (tFilepath ~= "" and fs.isReadOnly(tFilepath) == true) then
|
||||
changesAllowed = false
|
||||
end
|
||||
a = {lUtils.drawEditBox(a[1],1,3,a[2],a[3],a[4],a[5],true,true,nil,changesAllowed)}
|
||||
--term.setCursorPos(1,3)
|
||||
--term.clearLine()
|
||||
--term.write("HIII: ")
|
||||
--term.write(textutils.serialize(a))
|
||||
os.sleep(0)
|
||||
end
|
||||
end
|
||||
_G.thetxtfunction = txt
|
||||
local function save()
|
||||
if tFilepath == "" then
|
||||
while true do
|
||||
local i = {lUtils.inputbox("Filepath","Please enter a new filepath:",29,10,{"Done","Cancel"})}
|
||||
if i[2] == false or i[4] == "Cancel" then
|
||||
return false
|
||||
end
|
||||
if fs.exists(i[1]) == true then
|
||||
lUtils.popup("Error","This path already exists!",29,9,{"OK"})
|
||||
else
|
||||
tFilepath = i[1]
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
local savefile = fs.open(tFilepath,"w")
|
||||
for t=1,#a[1].lines do
|
||||
savefile.writeLine(a[1].lines[t])
|
||||
end
|
||||
savefile.close()
|
||||
return true
|
||||
end
|
||||
function uwansave()
|
||||
local name = ""
|
||||
if tFilepath == "" then
|
||||
name = "Untitled"
|
||||
else
|
||||
name = fs.getName(tFilepath)
|
||||
end
|
||||
local c = {lUtils.popup("Notepad","Do you want to save your changes in "..name.."?",30,8,{"Save","Don't save","Cancel"})}
|
||||
if c[1] == false then return false
|
||||
elseif c[3] == "Save" then
|
||||
if tFilepath == "" then
|
||||
-- select file path with explorer asap
|
||||
return false
|
||||
end
|
||||
local ayyy = fs.open(tFilepath,"w")
|
||||
for t=1,#a[1].lines do
|
||||
ayyy.writeLine(a[1].lines[t])
|
||||
end
|
||||
end
|
||||
if c[3] ~= "Cancel" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
local function scrollbars()
|
||||
local w,h = term.getSize()
|
||||
term.setCursorPos(1,h-1)
|
||||
term.setBackgroundColor(tCol.misc)
|
||||
term.setTextColor(tCol.misc2)
|
||||
term.clearLine()
|
||||
term.setCursorPos(1,h-1)
|
||||
term.write("\17")
|
||||
term.setCursorPos(w-1,h-1)
|
||||
term.write("\16")
|
||||
for t=2,h-2 do
|
||||
term.setCursorPos(w,t)
|
||||
if t == 3 then
|
||||
term.write("\30")
|
||||
elseif t == h-2 then
|
||||
term.write("\31")
|
||||
else
|
||||
term.write(" ")
|
||||
end
|
||||
end
|
||||
term.setCursorPos(1,h)
|
||||
for t=1,w do
|
||||
term.write("\131")
|
||||
end
|
||||
end
|
||||
function LevelOS.close()
|
||||
local u = true
|
||||
if a[1].changed == true then
|
||||
u = uwansave()
|
||||
end
|
||||
if u == true then
|
||||
return
|
||||
else
|
||||
regevents()
|
||||
end
|
||||
end
|
||||
function regevents()
|
||||
scrollbars()
|
||||
local txtcor = coroutine.create(txt)
|
||||
topbar()
|
||||
coroutine.resume(txtcor)
|
||||
while true do
|
||||
e = {os.pullEvent()}
|
||||
scrollbars()
|
||||
if not ((e[1] == "mouse_click" or e[1] == "mouse_up") and e[4] == 1) then
|
||||
coroutine.resume(txtcor,table.unpack(e))
|
||||
end
|
||||
--term.setCursorPos(1,3)
|
||||
--term.setBackgroundColor(colors.white)
|
||||
--term.setTextColor(colors.black)
|
||||
--term.clearLine()
|
||||
--term.setCursorPos(1,3)
|
||||
--term.write(coroutine.status(txtcor).." "..textutils.serialize(a[1]))
|
||||
if e[1] == "term_resize" then
|
||||
topbar()
|
||||
scrollbars()
|
||||
coroutine.resume(txtcor,"mouse_click",1,1,1)
|
||||
elseif e[1] == "mouse_click" then
|
||||
if e[4] == 1 then
|
||||
topbar()
|
||||
term.setCursorBlink(false)
|
||||
local oldcursorpos = {term.getCursorPos()}
|
||||
for t=1,#btns do
|
||||
if e[3] >= btns[t].x and e[3] <= btns[t].x+btns[t].w-1 then
|
||||
-- open menu and color button light blue
|
||||
term.setCursorPos(btns[t].x,1)
|
||||
term.setBackgroundColor(colors.blue)
|
||||
term.write(" "..btns[t][1].." ")
|
||||
local disabled = {}
|
||||
if btns[t][1] == "File" then
|
||||
if a[1].changed == false then
|
||||
disabled = {"Save","Save as..."}
|
||||
end
|
||||
end
|
||||
local b = {lUtils.clickmenu(btns[t].x,2,20,btns[t][2],true,disabled)}
|
||||
if b[1] ~= false then
|
||||
if b[3] == "New" then
|
||||
local d = true
|
||||
if a[1].changed == true then
|
||||
d = uwansave()
|
||||
end
|
||||
if d == true then
|
||||
tFilepath = ""
|
||||
txtcor = coroutine.create(txt)
|
||||
os.startTimer(0.1)
|
||||
end
|
||||
elseif b[3] == "New window" then
|
||||
lOS.execute(LevelOS.path)
|
||||
elseif b[3] == "Open..." then
|
||||
local u = true
|
||||
if a[1].changed == true then
|
||||
u = uwansave()
|
||||
end
|
||||
if u == true then
|
||||
local d = {lUtils.explorer("/","SelFile false")}
|
||||
if d[1] ~= nil then
|
||||
if fs.exists(d[1]) == true then
|
||||
a = {}
|
||||
txtcor = coroutine.create(txt)
|
||||
coroutine.resume(txtcor)
|
||||
tFilepath = d[1]
|
||||
local openfile = fs.open(tFilepath,"r")
|
||||
a[1].lines = {}
|
||||
for line in openfile.readLine do
|
||||
a[1].lines[#a[1].lines+1] = line
|
||||
end
|
||||
openfile.close()
|
||||
if a[1].lines[1] == nil then
|
||||
a[1].lines[1] = ""
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif b[3] == "Save" then
|
||||
if save() == true then
|
||||
a[1].changed = false
|
||||
end
|
||||
elseif b[3] == "Save as..." then
|
||||
local oldF = tFilepath
|
||||
tFilepath = ""
|
||||
if save() == false then
|
||||
tFilepath = oldF
|
||||
else
|
||||
a[1].changed = false
|
||||
end
|
||||
elseif b[3] == "Quit" then
|
||||
local u = true
|
||||
if a[1].changed == true then
|
||||
u = uwansave()
|
||||
end
|
||||
if u == true then
|
||||
return
|
||||
end
|
||||
elseif b[3] == "Dark Mode" then
|
||||
tCol = {bg=colors.black,txt=colors.white,misc=colors.gray,misc2=colors.lightGray}
|
||||
topbar()
|
||||
scrollbars()
|
||||
coroutine.resume(txtcor,"mouse_click",1,1,1)
|
||||
btns[3][2][1] = "Light Mode"
|
||||
elseif b[3] == "Light Mode" then
|
||||
tCol = {bg=colors.white,txt=colors.black,misc=colors.lightGray,misc2=colors.gray}
|
||||
topbar()
|
||||
scrollbars()
|
||||
coroutine.resume(txtcor,"mouse_click",1,1,1)
|
||||
btns[3][2][1] = "Dark Mode"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
topbar()
|
||||
term.setCursorPos(table.unpack(oldcursorpos))
|
||||
term.setTextColor(colors.red)
|
||||
term.setCursorBlink(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
regevents()
|
||||
1
Program_Files/LevelOS/Notepad/taskbar.limg
Normal file
1
Program_Files/LevelOS/Notepad/taskbar.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," 0","00 ",},{"
","000"," ",},},}
|
||||
1
Program_Files/LevelOS/Store/icon.limg
Normal file
1
Program_Files/LevelOS/Store/icon.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," ","999",},{""," 9 ","909",},{"","999"," ",},},}
|
||||
1538
Program_Files/LevelOS/Store/main.lua
Normal file
1538
Program_Files/LevelOS/Store/main.lua
Normal file
File diff suppressed because it is too large
Load Diff
1
Program_Files/LevelOS/Store/taskbar.limg
Normal file
1
Program_Files/LevelOS/Store/taskbar.limg
Normal file
@ -0,0 +1 @@
|
||||
{{{""," 0","00 ",},{"
","000"," ",},},}
|
||||
743
blittle
Normal file
743
blittle
Normal file
@ -0,0 +1,743 @@
|
||||
-- +--------------------------------------------------------+
|
||||
-- | |
|
||||
-- | BLittle |
|
||||
-- | |
|
||||
-- +--------------------------------------------------------+
|
||||
|
||||
local version = "Version 1.1.6beta"
|
||||
|
||||
-- By Jeffrey Alexander, aka Bomb Bloke.
|
||||
-- Convenience functions to make use of ComputerCraft 1.76's new "drawing" characters.
|
||||
-- http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
|
||||
|
||||
-------------------------------------------------------------
|
||||
|
||||
if shell then
|
||||
local arg = {...}
|
||||
|
||||
if #arg == 0 then
|
||||
print("Usage:")
|
||||
print("blittle <scriptName> [args]")
|
||||
return
|
||||
end
|
||||
|
||||
if not blittle then os.loadAPI(shell.getRunningProgram()) end
|
||||
local oldTerm = term.redirect(blittle.createWindow())
|
||||
shell.run(unpack(arg))
|
||||
term.redirect(oldTerm)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local relations = {[0] = {8, 4, 3, 6, 5}, {4, 14, 8, 7}, {6, 10, 8, 7}, {9, 11, 8, 0}, {1, 14, 8, 0}, {13, 12, 8, 0}, {2, 10, 8, 0}, {15, 8, 10, 11, 12, 14},
|
||||
{0, 7, 1, 9, 2, 13}, {3, 11, 8, 7}, {2, 6, 7, 15}, {9, 3, 7, 15}, {13, 5, 7, 15}, {5, 12, 8, 7}, {1, 4, 7, 15}, {7, 10, 11, 12, 14}}
|
||||
|
||||
local colourNum, exponents, colourChar = {}, {}, {}
|
||||
for i = 0, 15 do exponents[2^i] = i end
|
||||
do
|
||||
local hex = "0123456789abcdef"
|
||||
for i = 1, 16 do
|
||||
colourNum[hex:sub(i, i)] = i - 1
|
||||
colourNum[i - 1] = hex:sub(i, i)
|
||||
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
|
||||
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
|
||||
|
||||
local thisRel = relations[i - 1]
|
||||
for i = 1, #thisRel do thisRel[i] = 2 ^ thisRel[i] end
|
||||
end
|
||||
end
|
||||
|
||||
local function getBestColourMatch(usage)
|
||||
local lastCol = relations[exponents[usage[#usage][1]]]
|
||||
|
||||
for j = 1, #lastCol do
|
||||
local thisRelation = lastCol[j]
|
||||
for i = 1, #usage - 1 do if usage[i][1] == thisRelation then return i end end
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
local function colsToChar(pattern, totals)
|
||||
if not totals then
|
||||
local newPattern = {}
|
||||
totals = {}
|
||||
for i = 1, 6 do
|
||||
local thisVal = pattern[i]
|
||||
local thisTot = totals[thisVal]
|
||||
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
|
||||
end
|
||||
pattern = newPattern
|
||||
end
|
||||
|
||||
local usage = {}
|
||||
for key, value in pairs(totals) do usage[#usage + 1] = {key, value} end
|
||||
|
||||
if #usage > 1 then
|
||||
-- Reduce the chunk to two colours:
|
||||
while #usage > 2 do
|
||||
table.sort(usage, function (a, b) return a[2] > b[2] end)
|
||||
local matchToInd, usageLen = getBestColourMatch(usage), #usage
|
||||
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
|
||||
for i = 1, 6 do if pattern[i] == matchFrom then
|
||||
pattern[i] = matchTo
|
||||
usage[matchToInd][2] = usage[matchToInd][2] + 1
|
||||
end end
|
||||
usage[usageLen] = nil
|
||||
end
|
||||
|
||||
-- Convert to character. Adapted from oli414's function:
|
||||
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
|
||||
local data = 128
|
||||
for i = 1, #pattern - 1 do if pattern[i] ~= pattern[6] then data = data + 2^(i-1) end end
|
||||
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
|
||||
else
|
||||
-- Solid colour character:
|
||||
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
|
||||
end
|
||||
end
|
||||
|
||||
local function snooze()
|
||||
local myEvent = tostring({})
|
||||
os.queueEvent(myEvent)
|
||||
os.pullEvent(myEvent)
|
||||
end
|
||||
|
||||
function shrink(image, bgCol)
|
||||
local results, width, height, bgCol = {{}, {}, {}}, 0, #image + #image % 3, bgCol or colours.black
|
||||
for i = 1, #image do if #image[i] > width then width = #image[i] end end
|
||||
|
||||
for y = 0, height - 1, 3 do
|
||||
local cRow, tRow, bRow, counter = {}, {}, {}, 1
|
||||
|
||||
for x = 0, width - 1, 2 do
|
||||
-- Grab a 2x3 chunk:
|
||||
local pattern, totals = {}, {}
|
||||
|
||||
for yy = 1, 3 do for xx = 1, 2 do
|
||||
pattern[#pattern + 1] = (image[y + yy] and image[y + yy][x + xx]) and (image[y + yy][x + xx] == 0 and bgCol or image[y + yy][x + xx]) or bgCol
|
||||
totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1
|
||||
end end
|
||||
|
||||
cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals)
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow)
|
||||
end
|
||||
|
||||
results.width, results.height = #results[1][1], #results[1]
|
||||
|
||||
return results
|
||||
end
|
||||
|
||||
function shrinkGIF(image, bgCol)
|
||||
if not GIF and not os.loadAPI("GIF") then error("blittle.shrinkGIF: Load GIF API first.", 2) end
|
||||
|
||||
image = GIF.flattenGIF(image)
|
||||
snooze()
|
||||
|
||||
local prev = GIF.toPaintutils(image[1])
|
||||
snooze()
|
||||
|
||||
prev = blittle.shrink(prev, bgCol)
|
||||
prev.delay = image[1].delay
|
||||
image[1] = prev
|
||||
snooze()
|
||||
|
||||
image.width, image.height = prev.width, prev.height
|
||||
|
||||
for i = 2, #image do
|
||||
local temp = GIF.toPaintutils(image[i])
|
||||
snooze()
|
||||
|
||||
temp = blittle.shrink(temp, bgCol)
|
||||
snooze()
|
||||
|
||||
local newImage = {{}, {}, {}, ["delay"] = image[i].delay, ["width"] = temp.width, ["height"] = 0}
|
||||
|
||||
local a, b, c, pa, pb, pc = temp[1], temp[2], temp[3], prev[1], prev[2], prev[3]
|
||||
for i = 1, temp.height do
|
||||
local a1, b1, c1, pa1, pb1, pc1 = a[i], b[i], c[i], pa[i], pb[i], pc[i]
|
||||
|
||||
if a1 ~= pa1 or b1 ~= pb1 or c1 ~= pc1 then
|
||||
local min, max = 1, #a1
|
||||
local a2, b2, c2, pa2, pb2, pc2 = {a1:byte(1, max)}, {b1:byte(1, max)}, {c1:byte(1, max)}, {pa1:byte(1, max)}, {pb1:byte(1, max)}, {pc1:byte(1, max)}
|
||||
|
||||
for j = 1, max do if a2[j] ~= pa2[j] or b2[j] ~= pb2[j] or c2[j] ~= pc2[j] then
|
||||
min = j
|
||||
break
|
||||
end end
|
||||
|
||||
for j = max, min, -1 do if a2[j] ~= pa2[j] or b2[j] ~= pb2[j] or c2[j] ~= pc2[j] then
|
||||
max = j
|
||||
break
|
||||
end end
|
||||
|
||||
newImage[1][i], newImage[2][i], newImage[3][i], newImage.height = min > 1 and {min - 1, a1:sub(min, max)} or a1:sub(min, max), b1:sub(min, max), c1:sub(min, max), i
|
||||
end
|
||||
|
||||
snooze()
|
||||
end
|
||||
|
||||
image[i], prev = newImage, temp
|
||||
|
||||
for j = 1, i - 1 do
|
||||
local oldImage = image[j]
|
||||
|
||||
if type(oldImage[1]) == "table" and oldImage.height == newImage.height then
|
||||
local same = true
|
||||
|
||||
for k = 1, oldImage.height do
|
||||
local comp1, comp2 = oldImage[1][k], newImage[1][k]
|
||||
|
||||
if type(comp1) ~= type(comp2) or
|
||||
(type(comp1) == "string" and comp1 ~= comp2) or
|
||||
(type(comp1) == "table" and (comp1[1] ~= comp2[1] or comp1[2] ~= comp2[2])) or
|
||||
oldImage[2][k] ~= newImage[2][k] or
|
||||
oldImage[3][k] ~= newImage[3][k] then
|
||||
same = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if same then
|
||||
newImage[1], newImage[2], newImage[3] = j
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
snooze()
|
||||
end
|
||||
end
|
||||
|
||||
return image
|
||||
end
|
||||
|
||||
local function newLine(width, bCol)
|
||||
local line = {}
|
||||
for i = 1, width do line[i] = {bCol, bCol, bCol, bCol, bCol, bCol} end
|
||||
return line
|
||||
end
|
||||
|
||||
function createWindow(parent, x, y, width, height, visible)
|
||||
if parent == term or not parent then
|
||||
parent = term.current()
|
||||
elseif type(parent) ~= "table" or not parent.write then
|
||||
error("blittle.newWindow: \"parent\" does not appear to be a terminal object.", 2)
|
||||
end
|
||||
|
||||
local workBuffer, backBuffer, frontBuffer, window, tCol, bCol, curX, curY, blink, cWidth, cHeight, pal = {}, {}, {}, {}, colours.white, colours.black, 1, 1, false
|
||||
if type(visible) ~= "boolean" then visible = true end
|
||||
x, y = x and math.floor(x) or 1, y and math.floor(y) or 1
|
||||
|
||||
do
|
||||
local xSize, ySize = parent.getSize()
|
||||
cWidth, cHeight = (width or xSize), (height or ySize)
|
||||
width, height = cWidth * 2, cHeight * 3
|
||||
end
|
||||
|
||||
if parent.setPaletteColour then
|
||||
pal = {}
|
||||
|
||||
local counter = 1
|
||||
for i = 1, 16 do
|
||||
pal[counter] = {parent.getPaletteColour(counter)}
|
||||
counter = counter * 2
|
||||
end
|
||||
|
||||
window.getPaletteColour = function(colour)
|
||||
return unpack(pal[colour])
|
||||
end
|
||||
|
||||
window.setPaletteColour = function(colour, r, g, b)
|
||||
pal[colour] = {r, g, b}
|
||||
if visible then return parent.setPaletteColour(colour, r, g, b) end
|
||||
end
|
||||
|
||||
window.getPaletteColor, window.setPaletteColor = window.getPaletteColour, window.setPaletteColour
|
||||
end
|
||||
|
||||
window.blit = function(_, _, bC)
|
||||
local bClen = #bC
|
||||
if curX > width or curX + bClen < 2 or curY < 1 or curY > height then
|
||||
curX = curX + bClen
|
||||
return
|
||||
end
|
||||
|
||||
if curX < 1 then
|
||||
bC = bC:sub(2 - curX)
|
||||
curX, bClen = 1, #bC
|
||||
end
|
||||
|
||||
if curX + bClen - 1 > width then bC, bClen = bC:sub(1, width - curX + 1), width - curX + 1 end
|
||||
|
||||
local colNum, rowNum, thisX, yBump = math.floor((curX - 1) / 2) + 1, math.floor((curY - 1) / 3) + 1, (curX - 1) % 2, ((curY - 1) % 3) * 2
|
||||
local firstColNum, lastColNum, thisRow = colNum, math.floor((curX + bClen) / 2), backBuffer[rowNum]
|
||||
local thisChar = thisRow[colNum]
|
||||
|
||||
for i = 1, bClen do
|
||||
thisChar[thisX + yBump + 1] = colourChar[bC:sub(i, i)]
|
||||
|
||||
if thisX == 1 then
|
||||
thisX, colNum = 0, colNum + 1
|
||||
thisChar = thisRow[colNum]
|
||||
if not thisChar then break end
|
||||
else thisX = 1 end
|
||||
end
|
||||
|
||||
if visible then
|
||||
local chars1, chars2, chars3, count = {}, {}, {}, 1
|
||||
|
||||
for i = firstColNum, lastColNum do
|
||||
chars1[count], chars2[count], chars3[count] = colsToChar(thisRow[i])
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
chars1, chars2, chars3 = table.concat(chars1), table.concat(chars2), table.concat(chars3)
|
||||
parent.setCursorPos(x + math.floor((curX - 1) / 2), y + math.floor((curY - 1) / 3))
|
||||
parent.blit(chars1, chars2, chars3)
|
||||
local thisRow = frontBuffer[rowNum]
|
||||
frontBuffer[rowNum] = {thisRow[1]:sub(1, firstColNum - 1) .. chars1 .. thisRow[1]:sub(lastColNum + 1), thisRow[2]:sub(1, firstColNum - 1) .. chars2 .. thisRow[2]:sub(lastColNum + 1), thisRow[3]:sub(1, firstColNum - 1) .. chars3 .. thisRow[3]:sub(lastColNum + 1)}
|
||||
else
|
||||
local thisRow = workBuffer[rowNum]
|
||||
|
||||
if (not thisRow[firstColNum]) or thisRow[firstColNum] < lastColNum then
|
||||
local x, newLastColNum = 1, lastColNum
|
||||
|
||||
while x <= lastColNum + 1 do
|
||||
local thisSpot = thisRow[x]
|
||||
|
||||
if thisSpot then
|
||||
if thisSpot >= firstColNum - 1 then
|
||||
if x < firstColNum then firstColNum = x else thisRow[x] = nil end
|
||||
if thisSpot > newLastColNum then newLastColNum = thisSpot end
|
||||
end
|
||||
x = thisSpot + 1
|
||||
else x = x + 1 end
|
||||
end
|
||||
|
||||
thisRow[firstColNum] = newLastColNum
|
||||
if thisRow.max <= newLastColNum then thisRow.max = firstColNum end
|
||||
end
|
||||
end
|
||||
|
||||
curX = curX + bClen
|
||||
end
|
||||
|
||||
window.write = function(text)
|
||||
window.blit(nil, nil, string.rep(colourChar[bCol], #tostring(text)))
|
||||
end
|
||||
|
||||
window.clearLine = function()
|
||||
local oldX = curX
|
||||
curX = 1
|
||||
window.blit(nil, nil, string.rep(colourChar[bCol], width))
|
||||
curX = oldX
|
||||
end
|
||||
|
||||
window.clear = function()
|
||||
local t, fC, bC = string.rep("\128", cWidth), string.rep(colourChar[tCol], cWidth), string.rep(colourChar[bCol], cWidth)
|
||||
for y = 1, cHeight do workBuffer[y], backBuffer[y], frontBuffer[y] = {["max"] = 0}, newLine(cWidth, bCol), {t, fC, bC} end
|
||||
window.redraw()
|
||||
end
|
||||
|
||||
window.getCursorPos = function()
|
||||
return curX, curY
|
||||
end
|
||||
|
||||
window.setCursorPos = function(newX, newY)
|
||||
curX, curY = math.floor(newX), math.floor(newY)
|
||||
if visible and blink then window.restoreCursor() end
|
||||
end
|
||||
|
||||
window.restoreCursor = function() end
|
||||
window.setCursorBlink = window.restoreCursor
|
||||
|
||||
window.isColour = function()
|
||||
return parent.isColour()
|
||||
end
|
||||
window.isColor = window.isColour
|
||||
|
||||
window.getSize = function()
|
||||
return width, height
|
||||
end
|
||||
|
||||
window.scroll = function(lines)
|
||||
lines = math.floor(lines)
|
||||
|
||||
if lines ~= 0 then
|
||||
if lines % 3 == 0 then
|
||||
local newWB, newBB, newFB, line1, line2, line3 = {}, {}, {}, string.rep("\128", cWidth), string.rep(colourChar[tCol], cWidth), string.rep(colourChar[bCol], cWidth)
|
||||
for y = 1, cHeight do newWB[y], newBB[y], newFB[y] = workBuffer[y + lines] or {["max"] = 0}, backBuffer[y + lines] or newLine(cWidth, bCol), frontBuffer[y + lines] or {line1, line2, line3} end
|
||||
workBuffer, backBuffer, frontBuffer = newWB, newBB, newFB
|
||||
else
|
||||
local newBB, tRowNum, tBump, sRowNum, sBump = {}, 1, 0, math.floor(lines / 3) + 1, (lines % 3) * 2
|
||||
local sRow, tRow = backBuffer[sRowNum], {}
|
||||
for x = 1, cWidth do tRow[x] = {} end
|
||||
|
||||
for y = 1, height do
|
||||
if sRow then
|
||||
for x = 1, cWidth do
|
||||
local tChar, sChar = tRow[x], sRow[x]
|
||||
tChar[tBump + 1], tChar[tBump + 2] = sChar[sBump + 1], sChar[sBump + 2]
|
||||
end
|
||||
else
|
||||
for x = 1, cWidth do
|
||||
local tChar = tRow[x]
|
||||
tChar[tBump + 1], tChar[tBump + 2] = bCol, bCol
|
||||
end
|
||||
end
|
||||
|
||||
tBump, sBump = tBump + 2, sBump + 2
|
||||
|
||||
if tBump > 4 then
|
||||
tBump, newBB[tRowNum] = 0, tRow
|
||||
tRowNum, tRow = tRowNum + 1, {}
|
||||
for x = 1, cWidth do tRow[x] = {} end
|
||||
end
|
||||
|
||||
if sBump > 4 then
|
||||
sRowNum, sBump = sRowNum + 1, 0
|
||||
sRow = backBuffer[sRowNum]
|
||||
end
|
||||
end
|
||||
|
||||
for y = 1, cHeight do workBuffer[y] = {["max"] = 1, cWidth} end
|
||||
|
||||
backBuffer = newBB
|
||||
end
|
||||
|
||||
window.redraw()
|
||||
end
|
||||
end
|
||||
|
||||
window.setTextColour = function(newCol)
|
||||
tCol = newCol
|
||||
end
|
||||
window.setTextColor = window.setTextColour
|
||||
|
||||
window.setBackgroundColour = function(newCol)
|
||||
bCol = newCol
|
||||
end
|
||||
window.setBackgroundColor = window.setBackgroundColour
|
||||
|
||||
window.getTextColour = function()
|
||||
return tCol
|
||||
end
|
||||
window.getTextColor = window.getTextColour
|
||||
|
||||
window.getBackgroundColour = function()
|
||||
return bCol
|
||||
end
|
||||
window.getBackgroundColor = window.getBackgroundColour
|
||||
|
||||
window.redraw = function()
|
||||
if visible then
|
||||
for i = 1, cHeight do
|
||||
local work, front = workBuffer[i], frontBuffer[i]
|
||||
local front1, front2, front3 = front[1], front[2], front[3]
|
||||
|
||||
if work.max > 0 then
|
||||
local line1, line2, line3, lineLen, skip, back, count = {}, {}, {}, 1, 0, backBuffer[i], 1
|
||||
|
||||
while count <= work.max do if work[count] then
|
||||
if skip > 0 then
|
||||
line1[lineLen], line2[lineLen], line3[lineLen] = front1:sub(count - skip, count - 1), front2:sub(count - skip, count - 1), front3:sub(count - skip, count - 1)
|
||||
skip, lineLen = 0, lineLen + 1
|
||||
end
|
||||
|
||||
for i = count, work[count] do
|
||||
line1[lineLen], line2[lineLen], line3[lineLen] = colsToChar(back[i])
|
||||
lineLen = lineLen + 1
|
||||
end
|
||||
|
||||
count = work[count] + 1
|
||||
else skip, count = skip + 1, count + 1 end end
|
||||
|
||||
if count < cWidth + 1 then line1[lineLen], line2[lineLen], line3[lineLen] = front1:sub(count), front2:sub(count), front3:sub(count) end
|
||||
|
||||
front1, front2, front3 = table.concat(line1), table.concat(line2), table.concat(line3)
|
||||
frontBuffer[i], workBuffer[i] = {front1, front2, front3}, {["max"] = 0}
|
||||
end
|
||||
|
||||
parent.setCursorPos(x, y + i - 1)
|
||||
parent.blit(front1, front2, front3)
|
||||
end
|
||||
|
||||
if pal then
|
||||
local counter = 1
|
||||
for i = 1, 16 do
|
||||
parent.setPaletteColour(counter, unpack(pal[counter]))
|
||||
counter = counter * 2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
window.setVisible = function(newVis)
|
||||
newVis = newVis and true or false
|
||||
|
||||
if newVis and not visible then
|
||||
visible = true
|
||||
window.redraw()
|
||||
else visible = newVis end
|
||||
end
|
||||
|
||||
window.getPosition = function()
|
||||
return x, y
|
||||
end
|
||||
|
||||
window.reposition = function(newX, newY, newWidth, newHeight)
|
||||
x, y = type(newX) == "number" and math.floor(newX) or x, type(newY) == "number" and math.floor(newY) or y
|
||||
|
||||
if type(newWidth) == "number" then
|
||||
newWidth = math.floor(newWidth)
|
||||
if newWidth > cWidth then
|
||||
local line1, line2, line3 = string.rep("\128", newWidth - cWidth), string.rep(colourChar[tCol], newWidth - cWidth), string.rep(colourChar[bCol], newWidth - cWidth)
|
||||
for y = 1, cHeight do
|
||||
local bRow, fRow = backBuffer[y], frontBuffer[y]
|
||||
for x = cWidth + 1, newWidth do bRow[x] = {bCol, bCol, bCol, bCol, bCol, bCol} end
|
||||
frontBuffer[y] = {fRow[1] .. line3, fRow[2] .. line2, fRow[3] .. line3}
|
||||
end
|
||||
elseif newWidth < cWidth then
|
||||
for y = 1, cHeight do
|
||||
local wRow, bRow, fRow = workBuffer[y], backBuffer[y], frontBuffer[y]
|
||||
for x = newWidth + 1, cWidth do bRow[x] = nil end
|
||||
frontBuffer[y] = {fRow[1]:sub(1, newWidth), fRow[2]:sub(1, newWidth), fRow[3]:sub(1, newWidth)}
|
||||
|
||||
while wRow[wRow.max] and wRow[wRow.max] > newWidth do
|
||||
wRow[wRow.max] = nil
|
||||
wRow.max = table.maxn(wRow)
|
||||
end
|
||||
end
|
||||
end
|
||||
width, cWidth = newWidth * 2, newWidth
|
||||
end
|
||||
|
||||
if type(newHeight) == "number" then
|
||||
newHeight = math.floor(newHeight)
|
||||
if newHeight > cHeight then
|
||||
local line1, line2, line3 = string.rep("\128", cWidth), string.rep(colourChar[tCol], cWidth), string.rep(colourChar[bCol], cWidth)
|
||||
for y = cHeight + 1, newHeight do workBuffer[y], backBuffer[y], frontBuffer[y] = {["max"] = 0}, newLine(cWidth, bCol), {line1, line2, line3} end
|
||||
elseif newHeight < cHeight then
|
||||
for y = newHeight + 1, cHeight do workBuffer[y], backBuffer[y], frontBuffer[y] = nil, nil, nil end
|
||||
end
|
||||
height, cHeight = newHeight * 3, newHeight
|
||||
end
|
||||
|
||||
window.redraw()
|
||||
end
|
||||
|
||||
window.clear()
|
||||
return window
|
||||
end
|
||||
|
||||
function draw(image, x, y, terminal)
|
||||
local t, tC, bC = image[1], image[2], image[3]
|
||||
x, y, terminal = x or 1, y or 1, terminal or term.current()
|
||||
|
||||
for i = 1, image.height do
|
||||
local tI = t[i]
|
||||
if type(tI) == "string" then
|
||||
terminal.setCursorPos(x, y + i - 1)
|
||||
terminal.blit(tI, tC[i], bC[i])
|
||||
elseif type(tI) == "table" then
|
||||
terminal.setCursorPos(x + tI[1], y + i - 1)
|
||||
terminal.blit(tI[2], tC[i], bC[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function save(image, filename)
|
||||
local output = fs.open(filename, "wb")
|
||||
if not output then error("Can't open "..filename.." for output.") end
|
||||
|
||||
local writeByte = output.write
|
||||
|
||||
local function writeInt(num)
|
||||
writeByte(bit.band(num, 255))
|
||||
writeByte(bit.brshift(num, 8))
|
||||
end
|
||||
|
||||
writeByte(66) -- B
|
||||
writeByte(76) -- L
|
||||
writeByte(84) -- T
|
||||
|
||||
local animated = image[1].delay ~= nil
|
||||
writeByte(animated and 1 or 0)
|
||||
|
||||
if animated then
|
||||
writeInt(#image)
|
||||
else
|
||||
local tempImage = {image[1], image[2], image[3]}
|
||||
image[1], image[2], image[3] = tempImage, nil, nil
|
||||
end
|
||||
|
||||
local width, height = image.width, image.height
|
||||
|
||||
writeInt(width)
|
||||
writeInt(height)
|
||||
|
||||
for k = 1, #image do
|
||||
local thisImage = image[k]
|
||||
|
||||
if type(thisImage[1]) == "number" then
|
||||
writeByte(3)
|
||||
writeInt(thisImage[1])
|
||||
else
|
||||
for i = 1, height do
|
||||
if thisImage[1][i] then
|
||||
local rowType, len, thisRow = type(thisImage[1][i])
|
||||
|
||||
if rowType == "string" then
|
||||
writeByte(1)
|
||||
len = #thisImage[1][i]
|
||||
writeInt(len)
|
||||
thisRow = {thisImage[1][i]:byte(1, len)}
|
||||
elseif rowType == "table" then
|
||||
writeByte(2)
|
||||
len = #thisImage[1][i][2]
|
||||
writeInt(len)
|
||||
writeInt(thisImage[1][i][1])
|
||||
thisRow = {thisImage[1][i][2]:byte(1, len)}
|
||||
else
|
||||
error("Malformed row record #"..i.." in frame #"..k.." when attempting to save \""..filename.."\", type is "..rowType..".")
|
||||
end
|
||||
|
||||
for x = 1, len do writeByte(thisRow[x]) end
|
||||
|
||||
local txt, bg = thisImage[2][i], thisImage[3][i]
|
||||
for x = 1, len do writeByte(colourNum[txt:sub(x, x)] + colourNum[bg:sub(x, x)] * 16) end
|
||||
else writeByte(0) end
|
||||
end
|
||||
end
|
||||
|
||||
if animated then writeInt(thisImage.delay * 20) end
|
||||
|
||||
snooze()
|
||||
end
|
||||
|
||||
if image.pal then
|
||||
writeByte(#image.pal)
|
||||
for i = 0, #image.pal do for j = 1, 3 do writeByte(image.pal[i][j]) end end
|
||||
end
|
||||
|
||||
if not animated then
|
||||
image[2], image[3] = image[1][2], image[1][3]
|
||||
image[1] = image[1][1]
|
||||
end
|
||||
|
||||
output.close()
|
||||
end
|
||||
|
||||
function load(filename)
|
||||
local input = fs.open(filename, "rb")
|
||||
if not input then error("Can't open "..filename.." for input.") end
|
||||
|
||||
local read = input.read
|
||||
|
||||
local function readInt()
|
||||
local result = read()
|
||||
return result + bit.blshift(read(), 8)
|
||||
end
|
||||
|
||||
if string.char(read(), read(), read()) ~= "BLT" then
|
||||
-- Assume legacy format.
|
||||
input.close()
|
||||
input = fs.open(filename, "rb")
|
||||
|
||||
read = input.read
|
||||
|
||||
function readInt()
|
||||
local result = input.read()
|
||||
return result + bit.blshift(input.read(), 8)
|
||||
end
|
||||
|
||||
local image = {}
|
||||
image.width, image.height = readInt(), readInt()
|
||||
|
||||
for i = 1, 3 do
|
||||
local thisSet = {}
|
||||
for y = 1, image.height do
|
||||
local thisRow = {}
|
||||
for x = 1, image.width do thisRow[x] = string.char(input.read()) end
|
||||
thisSet[y] = table.concat(thisRow)
|
||||
end
|
||||
image[i] = thisSet
|
||||
end
|
||||
|
||||
input.close()
|
||||
|
||||
return image
|
||||
end
|
||||
|
||||
local image, animated, frames = {}, read() == 1
|
||||
if animated then frames = readInt() else frames = 1 end
|
||||
|
||||
local width, height = readInt(), readInt()
|
||||
image.width, image.height = width, height
|
||||
|
||||
for k = 1, frames do
|
||||
local thisImage = {["width"] = width, ["height"] = 0}
|
||||
local chr, txt, bg = {}, {}, {}
|
||||
|
||||
for i = 1, height do
|
||||
local lineType = read()
|
||||
|
||||
if lineType == 3 then
|
||||
chr, txt, bg = readInt()
|
||||
break
|
||||
elseif lineType > 0 then
|
||||
local l1, l2, len, bump = {}, {}, readInt()
|
||||
if lineType == 2 then bump = readInt() end
|
||||
|
||||
for x = 1, len do l1[x] = read() end
|
||||
chr[i] = string.char(unpack(l1))
|
||||
if lineType == 2 then chr[i] = {bump, chr[i]} end
|
||||
|
||||
for x = 1, len do
|
||||
local thisVal = read()
|
||||
l1[x], l2[x] = colourNum[bit.band(thisVal, 15)], colourNum[bit.brshift(thisVal, 4)]
|
||||
end
|
||||
|
||||
txt[i], bg[i], thisImage.height = table.concat(l1), table.concat(l2), i
|
||||
end
|
||||
end
|
||||
|
||||
if animated then thisImage["delay"] = readInt() / 20 end
|
||||
thisImage[1], thisImage[2], thisImage[3] = chr, txt, bg
|
||||
image[k] = thisImage
|
||||
|
||||
snooze()
|
||||
end
|
||||
|
||||
local palLength = read()
|
||||
if palLength and palLength > 0 then
|
||||
image.pal = {}
|
||||
for i = 0, palLength do image.pal[i] = {read(), read(), read()} end
|
||||
end
|
||||
|
||||
if not animated then
|
||||
image[2], image[3] = image[1][2], image[1][3]
|
||||
image[1] = image[1][1]
|
||||
end
|
||||
|
||||
input.close()
|
||||
|
||||
return image
|
||||
end
|
||||
|
||||
if term.setPaletteColour then
|
||||
function applyPalette(image, terminal)
|
||||
terminal = terminal or term
|
||||
|
||||
local col, pal = 1, image.pal
|
||||
|
||||
for i = 0, #pal do
|
||||
local thisCol = pal[i]
|
||||
terminal.setPaletteColour(col, thisCol[1] / 255, thisCol[2] / 255, thisCol[3] / 255)
|
||||
col = col * 2
|
||||
end
|
||||
end
|
||||
end
|
||||
847
real_startup.lua
Normal file
847
real_startup.lua
Normal file
@ -0,0 +1,847 @@
|
||||
-- LevelOS
|
||||
|
||||
term.clear()
|
||||
term.setCursorPos(1,1)
|
||||
|
||||
if not fs.exists("LevelOS") then
|
||||
--Let the bios know the system is broken
|
||||
fs.delete("/real_startup.lua")
|
||||
os.reboot()
|
||||
return
|
||||
end
|
||||
for k,v in pairs(colors) do
|
||||
if type(v) == "number" then
|
||||
term.setPaletteColor(v,term.native().getPaletteColor(v))
|
||||
end
|
||||
end
|
||||
|
||||
if lOS then
|
||||
error("LevelOS is already running, silly!")
|
||||
end
|
||||
|
||||
_G.lOS = {}
|
||||
lOS.path = shell.getRunningProgram()
|
||||
|
||||
|
||||
local chunkSize = 32768
|
||||
if jit then
|
||||
chunkSize = 4092
|
||||
end
|
||||
|
||||
local function encodeUTF8(asciiText)
|
||||
local utf8Text = ""
|
||||
|
||||
for i=1, #asciiText, chunkSize do
|
||||
utf8Text = utf8Text..utf8.char(string.byte(asciiText, i, math.min(i + (chunkSize-1), #asciiText)))
|
||||
end
|
||||
|
||||
return utf8Text
|
||||
end
|
||||
|
||||
local function decodeUTF8(utf8Text)
|
||||
local asciiText = ""
|
||||
|
||||
local ok, t = pcall(function()
|
||||
return string.char(utf8.codepoint(utf8Text, 1, #utf8Text))
|
||||
end)
|
||||
|
||||
if ok then
|
||||
asciiText = t
|
||||
else
|
||||
local ok2, err = pcall(function()
|
||||
for _, codepoint in utf8.codes(utf8Text) do
|
||||
if codepoint < 256 then
|
||||
asciiText = asciiText .. string.char(codepoint)
|
||||
else
|
||||
asciiText = asciiText .. "?"
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
if not ok2 then
|
||||
_G.debugCurrentText = asciiText
|
||||
_G.debugTextInput = utf8Text
|
||||
|
||||
error(err, 2)
|
||||
end
|
||||
end
|
||||
|
||||
return asciiText
|
||||
end
|
||||
|
||||
|
||||
local function encodeAll(...)
|
||||
local tbl = table.pack(...)
|
||||
for k,v in pairs(tbl) do
|
||||
if type(v) == "string" and not utf8.len(v) then
|
||||
tbl[k] = encodeUTF8(v)
|
||||
end
|
||||
end
|
||||
|
||||
return table.unpack(tbl, 1, tbl.n)
|
||||
end
|
||||
|
||||
local function decodeAll(...)
|
||||
local tbl = table.pack(...)
|
||||
for k,v in pairs(tbl) do
|
||||
if type(v) == "string" then
|
||||
tbl[k] = decodeUTF8(v)
|
||||
end
|
||||
end
|
||||
|
||||
return table.unpack(tbl, 1, tbl.n)
|
||||
end
|
||||
|
||||
lOS.utf8 = {
|
||||
decode = decodeUTF8,
|
||||
encode = encodeUTF8,
|
||||
decodeAll = decodeAll,
|
||||
encodeAll = encodeAll,
|
||||
}
|
||||
|
||||
local function extractVersion(str)
|
||||
local version = str:match("ComputerCraft (%d+%.%d+%.%d+)")
|
||||
return version
|
||||
end
|
||||
|
||||
local function isVersionAbove(version1, version2)
|
||||
local function splitVersion(version)
|
||||
local parts = {}
|
||||
for part in version:gmatch("(%d+)") do
|
||||
table.insert(parts, tonumber(part))
|
||||
end
|
||||
return parts
|
||||
end
|
||||
|
||||
local v1Parts = splitVersion(version1)
|
||||
local v2Parts = splitVersion(version2)
|
||||
|
||||
for i = 1, math.max(#v1Parts, #v2Parts) do
|
||||
local v1 = v1Parts[i] or 0
|
||||
local v2 = v2Parts[i] or 0
|
||||
if v1 > v2 then
|
||||
return true
|
||||
elseif v1 < v2 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true -- They are equal if all parts are equal
|
||||
end
|
||||
|
||||
if isVersionAbove(extractVersion(_HOST), "1.109") then
|
||||
local fopen = fs.open
|
||||
|
||||
function fs.open(path, mode)
|
||||
local f = fopen(path, mode)
|
||||
if not f then return nil end
|
||||
|
||||
local customHandle = {}
|
||||
|
||||
for k,v in pairs(f) do
|
||||
if mode:find("b") then
|
||||
customHandle[k] = function(...) return v(...) end
|
||||
else
|
||||
customHandle[k] = function(...) return decodeAll(v(encodeAll(...))) end
|
||||
end
|
||||
end
|
||||
|
||||
return customHandle
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--enable mouse if no color
|
||||
if not rtype then
|
||||
_G.rtype = type
|
||||
_G.type = function(obj)
|
||||
local mt = getmetatable(obj)
|
||||
if rtype(mt) == "table" and mt.__type then
|
||||
if rtype(mt.__type) == "string" then
|
||||
return mt.__type
|
||||
elseif rtype(mt.__type) == "function" then
|
||||
return mt.__type(obj)
|
||||
end
|
||||
else
|
||||
return rtype(obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _G.pairs(t)
|
||||
local mt = getmetatable(t)
|
||||
if mt and type(mt.__pairs) == "function" then
|
||||
return mt.__pairs(t)
|
||||
else
|
||||
return next, t, nil
|
||||
end
|
||||
end
|
||||
|
||||
if not hardreboot then
|
||||
_G.hardreboot = os.reboot
|
||||
end
|
||||
|
||||
if fs.combine("a","b","c") == fs.combine("a","b") then
|
||||
local ocombine = fs.combine
|
||||
function fs.combine(path,...)
|
||||
local parts = {...}
|
||||
for p=1,#parts do
|
||||
path = ocombine(path,parts[p])
|
||||
end
|
||||
return path
|
||||
end
|
||||
end
|
||||
|
||||
local w,h = term.getSize()
|
||||
if h < 19 then return end
|
||||
local newwin = false
|
||||
|
||||
local therealOGterm = term.current()
|
||||
local function tokenise( ... )
|
||||
local sLine = table.concat( { ... }, " " )
|
||||
local tWords = {}
|
||||
local bQuoted = false
|
||||
for match in string.gmatch( sLine .. "\"", "(.-)\"" ) do
|
||||
if bQuoted then
|
||||
table.insert( tWords, match )
|
||||
else
|
||||
for m in string.gmatch( match, "[^ \t]+" ) do
|
||||
table.insert( tWords, m )
|
||||
end
|
||||
end
|
||||
bQuoted = not bQuoted
|
||||
end
|
||||
return tWords
|
||||
end
|
||||
|
||||
if fs.exists("AppData") == false then
|
||||
fs.makeDir("AppData")
|
||||
end
|
||||
|
||||
if fs.exists("User") == false then
|
||||
fs.makeDir("User")
|
||||
fs.makeDir("User/Documents")
|
||||
fs.makeDir("User/Images")
|
||||
fs.makeDir("User/Scripts")
|
||||
fs.makeDir("User/Downloads")
|
||||
end
|
||||
|
||||
if not fs.exists("bigfont") then
|
||||
--Let the bios know the system is broken
|
||||
fs.delete("/real_startup.lua")
|
||||
os.reboot()
|
||||
return
|
||||
end
|
||||
|
||||
local to_colors, to_blit = {}, {}
|
||||
for i = 1, 16 do
|
||||
to_blit[2^(i-1)] = ("0123456789abcdef"):sub(i, i)
|
||||
to_colors[("0123456789abcdef"):sub(i, i)] = 2^(i-1)
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function toColor(theblit)
|
||||
return to_colors[theblit] or nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function toBlit(thecolor)
|
||||
return to_blit[thecolor] or nil
|
||||
end
|
||||
|
||||
local function render(spr,x,y)
|
||||
local format = "lImg"
|
||||
if format == "lImg" then
|
||||
local sW,sH = #spr[1][1],#spr
|
||||
local w,h = term.getSize()
|
||||
for l=1,#spr do
|
||||
if not y then
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(sW/2),(math.ceil(h/2)-math.floor(sH/2)+(l-1))+x)
|
||||
else
|
||||
term.setCursorPos(x,y+(l-1))
|
||||
end
|
||||
local bl = {}
|
||||
bl[1] = spr[l][1]
|
||||
bl[2] = string.gsub(spr[l][2],"T",toBlit(term.getBackgroundColor()))
|
||||
bl[3] = string.gsub(spr[l][3],"T",toBlit(term.getBackgroundColor()))
|
||||
term.blit(unpack(bl))
|
||||
end
|
||||
elseif format == "nfp" or format == "nfg" then
|
||||
local b,e = string.find(spr,"\n")
|
||||
local sW,sH
|
||||
local w,h = term.getSize()
|
||||
local lines,sW = getLines(spr)
|
||||
sH = #lines
|
||||
for l=1,sH do
|
||||
term.setCursorPos(math.ceil(w/2)-math.floor(sW/2),math.ceil(h/2)-math.floor(sH/2)+(l-1))
|
||||
term.blit(string.rep(" ",#lines[l]),lines[l],lines[l])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function fread(file)
|
||||
local f = fs.open(file,"r")
|
||||
local o = f.readAll()
|
||||
f.close()
|
||||
return o
|
||||
end
|
||||
|
||||
local function fwrite(file,content)
|
||||
local f = fs.open(file,"w")
|
||||
f.write(content)
|
||||
f.close()
|
||||
return true
|
||||
end
|
||||
|
||||
local loadingico = textutils.unserialize(fread("LevelOS/assets/loading.limg"))
|
||||
|
||||
|
||||
_G.bigfont = loadfile("bigfont",_ENV)()
|
||||
|
||||
|
||||
local progress = 0
|
||||
|
||||
local function centerText(text,customY,customLen) -- i tried to put indentation but pastebin is being stupid for some reason
|
||||
local x,y = term.getSize()
|
||||
local x2,y2 = term.getCursorPos()
|
||||
if customY then y2 = customY end
|
||||
local len = customLen or text:len()
|
||||
term.setCursorPos((math.ceil(x / 2) - math.floor(len / 2)), y2)
|
||||
term.write(text)
|
||||
term.setCursorPos(x2,y2+1)
|
||||
end
|
||||
|
||||
local doUpdate
|
||||
local bootText = "Initializing"
|
||||
local dots = 1
|
||||
local frame = 1
|
||||
|
||||
local function bootscreen()
|
||||
term.setBackgroundColor(colors.black)
|
||||
term.setTextColor(colors.cyan)
|
||||
term.clear()
|
||||
local w,h = term.getSize()
|
||||
if h > 19 then
|
||||
if fs.exists("LevelOS/assets/logo_christmas.limg") and os.date("%m") == "12" then
|
||||
render(textutils.unserialize(fread("LevelOS/assets/logo_christmas.limg"))[1],math.ceil(w/2)-4,h/2-8)
|
||||
elseif fs.exists("LevelOS/assets/logo_pride.limg") then
|
||||
render(textutils.unserialize(fread("LevelOS/assets/logo_pride.limg"))[1],math.ceil(w/2)-4,h/2-8)
|
||||
else
|
||||
bigfont.writeOn(term.current(),2,"L",nil,h/2-8)
|
||||
end
|
||||
else
|
||||
if fs.exists("LevelOS/assets/logo_christmas.limg") and os.date("%m") == "12" then
|
||||
render(textutils.unserialize(fread("LevelOS/assets/logo_christmas.limg"))[1],math.ceil(w/2)-4,h/2-5)
|
||||
elseif fs.exists("LevelOS/assets/logo_pride.limg") then
|
||||
render(textutils.unserialize(fread("LevelOS/assets/logo_pride.limg"))[1],math.ceil(w/2)-4,h/2-5)
|
||||
else
|
||||
bigfont.writeOn(term.current(),2,"L",nil,h/2-5)
|
||||
end
|
||||
end
|
||||
while true do
|
||||
if doUpdate then
|
||||
term.setBackgroundColor(colors.blue)
|
||||
term.setTextColor(colors.white)
|
||||
term.clear()
|
||||
local w,h = term.getSize()
|
||||
term.setCursorPos(1,math.ceil(h/2))
|
||||
centerText("Getting ready for updates")
|
||||
centerText("Do not turn off your computer")
|
||||
local init = false
|
||||
while true do
|
||||
render(loadingico[frame],-5)
|
||||
if progress > 0 then
|
||||
if not init then
|
||||
term.setBackgroundColor(colors.blue)
|
||||
term.setTextColor(colors.white)
|
||||
term.clear()
|
||||
render(loadingico[frame],-5)
|
||||
init = true
|
||||
end
|
||||
term.setCursorPos(1,math.ceil(h/2))
|
||||
centerText("Working on updates")
|
||||
centerText(math.floor(progress + 0.5).."% complete")
|
||||
centerText("Do not turn off your computer")
|
||||
end
|
||||
frame = frame+1
|
||||
if frame > #loadingico then
|
||||
frame = 1
|
||||
end
|
||||
os.sleep(0.1)
|
||||
end
|
||||
end
|
||||
if h > 19 then
|
||||
render(loadingico[frame],10)
|
||||
if bootText then
|
||||
centerText(" "..bootText..string.rep(".",dots).." ",h/2+14,#(" "..bootText.." "))
|
||||
end
|
||||
else
|
||||
render(loadingico[frame],7)
|
||||
end
|
||||
os.pullEvent()
|
||||
end
|
||||
end
|
||||
|
||||
local function loadIco()
|
||||
while true do
|
||||
frame = frame+1
|
||||
if frame > #loadingico then
|
||||
frame = 1
|
||||
end
|
||||
dots = dots+0.5
|
||||
if dots > 3 then dots = 0 end
|
||||
os.sleep(0.1)
|
||||
end
|
||||
end
|
||||
|
||||
local hpost = function(...)
|
||||
while true do
|
||||
local ret = table.pack(http.post(...))
|
||||
if not ret[1] then
|
||||
os.sleep(0.5)
|
||||
else
|
||||
badConn = false
|
||||
return table.unpack(ret, 1, ret.n)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function getField(thing,fieldname)
|
||||
if string.find(thing,"<"..fieldname..">",1,true) ~= nil and string.find(thing,"</"..fieldname..">",1,true) ~= nil then
|
||||
local begin = nil
|
||||
local ending = nil
|
||||
local trash,begin = string.find(thing,"<"..fieldname..">",1,true)
|
||||
local ending,ending2 = string.find(thing,"</"..fieldname..">",begin+1,true)
|
||||
if begin ~= nil and ending ~= nil then
|
||||
return string.sub(thing,begin+1,ending-1),string.sub(thing,1,trash-1)..string.sub(thing,ending2+1,string.len(thing))
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function download(pth)
|
||||
local f = hpost("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode(pth).."&code="..textutils.urlEncode("lSlb8kZq"),{Cookie=userID}).readAll()
|
||||
if f ~= "409" and f ~= "403" and f ~= "401" then
|
||||
if pth == "startup.lua" and f ~= fread(shell.getRunningProgram()) then
|
||||
fwrite(shell.getRunningProgram(),f)
|
||||
os.sleep(1)
|
||||
os.reboot()
|
||||
end
|
||||
if pth ~= "startup.lua" then
|
||||
fwrite(pth,f)
|
||||
end
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local step = 0.05
|
||||
local function update()
|
||||
bootText = "Connecting to server"
|
||||
os.sleep(step)
|
||||
local opost = http.post
|
||||
local ping = http.get("https://os.leveloper.cc/ping.php")
|
||||
if not ping then
|
||||
bootText = "Trying HTTP"
|
||||
os.sleep(step)
|
||||
local ping2 = http.get("http://os.leveloper.cc/ping.php")
|
||||
if not ping2 then
|
||||
bootText = "Starting in offline"
|
||||
os.sleep(step)
|
||||
-- no internet
|
||||
return
|
||||
end
|
||||
function http.post(...)
|
||||
local args = table.pack(...)
|
||||
local r = table.pack(opost(...))
|
||||
if not r[1] and string.find(args[1],"https://",nil,true) == 1 then
|
||||
args[1] = "http"..string.sub(args[1],6,#args[1])
|
||||
return opost(table.unpack(args))
|
||||
else
|
||||
return table.unpack(r)
|
||||
end
|
||||
end
|
||||
local oget = http.get
|
||||
function http.get(...)
|
||||
local args = table.pack(...)
|
||||
local r = table.pack(oget(...))
|
||||
if not r[1] and string.find(args[1],"https://",nil,true) == 1 then
|
||||
args[1] = "http"..string.sub(args[1],6,#args[1])
|
||||
return oget(table.unpack(args))
|
||||
else
|
||||
return table.unpack(r)
|
||||
end
|
||||
end
|
||||
hpost = http.post
|
||||
end
|
||||
|
||||
bootText = "Checking client version"
|
||||
os.sleep(step)
|
||||
local servertimestamp
|
||||
local clienttimestamp
|
||||
if fs.exists("LevelOS/data/version.txt") then
|
||||
clienttimestamp = tonumber(fread("LevelOS/data/version.txt"))
|
||||
end
|
||||
if not clienttimestamp then
|
||||
clienttimestamp = 0
|
||||
end
|
||||
bootText = "Looking for updates"
|
||||
os.sleep(step)
|
||||
local response,err = hpost("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode("").."&code="..textutils.urlEncode("lSlb8kZq"))
|
||||
local res2,err2
|
||||
if fs.exists("LevelOS/startup/LevelCloud.lua") then
|
||||
res2,err2 = hpost("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode("").."&code="..textutils.urlEncode("Sm0f1bwQ"))
|
||||
end
|
||||
if res2 then
|
||||
bootText = "Updating LevelCloud"
|
||||
os.sleep(step)
|
||||
local f = res2.readAll()
|
||||
local sTS = tonumber((getField(f,"version"))) or math.huge
|
||||
local cTS = fs.attributes("LevelOS/startup/LevelCloud.lua").modification or fs.attributes("LevelOS/startup/LevelCloud.lua").modified or 0
|
||||
if sTS > cTS then
|
||||
local f = hpost("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode("LevelCloud.lua").."&code="..textutils.urlEncode("Sm0f1bwQ"))
|
||||
if f then
|
||||
fwrite("LevelOS/startup/LevelCloud.lua",f.readAll())
|
||||
end
|
||||
end
|
||||
end
|
||||
bootText = "Processing"
|
||||
os.sleep(step)
|
||||
if not response then
|
||||
-- could not connect
|
||||
--os.sleep(0.5)
|
||||
-- put "starting in offline mode"
|
||||
return
|
||||
end
|
||||
local f = response.readAll()
|
||||
servertimestamp = tonumber((getField(f,"version")))
|
||||
local tFiles = 0
|
||||
local pack = "Full"
|
||||
if fs.exists("LevelOS/data/settings.lconf") then
|
||||
local set = textutils.unserialize(fread("LevelOS/data/settings.lconf"))
|
||||
if set.package then
|
||||
pack = set.package
|
||||
end
|
||||
end
|
||||
|
||||
local tree = {}
|
||||
local folders = {}
|
||||
local function searchFolder(folder)
|
||||
--print("Searching folder root/"..folder)
|
||||
local f = hpost("https://os.leveloper.cc/sGet.php","path="..textutils.urlEncode(folder).."&code="..textutils.urlEncode("lSlb8kZq")).readAll()
|
||||
--print(f)
|
||||
local f2 = f
|
||||
while true do
|
||||
local file = nil
|
||||
file,f = getField(f,"file")
|
||||
if not file then
|
||||
break
|
||||
else
|
||||
local name = getField(file,"name")
|
||||
local timestamp = getField(file,"timestamp")
|
||||
timestamp = tonumber(timestamp)
|
||||
if pack == "Full" or fs.exists(fs.combine(folder,name)) or folder == "LevelOS/assets" or fs.combine(folder,name) == "startup.lua" then
|
||||
tree[fs.combine(folder,name)] = {timestamp=timestamp}
|
||||
tFiles = tFiles+1
|
||||
end
|
||||
--print("Found "..fs.combine(folder,name))
|
||||
end
|
||||
end
|
||||
f = f2
|
||||
while true do
|
||||
local file = nil
|
||||
file,f = getField(f,"folder")
|
||||
if not file then
|
||||
break
|
||||
else
|
||||
local name = getField(file,"name")
|
||||
if not fs.exists(fs.combine(folder,name)) then
|
||||
fs.makeDir(fs.combine(folder,name))
|
||||
end
|
||||
folders[fs.combine(folder,name)] = ""
|
||||
searchFolder(fs.combine(folder,name))
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
if servertimestamp > clienttimestamp then
|
||||
doUpdate = true
|
||||
local deleteFiles = {
|
||||
"LevelOS/explorer.lua",
|
||||
"LevelOS/Pigeon.lua",
|
||||
"LevelOS/LevelCloud.lua",
|
||||
"LevelOS/notepad.lua",
|
||||
"LevelOS/Register.lua",
|
||||
}
|
||||
if fs.exists("LevelOS/data/nativelog.txt") then
|
||||
fs.move("LevelOS/data/nativelog.txt","LevelOS/data/nativelog.lconf")
|
||||
end
|
||||
for f=1,#deleteFiles do
|
||||
if fs.exists(deleteFiles[f]) then
|
||||
fs.delete(deleteFiles[f])
|
||||
end
|
||||
end
|
||||
else
|
||||
bootText = "Checking file integrity"
|
||||
os.sleep(step)
|
||||
local icheck = {
|
||||
--"startup.lua",
|
||||
"bigfont",
|
||||
"blittle",
|
||||
"LevelOS",
|
||||
"LevelOS/system.lua",
|
||||
"LevelOS/startup",
|
||||
"LevelOS/startup/lUtils.lua",
|
||||
"LevelOS/assets",
|
||||
"LevelOS/assets/Circle_Symbols.limg",
|
||||
"LevelOS/assets/circProgress.limg",
|
||||
"LevelOS/assets/Compact_Icons.limg",
|
||||
"LevelOS/assets/Desktop_Icons.limg",
|
||||
"LevelOS/assets/loading.limg",
|
||||
"LevelOS/assets/logo_pride.limg",
|
||||
"LevelOS/assets/QR_Code.limg",
|
||||
"LevelOS/assets/wifi.limg",
|
||||
"LevelOS/login.lua",
|
||||
"LevelOS/Changelog.lua",
|
||||
"LevelOS/lStore.lua",
|
||||
"LevelOS/SystemUI.lua",
|
||||
"LevelOS/Task_Manager.lua",
|
||||
}
|
||||
local aFiles = {} -- absent files
|
||||
for f=1,#icheck do
|
||||
if not fs.exists(icheck[f]) then
|
||||
table.insert(aFiles,icheck[f])
|
||||
end
|
||||
end
|
||||
if #aFiles > 0 then
|
||||
bootText = "Integrity compromised"
|
||||
os.sleep(0.5)
|
||||
bootText = "Restoring files"
|
||||
if not searchFolder("") then return false end
|
||||
|
||||
for f=1,#aFiles do
|
||||
while not download(aFiles[f]) do
|
||||
end
|
||||
end
|
||||
bootText = "Restarting"
|
||||
os.sleep(1)
|
||||
os.reboot()
|
||||
end
|
||||
end
|
||||
|
||||
if doUpdate then
|
||||
if not searchFolder("") then return false end
|
||||
|
||||
if tree["startup.lua"] then
|
||||
download("startup.lua")
|
||||
end
|
||||
|
||||
for k,v in pairs(tree) do
|
||||
if download(k,root,v.timestamp) == true then
|
||||
progress = progress+(100/tFiles)
|
||||
end
|
||||
end
|
||||
fwrite("LevelOS/data/version.txt",tostring(servertimestamp))
|
||||
os.sleep(1)
|
||||
os.reboot()
|
||||
end
|
||||
if not fs.exists("LevelOS/assets/wifi.limg") then
|
||||
folders["LevelOS/assets"] = ""
|
||||
if not searchFolder("LevelOS/assets") then return false end
|
||||
for k,v in pairs(tree) do
|
||||
if download(k) == true then
|
||||
end
|
||||
end
|
||||
end
|
||||
bootText = "Loading system"
|
||||
os.sleep(step)
|
||||
end
|
||||
|
||||
|
||||
parallel.waitForAny(update,bootscreen,loadIco)
|
||||
|
||||
local expect = require "cc.expect".expect
|
||||
|
||||
local function wrap(txt,width)
|
||||
local lines = {}
|
||||
for line in txt:gmatch("([^\n]*)\n?") do
|
||||
table.insert(lines,"")
|
||||
for word in line:gmatch("%S*%s?") do
|
||||
if #lines[#lines]+#word > width and #lines[#lines] > 0 then
|
||||
lines[#lines+1] = ""
|
||||
end
|
||||
if #lines[#lines]+#word > width then
|
||||
local tWord = word
|
||||
while #lines[#lines]+#tWord > width do
|
||||
print(tWord:sub(1,width))
|
||||
lines[#lines] = tWord:sub(1,width)
|
||||
table.insert(lines,"")
|
||||
tWord = tWord:sub(width+1)
|
||||
end
|
||||
lines[#lines] = tWord
|
||||
else
|
||||
lines[#lines] = lines[#lines]..word
|
||||
end
|
||||
end
|
||||
end
|
||||
if txt:sub(#txt) == "\n" then
|
||||
table.insert(lines,"")
|
||||
end
|
||||
return lines
|
||||
end
|
||||
|
||||
local function bPrint(txt)
|
||||
local x,y = term.getCursorPos()
|
||||
local w,h = term.getSize()
|
||||
|
||||
local text = wrap(txt,w-(x-1))
|
||||
for t=1,#text do
|
||||
term.write(text[t])
|
||||
term.setCursorPos(x,y+t)
|
||||
end
|
||||
end
|
||||
|
||||
local function wordwrap(str)
|
||||
local x,y = term.getCursorPos()
|
||||
local tW,tH = term.getSize()
|
||||
for w in str:gmatch("%S+") do
|
||||
local x1,y1 = term.getCursorPos()
|
||||
if x1+(#w*3) >= tW then
|
||||
bigfont.bigPrint(" ")
|
||||
local x2,y2 = term.getCursorPos()
|
||||
term.setCursorPos(x,y2)
|
||||
end
|
||||
bigfont.bigWrite(w.." ")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if fs.exists("LevelOS/lStore.lua") then
|
||||
shell.setAlias("lStore","LevelOS/lStore.lua")
|
||||
|
||||
local completion = require "cc.shell.completion"
|
||||
local function completelStorePut(shell, text, previous)
|
||||
if previous[2] == "put" then
|
||||
return fs.complete(text, "User/Cloud", true, false)
|
||||
end
|
||||
end
|
||||
|
||||
shell.setCompletionFunction("LevelOS/lStore.lua", completion.build(
|
||||
{ completion.choice, { "put ", "get ", "run " } },
|
||||
completelStorePut
|
||||
))
|
||||
end
|
||||
|
||||
if jit then
|
||||
shell.run("lStore get JITAlert LevelOS/startup/JITAlert2.lua")
|
||||
if fs.exists("LevelOS/startup/JITAlert2.lua") then
|
||||
if fs.exists("LevelOS/startup/JITAlert.lua") then
|
||||
fs.delete("LevelOS/startup/JITAlert.lua")
|
||||
end
|
||||
fs.move("LevelOS/startup/JITAlert2.lua","LevelOS/startup/JITAlert.lua")
|
||||
end
|
||||
elseif fs.exists("LevelOS/startup/JITAlert.lua") then
|
||||
fs.delete("LevelOS/startup/JITAlert.lua")
|
||||
end
|
||||
|
||||
local u
|
||||
|
||||
local u = {pcall(loadfile("LevelOS/system.lua",_ENV))}
|
||||
_G.whatitreturn = u
|
||||
local link
|
||||
local copied = false
|
||||
local crashwin
|
||||
function bsodRender()
|
||||
term.redirect(therealOGterm)
|
||||
term.setPaletteColor(colors.blue,0,120/255,215/255)
|
||||
term.setPaletteColor(colors.white,1,1,1)
|
||||
term.setCursorPos(4,4)
|
||||
term.setBackgroundColor(colors.blue)
|
||||
term.clear()
|
||||
local w,h = term.getSize()
|
||||
if w > 140 then
|
||||
crashwin = window.create(therealOGterm,12,8,w/2+10,h-12)
|
||||
bigfont.writeOn(therealOGterm,3,"L",w-40,math.ceil(h/2)-10)
|
||||
else
|
||||
crashwin = window.create(therealOGterm,4,5,w-8,h-5)
|
||||
end
|
||||
term.redirect(crashwin)
|
||||
term.setBackgroundColor(colors.blue)
|
||||
term.clear()
|
||||
if w > 110 and h > 40 and fs.exists("LevelOS/assets/QR_Code.limg") then
|
||||
local qrcode = textutils.unserialize(fread("LevelOS/assets/QR_Code.limg"))
|
||||
bigfont.hugePrint(":(")
|
||||
wordwrap("Your PC ran into a problem and needs to restart. Please press space to continue.")
|
||||
print("\n\n\n\n\n\n")
|
||||
local x,y = term.getCursorPos()
|
||||
render(qrcode[1],x,y)
|
||||
term.setCursorPos(x+22,y)
|
||||
bPrint("For more information about this issue and possible fixes, visit ")
|
||||
local txt = "https://discord.gg/vBsjGqy99U"
|
||||
if copied then
|
||||
txt = txt.." (copied to clipboard!)"
|
||||
end
|
||||
local tx,ty = term.getCursorPos()
|
||||
local tw,th = term.getSize()
|
||||
if tx+(#txt-1) > tw then
|
||||
ty = ty+1
|
||||
tx = x+22
|
||||
end
|
||||
if ccemux and ccemux.setClipboard then
|
||||
link = {x=tx,y=ty,w=#txt,h=1,txt="https://discord.gg/vBsjGqy99U"}
|
||||
if copied then
|
||||
term.setTextColor(colors.cyan)
|
||||
else
|
||||
term.setTextColor(colors.lightBlue)
|
||||
term.setCursorPos(link.x,link.y+1)
|
||||
term.write(string.rep("\131",link.w))
|
||||
end
|
||||
end
|
||||
term.setCursorPos(tx,ty)
|
||||
term.write(txt)
|
||||
term.setTextColor(colors.white)
|
||||
term.setCursorPos(x+22,y+(#qrcode[1]-3))
|
||||
bPrint("If you contact support, give them this info:")
|
||||
term.setCursorPos(x+22,y+(#qrcode[1]-1))
|
||||
bPrint(u[2])
|
||||
else
|
||||
bigfont.bigPrint(":(")
|
||||
print("\nYour PC ran into a problem and needs to restart. Please press space to continue.")
|
||||
print("\nError:")
|
||||
print(u[2])
|
||||
end
|
||||
end
|
||||
bsodRender()
|
||||
os.sleep(1)
|
||||
while true do
|
||||
local e = {os.pullEventRaw()}
|
||||
if e[1] == "mouse_click" then
|
||||
local x,y = crashwin.getPosition()
|
||||
e[3] = e[3]-(x-1)
|
||||
e[4] = e[4]-(y-1)
|
||||
end
|
||||
if e[1] == "key" and e[2] == keys.space then
|
||||
hardreboot()
|
||||
elseif e[1] == "term_resize" then
|
||||
bsodRender()
|
||||
elseif link and e[1] == "mouse_click" and e[3] >= link.x and e[4] == link.y and e[3] <= link.x+(link.w-1) then
|
||||
ccemux.setClipboard(link.txt)
|
||||
copied = true
|
||||
bsodRender()
|
||||
elseif link and e[1] == "mouse_click" then
|
||||
--[[term.setCursorPos(1,1)
|
||||
print(textutils.serialize(link))
|
||||
print(textutils.serialize(e))]]
|
||||
elseif e[1] == "terminate" then
|
||||
term.redirect(therealOGterm)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- TEMP FOR DEBUGGING
|
||||
term.setBackgroundColor(colors.black) term.clear() term.setCursorPos(1,1)
|
||||
shell.run("shell")
|
||||
Loading…
x
Reference in New Issue
Block a user