This commit is contained in:
Crispy 2025-07-03 01:23:46 +02:00
parent 491112768c
commit 68ec37f994
66 changed files with 6591 additions and 10096 deletions

View file

@ -1,4 +1,5 @@
{
[ "shell.allow_disk_startup" ] = false,
[ "motd.enable" ] = false,
[ "motd.path" ] = "/rom/motd.txt:/motd.txt:/rom/cccbridge_motd.txt",
[ "motd.path" ] = "/rom/motd.txt:/motd.txt:/rom/cccbridge_motd.txt:/rom/cccbridge_motd.txt",
}

11
computer/15/bg.lua Normal file
View file

@ -0,0 +1,11 @@
if not shell.openTab then
printError("Requires multishell")
return
end
local tArgs = { ... }
if #tArgs > 0 then
shell.openTab(table.unpack(tArgs))
else
shell.openTab("shell")
end

80
computer/15/dirt.lua Normal file
View file

@ -0,0 +1,80 @@
basin = peripheral.wrap("top")
base_item = "dirt"
levels = {
compressed = 1,
double_compressed = 2,
triple_compressed = 3,
quadruple_compressed = 4,
quintuple_compressed = 5,
sextuple_compressed = 6,
septuple_compressed = 7,
octuple_compressed = 8,
}
unpacked = {
9,
81,
729,
6561,
59049,
531441,
4782969,
43046721
}
last_total = 0
last_estimate_time = 0
estimate_interval_h = 30/3600
estimated_speed = 0
function update()
local counts = {}
local raw = basin.list()
local total = 0
for _, item in pairs(raw) do
name = string.sub(item.name, string.len("compressor:_"), -string.len(base_item)-2)
count = item.count
if levels[name] then
counts[levels[name]] = count
total = total + unpacked[levels[name]] * count
end
end
local time = os.time("utc")
if time - last_estimate_time >= estimate_interval_h then
last_estimate_time = time
estimated_speed = (total - last_total) / (estimate_interval_h * 3600)
last_total = total
end
-- draw
term.clear()
term.setCursorPos(1,1)
print(base_item, "progress")
for level = 1, 7 do
local count = counts[level] or 0
local bar = string.rep("#", count) .. string.rep(".", 9 - count)
print("lvl", level, bar)
end
print("total: ", total)
local progress = math.floor(total / unpacked[8] * 10000) / 100
print("progress to octuple: " .. progress .. "%")
print("speed:", estimated_speed, base_item.."/s")
local eta = math.floor((unpacked[8] - progress) / estimated_speed + 0.5)
local eta_s = eta % 60
local eta_m = math.floor(eta / 60) % 60
local eta_h = math.floor(eta / 3600) % 24
local eta_d = math.floor(eta / 86400)
-- print(eta)
print("time remaining: ", eta_d .. "d", eta_h .. ":" .. eta_m .. ":" .. eta_s)
local n = math.floor(30 * (time - last_estimate_time) / estimate_interval_h)
print(string.rep(",", n)..string.rep(".", 32-n))
end
while true do
update()
sleep(2)
end

36
computer/15/lock.lua Normal file
View file

@ -0,0 +1,36 @@
term.clear()
term.setCursorPos(1,1)
print("Chaos Gremlin Protection System")
local secret = ""
local input = ""
write("log in: ")
while true do
local event, extra = os.pullEventRaw()
if event == "terminate" then
print("\nnice try")
write("log in: ")
input = ""
elseif event == "char" then
input = input .. extra
write("*")
elseif event == "key" then
if extra == 259 and #input > 0 then
x, y = term.getCursorPos()
x = x - 1
term.setCursorPos(x, y)
write(" ")
term.setCursorPos(x, y)
input = string.sub(input, 1, string.len(input) - 1)
elseif extra == 257 then
if input == secret then
break
else
print("\nbegone, intruder\n\""..input.."\" is wrong")
write("log in: ")
input = ""
end
end
end
end
print()

View file

@ -1 +0,0 @@
require("startup")

429
computer/15/multishell.lua Normal file
View file

