Compare commits
16 Commits
6c7f4c7a1e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6068162d6a | |||
| b464270e60 | |||
| 06bc628ecf | |||
| 4194765119 | |||
| 85e19133a3 | |||
| b1da7a3337 | |||
| aa681dad7c | |||
|
|
2c83b796f5 | ||
|
|
0d4a3461a2 | ||
|
|
9475f2d98d | ||
|
|
d3fd03a069 | ||
| bfe8bddf37 | |||
|
|
dcfd1acbd2 | ||
|
|
5f90062dc9 | ||
|
|
cb6ed18e10 | ||
|
|
dfe28a97f5 |
@@ -3,6 +3,7 @@ local window = require("libs.window")
|
||||
local x, y = term.getSize()
|
||||
local win = window.create("Worm", x / 1.4, y / 1.4, x / 2 - ((x / 1.4) / 2), y / 2 - ((y / 1.5) / 2))
|
||||
win.resizable = false
|
||||
win.fullscreenButton = false
|
||||
sleep()
|
||||
compat.runFile("/rom/programs/fun/worm.lua", win)
|
||||
win.close()
|
||||
|
||||
@@ -13,19 +13,38 @@ local function download_to(url,path)
|
||||
print(" OK")
|
||||
end
|
||||
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/startup.lua","startup.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/modules/interactions.lua","modules/interactions.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/modules/keybinds.lua","modules/keybinds.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/modules/launcher.lua","modules/launcher.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/modules/entrypointclient.lua","modules/entrypointclient.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/libs/keybinds.lua","libs/keybinds.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/libs/compat.lua","libs/compat.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/libs/threading.lua","libs/threading.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/libs/window.lua","libs/window.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/apps/adventure.lua","apps/adventure.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/apps/shell.lua","apps/shell.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/apps/worm.lua","apps/worm.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/apps/launcher.lua","apps/launcher.lua")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/.apps/adventure.app",".apps/adventure.app")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/.apps/shell.app",".apps/shell.app")
|
||||
download_to("https://github.com/cadenthecreator/ccde/raw/refs/heads/main/.apps/worm.app",".apps/worm.app")
|
||||
write("Do you want to setup netmount?\n(Y/n) ")
|
||||
local netmount = read():sub(1,1):lower() ~= "n"
|
||||
|
||||
if netmount then
|
||||
write("URL: ")
|
||||
settings.set("netmount.url", read())
|
||||
write("Username: ")
|
||||
settings.set("netmount.username", read())
|
||||
write("Password: ")
|
||||
settings.set("netmount.password", read("\7"))
|
||||
settings.set("netmount.path", "cloud")
|
||||
settings.save()
|
||||
end
|
||||
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/startup.lua","startup.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/modules/interactions.lua","modules/interactions.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/modules/keybinds.lua","modules/keybinds.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/modules/launcher.lua","modules/launcher.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/modules/entrypointclient.lua","modules/entrypointclient.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/libs/keybinds.lua","libs/keybinds.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/libs/compat.lua","libs/compat.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/libs/threading.lua","libs/threading.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/libs/window.lua","libs/window.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/apps/adventure.lua","apps/adventure.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/apps/shell.lua","apps/shell.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/apps/worm.lua","apps/worm.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/apps/launcher.lua","apps/launcher.lua")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/.apps/adventure.app",".apps/adventure.app")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/.apps/shell.app",".apps/shell.app")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/.apps/worm.app",".apps/worm.app")
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/.wallpaper.nfp",".wallpaper.nfp")
|
||||
|
||||
if netmount then
|
||||
download_to("https://git.cadencoaster.com/Rivulet/ccde/raw/branch/main/modules/netmount.lua","modules/netmount.lua")
|
||||
end
|
||||
|
||||
@@ -541,6 +541,7 @@ function lib.setupENV(win)
|
||||
env.settings = settings
|
||||
env._ENV = env
|
||||
env._G = env
|
||||
env.http = http
|
||||
term.redirect(win)
|
||||
return env
|
||||
end
|
||||
@@ -617,6 +618,7 @@ local function runInRuntime(func, win, close_handled)
|
||||
end
|
||||
local data = table.pack(os.pullEvent())
|
||||
data[1] = data[1]:gsub(escape_lua_pattern "_" .. winid, "")
|
||||
event_data = { n = 0 }
|
||||
if data[1] == filter or filter == nil or data[1] == "terminated" then
|
||||
if data[1] == "char" then
|
||||
if data[#data] == winid then
|
||||
@@ -661,8 +663,6 @@ local function runInRuntime(func, win, close_handled)
|
||||
else
|
||||
event_data = data
|
||||
end
|
||||
else
|
||||
event_data = { n = 0 }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
112
libs/window.lua
112
libs/window.lua
@@ -1,5 +1,5 @@
|
||||
local lib = {}
|
||||
|
||||
local threading = require("libs.threading")
|
||||
local function add(t, v)
|
||||
for i = 1, #t + 1 do
|
||||
if t[i] == nil then
|
||||
@@ -52,7 +52,7 @@ end
|
||||
|
||||
local function clamp(v, lo, hi) return (v < lo) and lo or ((v > hi) and hi or v) end
|
||||
|
||||
function lib.create(name, w, h, x, y)
|
||||
function lib.create(name, w, h, x, y, do_not_add)
|
||||
local sx,sy = term.getSize()
|
||||
if not x then x = sx/2-w/2 end
|
||||
if not y then y = sy/2-h/2 end
|
||||
@@ -71,6 +71,7 @@ function lib.create(name, w, h, x, y)
|
||||
y = y or 2,
|
||||
|
||||
-- column-major buffer: buffer[x][y] = {char, tc, bc}
|
||||
isFullscreen = false,
|
||||
buffer = {},
|
||||
cursorX = 1,
|
||||
cursorY = 1,
|
||||
@@ -82,23 +83,38 @@ function lib.create(name, w, h, x, y)
|
||||
decorations = true,
|
||||
alwaysOnTop = false,
|
||||
alwaysBelow = false,
|
||||
fullscreenButton = true,
|
||||
closing = false,
|
||||
_palette = {}, -- optional local palette store
|
||||
}
|
||||
|
||||
local function init_col(xi)
|
||||
local w = t.w
|
||||
local h = t.h
|
||||
if t.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
end
|
||||
if not t.buffer[xi] then
|
||||
t.buffer[xi] = {}
|
||||
for yy = 1, t.h do
|
||||
for yy = 1, h do
|
||||
t.buffer[xi][yy] = { char = " ", tc = t.textColor, bc = t.bgColor }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function t.clear()
|
||||
for xi = 1, t.w do
|
||||
local w = t.w
|
||||
local h = t.h
|
||||
if t.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
end
|
||||
for xi = 1, w do
|
||||
init_col(xi)
|
||||
for yy = 1, t.h do
|
||||
for yy = 1, h do
|
||||
local cell = t.buffer[xi][yy]
|
||||
if not cell then cell = { char = " ", tc = t.textColor, bc = t.bgColor } end
|
||||
cell.char, cell.tc, cell.bc = " ", t.textColor, t.bgColor
|
||||
@@ -113,16 +129,30 @@ function lib.create(name, w, h, x, y)
|
||||
|
||||
function t.clearLine()
|
||||
local y0 = t.cursorY
|
||||
if y0 < 1 or y0 > t.h then return end
|
||||
for xi = 1, t.w do
|
||||
local w = t.w
|
||||
local h = t.h
|
||||
if t.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
end
|
||||
if y0 < 1 or y0 > h then return end
|
||||
for xi = 1, w do
|
||||
init_col(xi)
|
||||
if not t.buffer[xi][y0] then t.buffer[xi][y0] = { char = " ", tc = t.textColor, bc = t.bgColor } end
|
||||
local cell = t.buffer[xi][y0]
|
||||
cell.char, cell.tc, cell.bc = " ", t.textColor, t.bgColor
|
||||
end
|
||||
-- base keeps cursorX unchanged
|
||||
end
|
||||
|
||||
function t.getSize() return t.w, t.h end
|
||||
function t.getSize()
|
||||
if t.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
return sw,sh-2
|
||||
end
|
||||
return t.w, t.h
|
||||
end
|
||||
|
||||
function t.setCursorPos(x0, y0)
|
||||
-- do NOT clamp; let writers clip like base window
|
||||
@@ -185,12 +215,20 @@ function lib.create(name, w, h, x, y)
|
||||
|
||||
-- write/blit: mutate buffer with clipping; let cursor run past width
|
||||
function t.write(str)
|
||||
local w = t.w
|
||||
local h = t.h
|
||||
if t.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
end
|
||||
str = tostring(str)
|
||||
local y0 = t.cursorY
|
||||
for i = 1, #str do
|
||||
local x = t.cursorX + i - 1
|
||||
if x >= 1 and x <= t.w and y0 >= 1 and y0 <= t.h then
|
||||
if x >= 1 and x <= w and y0 >= 1 and y0 <= h then
|
||||
init_col(x)
|
||||
if not t.buffer[x][y0] then t.buffer[x][y0] = { char = " ", tc = t.textColor, bc = t.bgColor } end
|
||||
local cell = t.buffer[x][y0]
|
||||
cell.char = str:sub(i, i)
|
||||
cell.tc, cell.bc = t.textColor, t.bgColor
|
||||
@@ -205,7 +243,13 @@ function lib.create(name, w, h, x, y)
|
||||
if bgColors and type(bgColors) ~= "string" then error("bad argument #3 (expected string)", 2) end
|
||||
if textColors and #textColors ~= #text then error("Arguments must be the same length", 2) end
|
||||
if bgColors and #bgColors ~= #text then error("Arguments must be the same length", 2) end
|
||||
|
||||
local w = t.w
|
||||
local h = t.h
|
||||
if t.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
end
|
||||
textColors = textColors and textColors:lower() or nil
|
||||
bgColors = bgColors and bgColors:lower() or nil
|
||||
|
||||
@@ -213,7 +257,7 @@ function lib.create(name, w, h, x, y)
|
||||
local n = #text
|
||||
for i = 1, n do
|
||||
local x = t.cursorX + i - 1
|
||||
if x >= 1 and x <= t.w and y0 >= 1 and y0 <= t.h then
|
||||
if x >= 1 and x <= w and y0 >= 1 and y0 <= h then
|
||||
init_col(x)
|
||||
local ch = text:sub(i, i)
|
||||
local tch = textColors and textColors:sub(i, i) or nil
|
||||
@@ -230,15 +274,22 @@ function lib.create(name, w, h, x, y)
|
||||
|
||||
-- scroll: supports positive (up) and negative (down)
|
||||
function t.scroll(n)
|
||||
local w = t.w
|
||||
local h = t.h
|
||||
if t.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
end
|
||||
n = math.floor(n or 1)
|
||||
if n == 0 then return end
|
||||
|
||||
local absn = math.abs(n)
|
||||
if absn >= t.h then
|
||||
if absn >= h then
|
||||
-- clear all rows to new empty lines with current colors
|
||||
for xi = 1, t.w do
|
||||
for xi = 1, w do
|
||||
init_col(xi)
|
||||
for yy = 1, t.h do
|
||||
for yy = 1, h do
|
||||
local cell = t.buffer[xi][yy] or { char = " ", tc = t.textColor, bc = t.bgColor }
|
||||
cell.char, cell.tc, cell.bc = " ", t.textColor, t.bgColor
|
||||
end
|
||||
@@ -248,13 +299,14 @@ function lib.create(name, w, h, x, y)
|
||||
|
||||
if n > 0 then
|
||||
-- move content up
|
||||
for xi = 1, t.w do
|
||||
for xi = 1, w do
|
||||
init_col(xi)
|
||||
for yy = 1, t.h - n do
|
||||
local dst, src = t.buffer[xi][yy], t.buffer[xi][yy + n]
|
||||
for yy = 1, h - n do
|
||||
if not t.buffer[xi][yy] then t.buffer[xi][yy] = { char = " ", tc = t.textColor, bc = t.bgColor } end
|
||||
local dst, src = t.buffer[xi][yy], (t.buffer[xi][yy + n] or { char = " ", tc = t.textColor, bc = t.bgColor })
|
||||
dst.char, dst.tc, dst.bc = src.char, src.tc, src.bc
|
||||
end
|
||||
for yy = t.h - n + 1, t.h do
|
||||
for yy = h - n + 1, h do
|
||||
local cell = t.buffer[xi][yy] or { char = " ", tc = t.textColor, bc = t.bgColor }
|
||||
cell.char, cell.tc, cell.bc = " ", t.textColor, t.bgColor
|
||||
end
|
||||
@@ -262,9 +314,9 @@ function lib.create(name, w, h, x, y)
|
||||
else
|
||||
-- n < 0 : move content down
|
||||
local k = -n
|
||||
for xi = 1, t.w do
|
||||
for xi = 1, w do
|
||||
init_col(xi)
|
||||
for yy = t.h, k + 1, -1 do
|
||||
for yy = h, k + 1, -1 do
|
||||
local dst, src = t.buffer[xi][yy], t.buffer[xi][yy - k]
|
||||
dst.char, dst.tc, dst.bc = src.char, src.tc, src.bc
|
||||
end
|
||||
@@ -326,7 +378,19 @@ function lib.create(name, w, h, x, y)
|
||||
t.buffer, t.w, t.h = newbuf, nw, nh
|
||||
end
|
||||
end
|
||||
|
||||
function t.fullscreen(fullscreen)
|
||||
if fullscreen == nil or fullscreen ~= t.isFullscreen then
|
||||
local w = t.w
|
||||
local h = t.h
|
||||
if t.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
end
|
||||
threading.addThread(function () t.resized(w,h) end)
|
||||
end
|
||||
t.isFullscreen = fullscreen or not t.isFullscreen
|
||||
end
|
||||
function t.redraw() end -- renderer handles this elsewhere
|
||||
|
||||
function t.setVisible(_) end
|
||||
@@ -337,8 +401,10 @@ function lib.create(name, w, h, x, y)
|
||||
|
||||
-- initialize
|
||||
t.clear()
|
||||
add(_G.windows, t)
|
||||
lib.reorder()
|
||||
if not do_not_add then
|
||||
add(_G.windows, t)
|
||||
lib.reorder()
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
@@ -33,29 +33,45 @@ while true do
|
||||
if data[1] == "mouse_click" then
|
||||
for indx = #_G.windows, 1, -1 do
|
||||
local win = _G.windows[indx]
|
||||
local h= win.h
|
||||
local w = win.w
|
||||
local x = win.x
|
||||
local y = win.y
|
||||
if win.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
x=1
|
||||
y=3
|
||||
end
|
||||
if data[4] == 1 then
|
||||
break
|
||||
elseif win.x+win.w-1 == data[3] and win.y+win.h-1 == data[4] and win.decorations and win.resizable then
|
||||
elseif x+w-1 == data[3] and y+h-1 == data[4] and win.decorations and win.resizable and not win.isFullscreen then
|
||||
dragging = win
|
||||
resizing = true
|
||||
bringtofront(indx)
|
||||
elseif ((win.y - 1 == data[4] and win.x + 1 <= data[3] and win.x + win.w >= data[3] and data[2] == 1 and win.decorations) or (win.y <= data[4] and win.x <= data[3] and win.y + win.h > data[4] and win.x + win.w > data[3] and key[keys["leftAlt"]] and win.draggable)) then
|
||||
elseif ((y - 1 == data[4] and x + 1 + (win.fullscreenButton and 1 or 0) <= data[3] and x + w >= data[3] and data[2] == 1 and win.decorations) or (y <= data[4] and x <= data[3] and y + h > data[4] and x + w > data[3] and key[keys["leftAlt"]] and win.draggable)) and not win.isFullscreen then
|
||||
dragging = win
|
||||
offsetX = win.x - data[3]
|
||||
offsetY = win.y - data[4]
|
||||
offsetX = x - data[3]
|
||||
offsetY = y - data[4]
|
||||
bringtofront(indx)
|
||||
break
|
||||
elseif win.y - 1 == data[4] and win.x == data[3] and win.decorations then
|
||||
elseif y - 1 == data[4] and x == data[3] and win.decorations then
|
||||
threading.addThread(function() win.closeRequested() end)
|
||||
bringtofront(indx)
|
||||
break
|
||||
elseif win.y <= data[4] and win.x <= data[3] and win.y + win.h > data[4] and win.x + win.w > data[3] then
|
||||
threading.addThread(function() win.clicked(data[3] - win.x + 1, data[4] - win.y + 1, data[2]) end)
|
||||
elseif y - 1 == data[4] and x+1 == data[3] and win.decorations and win.fullscreenButton then
|
||||
threading.addThread(function() win.fullscreen() end)
|
||||
bringtofront(indx)
|
||||
break
|
||||
elseif y <= data[4] and x <= data[3] and y + h > data[4] and x + w > data[3] then
|
||||
threading.addThread(function() win.clicked(data[3] - x + 1, data[4] - y + 1, data[2]) end)
|
||||
bringtofront(indx)
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif data[1] == "mouse_drag" then
|
||||
data[4] = math.max(data[4],2)
|
||||
if data[2] == 1 and dragging then
|
||||
if resizing then
|
||||
dragging.w = math.max(data[3] - dragging.x + 1,dragging.min_w)
|
||||
@@ -63,13 +79,24 @@ while true do
|
||||
threading.addThread(function()dragging.resized(dragging.w,dragging.h)end)
|
||||
else
|
||||
dragging.x = data[3] + offsetX
|
||||
dragging.y = math.max(data[4] + offsetY,3)
|
||||
dragging.y = data[4] + offsetY
|
||||
end
|
||||
else
|
||||
for indx = #_G.windows, 1, -1 do
|
||||
local win = _G.windows[indx]
|
||||
if win.y <= data[4] and win.x <= data[3] and win.y + win.h > data[4] and win.x + win.w > data[3] then
|
||||
threading.addThread(function() win.dragged(data[3] - win.x + 1, data[4] - win.y + 1, data[2]) end)
|
||||
local h= win.h
|
||||
local w = win.w
|
||||
local x = win.x
|
||||
local y = win.y
|
||||
if win.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
x=1
|
||||
y=3
|
||||
end
|
||||
if y <= data[4] and x <= data[3] and y + h > data[4] and x + w > data[3] then
|
||||
threading.addThread(function() win.dragged(data[3] - x + 1, data[4] - y + 1, data[2]) end)
|
||||
bringtofront(indx)
|
||||
break
|
||||
end
|
||||
@@ -82,8 +109,19 @@ while true do
|
||||
else
|
||||
for indx = #_G.windows, 1, -1 do
|
||||
local win = _G.windows[indx]
|
||||
if win.y <= data[4] and win.x <= data[3] and win.y + win.h > data[4] and win.x + win.w > data[3] then
|
||||
threading.addThread(function() win.released(data[3] - win.x + 1, data[4] - win.y + 1, data[2]) end)
|
||||
local h= win.h
|
||||
local w = win.w
|
||||
local x = win.x
|
||||
local y = win.y
|
||||
if win.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
x=1
|
||||
y=3
|
||||
end
|
||||
if y <= data[4] and x <= data[3] and y + h > data[4] and x + w > data[3] then
|
||||
threading.addThread(function() win.released(data[3] - x + 1, data[4] - y + 1, data[2]) end)
|
||||
bringtofront(indx)
|
||||
break
|
||||
end
|
||||
@@ -92,8 +130,19 @@ while true do
|
||||
elseif data[1] == "mouse_scroll" then
|
||||
for indx = #_G.windows, 1, -1 do
|
||||
local win = _G.windows[indx]
|
||||
if win.y <= data[4] and win.x <= data[3] and win.y + win.h > data[4] and win.x + win.w > data[3] then
|
||||
threading.addThread(function() win.scrolled(data[2], data[3] - win.x + 1, data[4] - win.y + 1) end)
|
||||
local h= win.h
|
||||
local w = win.w
|
||||
local x = win.x
|
||||
local y = win.y
|
||||
if win.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
x=1
|
||||
y=3
|
||||
end
|
||||
if y <= data[4] and x <= data[3] and y + h > data[4] and x + w > data[3] then
|
||||
threading.addThread(function() win.scrolled(data[2], data[3] - x + 1, data[4] - y + 1) end)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
204
modules/netmount.lua
Normal file
204
modules/netmount.lua
Normal file
@@ -0,0 +1,204 @@
|
||||
local _
|
||||
local ofs = assert(_G.fs, "-eh?")
|
||||
-- [[ Argument Parsing ]] --
|
||||
local args = table.pack(...)
|
||||
local handle
|
||||
while true do
|
||||
for i = 1, #args do
|
||||
args[i]:gsub("(.*)=(.*)", function(k, v)
|
||||
args[k] = v
|
||||
end)
|
||||
end
|
||||
if #args < 3 then
|
||||
local keys = {
|
||||
"url",
|
||||
"username",
|
||||
"password",
|
||||
"path",
|
||||
"run"
|
||||
}
|
||||
for i = 1, #keys do
|
||||
local key = keys[i]
|
||||
if not args[key] then
|
||||
args[key] = settings.get("netmount." .. key)
|
||||
end
|
||||
end
|
||||
args.path = args.path or "net"
|
||||
end
|
||||
if (args.username and args.url and args.password) then
|
||||
handle = http.get(args.url:gsub("/$", "").."/api.lua")
|
||||
if handle then break end
|
||||
sleep(3)
|
||||
end
|
||||
sleep()
|
||||
end
|
||||
|
||||
local _, nm = assert(pcall(assert(load(handle.readAll(), "nmapi", nil, _ENV))))
|
||||
handle.close()
|
||||
local state = assert(nm.createState(args.url, args.username, args.password))
|
||||
|
||||
local netroot = ofs.combine(args.path)
|
||||
assert(not ofs.exists(netroot), "Directory "..netroot.." already exists")
|
||||
|
||||
local function toNetRoot(path)
|
||||
path = ofs.combine(path)
|
||||
local nreplaced
|
||||
path, nreplaced = path:gsub("^" .. netroot .. "/", "")
|
||||
if path == netroot then
|
||||
return true, ""
|
||||
elseif path == netroot or nreplaced == 1 then
|
||||
return true, path
|
||||
else
|
||||
return false, path
|
||||
end
|
||||
end
|
||||
|
||||
-- [[ Websocket Request/Response Function & Netmount fs Initialization ]] --
|
||||
|
||||
local function wrapfs()
|
||||
local nfs = nm.createFs(state, args.path)
|
||||
|
||||
local api = {}
|
||||
|
||||
-- [[ Functions that can be directly ripped from old fs API ]] --
|
||||
local copyold = {
|
||||
"combine",
|
||||
"getName",
|
||||
"getDir",
|
||||
}
|
||||
|
||||
for _, fn in ipairs(copyold) do
|
||||
api[fn] = ofs[fn]
|
||||
end
|
||||
|
||||
-- [[ Network Dependent Overrides ]] --
|
||||
|
||||
local singleOverrides = {
|
||||
"makeDir", "delete", "list",
|
||||
"attributes", "exists", "isDir",
|
||||
"isReadOnly", "getDrive", "getSize",
|
||||
"getFreeSpace", "getCapacity"
|
||||
}
|
||||
|
||||
for _, name in ipairs(singleOverrides) do
|
||||
api[name] = function(path)
|
||||
local net
|
||||
net, path = toNetRoot(path)
|
||||
if net then
|
||||
return nfs[name](path)
|
||||
else
|
||||
local out = ofs[name](path)
|
||||
if #fs.combine(path) == 0 then
|
||||
if name == "list" then
|
||||
---@cast out string[]
|
||||
out[#out + 1] = args.path
|
||||
table.sort(out, function(a, b)
|
||||
return #a < #b
|
||||
end)
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local doubleOverrides = {
|
||||
"move",
|
||||
"copy"
|
||||
}
|
||||
|
||||
--- Bidirectionally handle relocating files
|
||||
---@param path string
|
||||
---@param dest string
|
||||
local function relocate(name, path, dest)
|
||||
if api.exists(dest) then
|
||||
error("/" .. api.combine(dest) .. ": File exists")
|
||||
end
|
||||
local pnet, dnet
|
||||
pnet, path = toNetRoot(path)
|
||||
dnet, dest = toNetRoot(dest)
|
||||
if pnet and dnet then
|
||||
nfs[name](path, dest)
|
||||
elseif not (pnet or dnet) then
|
||||
ofs[name](path, dest)
|
||||
else
|
||||
local pfs, dfs, perr, derr
|
||||
local estr = "Failed to open %s file %s"
|
||||
if pnet and not dnet then -- from server to client
|
||||
pfs, dfs = nfs, ofs
|
||||
perr, derr = "remote", "local"
|
||||
else -- from client to server
|
||||
pfs, dfs = ofs, nfs
|
||||
perr, derr = "local", "remote"
|
||||
end
|
||||
if pfs.isDir(path) then
|
||||
local list = pfs.list(path)
|
||||
for _, p in ipairs(list) do
|
||||
relocate(api.combine(path, p), api.combine(dest, p))
|
||||
end
|
||||
else
|
||||
local pfile, dfile = assert(pfs.open(path, "rb"), estr:format(perr, path)), assert(dfs.open(dest, "wb"), estr:format(derr, dest))
|
||||
dfile.write(pfile.readAll())
|
||||
pfile.close()
|
||||
dfile.close()
|
||||
if name == "move" then
|
||||
pfs.delete(path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, name in ipairs(doubleOverrides) do
|
||||
api[name] = function(path, dest)
|
||||
relocate(name, path, dest)
|
||||
end
|
||||
end
|
||||
|
||||
-- [[ Network Dependent File Handles ]] --
|
||||
|
||||
api.open = function(path, mode)
|
||||
local net
|
||||
net, path = toNetRoot(path)
|
||||
if net then
|
||||
return nfs.open(path, mode)
|
||||
else
|
||||
return ofs.open(path, mode)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local romfs, i = "", 1
|
||||
for line in io.lines("rom/apis/fs.lua") do
|
||||
-- Rip out definition weirdness
|
||||
if not (i > 9 and i < 14) then
|
||||
romfs = romfs .. line .. "\n"
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
local env = {}
|
||||
for k, f in pairs(_ENV) do
|
||||
if f == _ENV then
|
||||
f = env
|
||||
else
|
||||
env[k] = f
|
||||
end
|
||||
end
|
||||
env.fs = api
|
||||
setmetatable(env, {__index = _G})
|
||||
assert(pcall(assert(load(romfs, "romfsapi", nil, env)))) -- find, complete, and isDriveRoot
|
||||
end
|
||||
|
||||
return api
|
||||
end
|
||||
|
||||
-- [[ Main Program / Connection handlers ]] --
|
||||
_G.fs = wrapfs()
|
||||
|
||||
local pok, err = pcall(parallel.waitForAny, nm.getSyncHandler(state), nm.getConnectionHandler(state))
|
||||
if not pok then
|
||||
printError(err)
|
||||
end
|
||||
state.close()
|
||||
print("Press any key to continue")
|
||||
os.pullEvent("key")
|
||||
_G.fs = ofs
|
||||
90
startup.lua
90
startup.lua
@@ -1,13 +1,35 @@
|
||||
--os.pullEvent = os.pullEventRaw
|
||||
os.pullEvent = os.pullEventRaw
|
||||
|
||||
local window = require("libs.window")
|
||||
local nft = require "cc.image.nft"
|
||||
local image = nft.load(".wallpaper.nft")
|
||||
local paint_image = paintutils.loadImage(".wallpaper.nfp")
|
||||
local wrap = require("cc.strings").wrap
|
||||
_G.threads = {}
|
||||
_G.windows = {}
|
||||
_G.keybinds = {}
|
||||
local term = term.native()
|
||||
local nterm = term
|
||||
local sx,sy = term.getSize()
|
||||
local term = window.create("",sx,sy,1,1,true)
|
||||
local event = { n = 0 }
|
||||
|
||||
local function drawPixelInternal(xPos, yPos)
|
||||
term.setCursorPos(xPos, yPos)
|
||||
term.write(" ")
|
||||
end
|
||||
|
||||
local function drawImage(image, xPos, yPos)
|
||||
for y = 1, #image do
|
||||
local tLine = image[y]
|
||||
for x = 1, #tLine do
|
||||
if tLine[x] > 0 then
|
||||
term.setBackgroundColor(tLine[x])
|
||||
drawPixelInternal(x + xPos - 1, y + yPos - 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function threads()
|
||||
for id, thr in pairs(_G.threads) do
|
||||
if thr then
|
||||
@@ -39,10 +61,21 @@ end
|
||||
local function windows()
|
||||
term.setCursorBlink(false)
|
||||
for id, win in ipairs(_G.windows) do
|
||||
for cy = 1, win.h do
|
||||
term.setCursorPos(win.x, win.y + cy - 1)
|
||||
local h= win.h
|
||||
local w = win.w
|
||||
local x = win.x
|
||||
local y = win.y
|
||||
if win.isFullscreen then
|
||||
local sw,sh = term.getSize()
|
||||
w = sw
|
||||
h = sh-2
|
||||
x=1
|
||||
y=3
|
||||
end
|
||||
for cy = 1, h do
|
||||
term.setCursorPos(x, y + cy - 1)
|
||||
local line, fg, bg = "", "", ""
|
||||
for cx = 1, win.w do
|
||||
for cx = 1, w do
|
||||
if win.buffer[cx] then
|
||||
local cell = win.buffer[cx][cy]
|
||||
if cell then
|
||||
@@ -63,17 +96,19 @@ local function windows()
|
||||
term.blit(line, fg, bg)
|
||||
end
|
||||
if win.decorations then
|
||||
term.setCursorPos(win.x, win.y - 1)
|
||||
term.setCursorPos(x, y - 1)
|
||||
term.setTextColor(colors.white)
|
||||
term.setBackgroundColor(colors.blue)
|
||||
term.write(string.sub("X " .. win.name .. string.rep(" ", win.w - #win.name - 2),1,win.w))
|
||||
if win.resizable then
|
||||
term.setCursorPos(win.x+win.w-1,win.y+win.h-1)
|
||||
local window_buttons = "X"
|
||||
if win.fullscreenButton then window_buttons = window_buttons.."O" end
|
||||
term.write(string.sub(window_buttons.." " .. win.name .. string.rep(" ", w - #win.name -1 -#window_buttons),1,w))
|
||||
if win.resizable and not win.isFullscreen then
|
||||
term.setCursorPos(x+w-1,y+h-1)
|
||||
term.write("\127")
|
||||
end
|
||||
end
|
||||
term.setCursorPos(win.x + win.cursorX - 1, win.y + win.cursorY - 1)
|
||||
term.setCursorBlink(win.cursorBlink)
|
||||
term.setCursorPos(x + win.cursorX - 1, y + win.cursorY - 1)
|
||||
nterm.setCursorBlink(win.cursorBlink)
|
||||
if win.closing then
|
||||
_G.windows[id] = nil
|
||||
end
|
||||
@@ -82,15 +117,13 @@ local function windows()
|
||||
end
|
||||
|
||||
local function desktop()
|
||||
local image = nft.load(".wallpaper.nft")
|
||||
local paint_image = paintutils.loadImage(".wallpaper.nfp")
|
||||
local w, h = term.getSize()
|
||||
term.setBackgroundColor(colors.white)
|
||||
term.clear()
|
||||
if image then
|
||||
nft.draw(image,1,1)
|
||||
elseif paint_image then
|
||||
paintutils.drawImage(paint_image,1,2)
|
||||
drawImage(paint_image,1,2)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -118,11 +151,40 @@ for _, i in ipairs(fs.list("/modules")) do
|
||||
end
|
||||
end
|
||||
|
||||
local function screen()
|
||||
local cx,cy = term.getCursorPos()
|
||||
for cy = 1, term.h do
|
||||
nterm.setCursorPos(term.x, term.y + cy - 1)
|
||||
local line, fg, bg = "", "", ""
|
||||
for cx = 1, term.w do
|
||||
if term.buffer[cx] then
|
||||
local cell = term.buffer[cx][cy]
|
||||
if cell then
|
||||
line = line .. cell.char
|
||||
fg = fg .. ("0123456789abcdef"):sub(math.log(cell.tc, 2) + 1, math.log(cell.tc, 2) + 1)
|
||||
bg = bg .. ("0123456789abcdef"):sub(math.log(cell.bc, 2) + 1, math.log(cell.bc, 2) + 1)
|
||||
else
|
||||
line = line .. " "
|
||||
fg = fg .. "0"
|
||||
bg = bg .. "f"
|
||||
end
|
||||
else
|
||||
line = line .. " "
|
||||
fg = fg .. "0"
|
||||
bg = bg .. "f"
|
||||
end
|
||||
end
|
||||
nterm.blit(line, fg, bg)
|
||||
end
|
||||
nterm.setCursorPos(cx,cy)
|
||||
end
|
||||
|
||||
local function render()
|
||||
while true do
|
||||
desktop()
|
||||
windows()
|
||||
bars()
|
||||
screen()
|
||||
sleep(1 / 20)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user