@ -0,0 +1,429 @@
--- Multishell allows multiple programs to be run at the same time.
--
-- When multiple programs are running, it displays a tab bar at the top of the
-- screen, which allows you to switch between programs. New programs can be
-- launched using the `fg` or `bg` programs, or using the @{shell.openTab} and
-- @{multishell.launch} functions.
--
-- Each process is identified by its ID, which corresponds to its position in
-- the tab list. As tabs may be opened and closed, this ID is _not_ constant
-- over a program's run. As such, be careful not to use stale IDs.
--
-- As with @{shell}, @{multishell} is not a "true" API. Instead, it is a
-- standard program, which launches a shell and injects its API into the shell's
-- environment. This API is not available in the global environment, and so is
-- not available to @{os.loadAPI|APIs}.
--
-- @module[module] multishell
-- @since 1.6
local expect = dofile("rom/modules/main/cc/expect.lua").expect
-- Setup process switching
local parentTerm = term.current()
local w, h = parentTerm.getSize()
local tProcesses = {}
local nCurrentProcess = nil
local nRunningProcess = nil
local bShowMenu = false
local bWindowsResized = false
local nScrollPos = 1
local bScrollRight = false
local function selectProcess(n)
if nCurrentProcess ~= n then
if nCurrentProcess then
local tOldProcess = tProcesses[nCurrentProcess]
tOldProcess.window.setVisible(false)
end
nCurrentProcess = n
if nCurrentProcess then
local tNewProcess = tProcesses[nCurrentProcess]
tNewProcess.window.setVisible(true)
tNewProcess.bInteracted = true
end
end
end
local function setProcessTitle(n, sTitle)
tProcesses[n].sTitle = sTitle
end
local function resumeProcess(nProcess, sEvent, ...)
local tProcess = tProcesses[nProcess]
local sFilter = tProcess.sFilter
if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then
local nPreviousProcess = nRunningProcess
nRunningProcess = nProcess
term.redirect(tProcess.terminal)
local ok, result = coroutine.resume(tProcess.co, sEvent, ...)
tProcess.terminal = term.current()
if ok then
tProcess.sFilter = result
else
printError(result)
end
nRunningProcess = nPreviousProcess
end
end
local function launchProcess(bFocus, tProgramEnv, sProgramPath, ...)
local tProgramArgs = table.pack(...)
local nProcess = #tProcesses + 1
local tProcess = {}
tProcess.sTitle = fs.getName(sProgramPath)
if bShowMenu then
tProcess.window = window.create(parentTerm, 1, 2, w, h - 1, false)
else
tProcess.window = window.create(parentTerm, 1, 1, w, h, false)
end
tProcess.co = coroutine.create(function()
os.run(tProgramEnv, sProgramPath, table.unpack(tProgramArgs, 1, tProgramArgs.n))
if not tProcess.bInteracted then
term.setCursorBlink(false)
print("Press any key to continue")
os.pullEvent("char")
end
end)
tProcess.sFilter = nil
tProcess.terminal = tProcess.window
tProcess.bInteracted = false
tProcesses[nProcess] = tProcess
if bFocus then
selectProcess(nProcess)
end
resumeProcess(nProcess)
return nProcess
end
local function cullProcess(nProcess)
local tProcess = tProcesses[nProcess]
if coroutine.status(tProcess.co) == "dead" then
if nCurrentProcess == nProcess then
selectProcess(nil)
end
table.remove(tProcesses, nProcess)
if nCurrentProcess == nil then
if nProcess > 1 then
selectProcess(nProcess - 1)
elseif #tProcesses > 0 then
selectProcess(1)
end
end
if nScrollPos ~= 1 then
nScrollPos = nScrollPos - 1
end
return true
end
return false
end
local function cullProcesses()
local culled = false
for n = #tProcesses, 1, -1 do
culled = culled or cullProcess(n)
end
return culled
end
-- Setup the main menu
local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor
if parentTerm.isColor() then
menuMainTextColor, menuMainBgColor = colors.yellow, colors.black
menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray
else
menuMainTextColor, menuMainBgColor = colors.white, colors.black
menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray
end
local function redrawMenu()
if bShowMenu then
-- Draw menu
parentTerm.setCursorPos(1, 1)
parentTerm.setBackgroundColor(menuOtherBgColor)
parentTerm.clearLine()
local nCharCount = 0
local nSize = parentTerm.getSize()
if nScrollPos ~= 1 then
parentTerm.setTextColor(menuOtherTextColor)
parentTerm.setBackgroundColor(menuOtherBgColor)
parentTerm.write("<")
nCharCount = 1
end
for n = nScrollPos, #tProcesses do
if n == nCurrentProcess then
parentTerm.setTextColor(menuMainTextColor)
parentTerm.setBackgroundColor(menuMainBgColor)
else
parentTerm.setTextColor(menuOtherTextColor)
parentTerm.setBackgroundColor(menuOtherBgColor)
end
parentTerm.write(" " .. tProcesses[n].sTitle .. " ")
nCharCount = nCharCount + #tProcesses[n].sTitle + 2
end
if nCharCount > nSize then
parentTerm.setTextColor(menuOtherTextColor)
parentTerm.setBackgroundColor(menuOtherBgColor)
parentTerm.setCursorPos(nSize, 1)
parentTerm.write(">")
bScrollRight = true
else
bScrollRight = false
end
-- Put the cursor back where it should be
local tProcess = tProcesses[nCurrentProcess]
if tProcess then
tProcess.window.restoreCursor()
end
end
end
local function resizeWindows()
local windowY, windowHeight
if bShowMenu then
windowY = 2
windowHeight = h - 1
else
windowY = 1
windowHeight = h
end
for n = 1, #tProcesses do
local tProcess = tProcesses[n]
local x, y = tProcess.window.getCursorPos()
if y > windowHeight then
tProcess.window.scroll(y - windowHeight)
tProcess.window.setCursorPos(x, windowHeight)
end
tProcess.window.reposition(1, windowY, w, windowHeight)
end
bWindowsResized = true
end
local function setMenuVisible(bVis)
if bShowMenu ~= bVis then
bShowMenu = bVis
resizeWindows()
redrawMenu()
end
end
local multishell = {} --- @export
--- Get the currently visible process. This will be the one selected on
-- the tab bar.
--
-- Note, this is different to @{getCurrent}, which returns the process which is
-- currently executing.
--
-- @treturn number The currently visible process's index.
-- @see setFocus
function multishell.getFocus()
return nCurrentProcess
end
--- Change the currently visible process.
--
-- @tparam number n The process index to switch to.
-- @treturn boolean If the process was changed successfully. This will
-- return @{false} if there is no process with this id.
-- @see getFocus
function multishell.setFocus(n)
expect(1, n, "number")
if n >= 1 and n <= #tProcesses then
selectProcess(n)
redrawMenu()
return true
end
return false
end
--- Get the title of the given tab.
--
-- This starts as the name of the program, but may be changed using
-- @{multishell.setTitle}.
-- @tparam number n The process index.
-- @treturn string|nil The current process title, or @{nil} if the
-- process doesn't exist.
function multishell.getTitle(n)
expect(1, n, "number")
if n >= 1 and n <= #tProcesses then
return tProcesses[n].sTitle
end
return nil
end
--- Set the title of the given process.
--
-- @tparam number n The process index.
-- @tparam string title The new process title.
-- @see getTitle
-- @usage Change the title of the current process
--
-- multishell.setTitle(multishell.getCurrent(), "Hello")
function multishell.setTitle(n, title)
expect(1, n, "number")
expect(2, title, "string")
if n >= 1 and n <= #tProcesses then
setProcessTitle(n, title)
redrawMenu()
end
end
--- Get the index of the currently running process.
--
-- @treturn number The currently running process.
function multishell.getCurrent()
return nRunningProcess
end
--- Start a new process, with the given environment, program and arguments.
--
-- The returned process index is not constant over the program's run. It can be
-- safely used immediately after launching (for instance, to update the title or
-- switch to that tab). However, after your program has yielded, it may no
-- longer be correct.
--
-- @tparam table tProgramEnv The environment to load the path under.
-- @tparam string sProgramPath The path to the program to run.
-- @param ... Additional arguments to pass to the program.
-- @treturn number The index of the created process.
-- @see os.run
-- @usage Run the "hello" program, and set its title to "Hello!"
--
-- local id = multishell.launch({}, "/rom/programs/fun/hello.lua")
-- multishell.setTitle(id, "Hello!")
function multishell.launch(tProgramEnv, sProgramPath, ...)
expect(1, tProgramEnv, "table")
expect(2, sProgramPath, "string")
local previousTerm = term.current()
setMenuVisible(#tProcesses + 1 >= 2)
local nResult = launchProcess(false, tProgramEnv, sProgramPath, ...)
redrawMenu()
term.redirect(previousTerm)
return nResult
end
--- Get the number of processes within this multishell.
--
-- @treturn number The number of processes.
function multishell.getCount()
return #tProcesses
end
-- Begin
parentTerm.clear()
setMenuVisible(false)
launchProcess(true, {
["shell"] = shell,
["multishell"] = multishell,
}, "/rom/programs/shell.lua")
-- Run processes
while #tProcesses > 0 do
-- Get the event
local tEventData = table.pack(os.pullEventRaw())
local sEvent = tEventData[1]
if sEvent == "term_resize" then
-- Resize event
w, h = parentTerm.getSize()
resizeWindows()
redrawMenu()
elseif sEvent == "char" or sEvent == "key" or sEvent == "key_up" or sEvent == "paste" or sEvent == "terminate" then
-- Keyboard event
-- Passthrough to current process
if tEventData[2] == 290 and sEvent == "key" then
multishell.setFocus((nCurrentProcess or 0) % #tProcesses + 1)
else
resumeProcess(nCurrentProcess, table.unpack(tEventData, 1, tEventData.n))
if cullProcess(nCurrentProcess) then
setMenuVisible(#tProcesses >= 2)
redrawMenu()
end
end
elseif sEvent == "mouse_click" then
-- Click event
local button, x, y = tEventData[2], tEventData[3], tEventData[4]
if bShowMenu and y == 1 then
-- Switch process
if x == 1 and nScrollPos ~= 1 then
nScrollPos = nScrollPos - 1
redrawMenu()
elseif bScrollRight and x == term.getSize() then
nScrollPos = nScrollPos + 1
redrawMenu()
else
local tabStart = 1
if nScrollPos ~= 1 then
tabStart = 2
end
for n = nScrollPos, #tProcesses do
local tabEnd = tabStart + #tProcesses[n].sTitle + 1
if x >= tabStart and x <= tabEnd then
selectProcess(n)
redrawMenu()
break
end
tabStart = tabEnd + 1
end
end
else
-- Passthrough to current process
resumeProcess(nCurrentProcess, sEvent, button, x, bShowMenu and y - 1 or y)
if cullProcess(nCurrentProcess) then
setMenuVisible(#tProcesses >= 2)
redrawMenu()
end
end
elseif sEvent == "mouse_drag" or sEvent == "mouse_up" or sEvent == "mouse_scroll" then
-- Other mouse event
local p1, x, y = tEventData[2], tEventData[3], tEventData[4]
if bShowMenu and sEvent == "mouse_scroll" and y == 1 then
if p1 == -1 and nScrollPos ~= 1 then
nScrollPos = nScrollPos - 1
redrawMenu()
elseif bScrollRight and p1 == 1 then
nScrollPos = nScrollPos + 1
redrawMenu()
end
elseif not (bShowMenu and y == 1) then
-- Passthrough to current process
resumeProcess(nCurrentProcess, sEvent, p1, x, bShowMenu and y - 1 or y)
if cullProcess(nCurrentProcess) then
setMenuVisible(#tProcesses >= 2)
redrawMenu()
end
end
else
-- Other event
-- Passthrough to all processes
local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event
for n = 1, nLimit do
resumeProcess(n, table.unpack(tEventData, 1, tEventData.n))
end
if cullProcesses() then
setMenuVisible(#tProcesses >= 2)
redrawMenu()
end
end
if bWindowsResized then
-- Pass term_resize to all processes
local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event
for n = 1, nLimit do
resumeProcess(n, "term_resize")
end
bWindowsResized = false
if cullProcesses() then
setMenuVisible(#tProcesses >= 2)
redrawMenu()
end
end
end
-- Shutdown
term.redirect(parentTerm)

View file

@ -1,48 +1,3 @@
term.clear()
term.setCursorPos(1,1)
print("Chaos Gremlin Protection System")
local secret = "mrrrp"
local input = ""
write("log in: ")
while true do
local event, extra = os.pullEventRaw()
if event == "terminate" then
print("\nnice try")
write("log in: ")
input = ""
elseif event == "char" then
input = input .. extra
write("*")
elseif event == "key" then
if extra == 259 and #input > 0 then
x, y = term.getCursorPos()
x = x - 1
term.setCursorPos(x, y)
write(" ")
term.setCursorPos(x, y)
input = string.sub(input, 1, string.len(input) - 1)
elseif extra == 257 then
if input == secret then
break
else
print("\nbegone, intruder\n\""..input.."\" is wrong")
write("log in: ")
input = ""
end
end
end
end
--require("multishell")
shell.execute("dirt")
print()
-- w = _G.write
-- p = _G.print
-- _G.write = function(text)
-- return w("meow ")
-- end
-- _G.print = function (...)
-- p("meow ")
-- end
-- b = term.blit
-- term.blit = function(text, fg, bg)
-- b("meow", fg, bg)
-- end