Compare commits
13 Commits
b0f8c1267a
...
erica
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92d97c8773 | ||
|
|
e5cd5c6e71 | ||
| 2fcea0909d | |||
|
|
4ff7e3216c | ||
|
|
6edfa118b1 | ||
|
|
3772d67726 | ||
|
7e21413e7b
|
|||
|
80f91cbcd9
|
|||
|
4d157bfee4
|
|||
|
db862f12ef
|
|||
|
fc349f46e4
|
|||
|
6cf175e5f0
|
|||
|
c7d7f9be98
|
1
dev-server/.envrc
Normal file
1
dev-server/.envrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
use flake
|
||||||
2
dev-server/.gitignore
vendored
Normal file
2
dev-server/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.direnv
|
||||||
|
node_modules
|
||||||
47
dev-server/bun.lock
Normal file
47
dev-server/bun.lock
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "dev-server",
|
||||||
|
"dependencies": {
|
||||||
|
"@elysiajs/static": "^1.2.0",
|
||||||
|
"elysia": "^1.2.25",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@elysiajs/static": ["@elysiajs/static@1.2.0", "", { "dependencies": { "node-cache": "^5.1.2" }, "peerDependencies": { "elysia": ">= 1.2.0" } }, "sha512-oLpAi8c+maPpA0XhhK3BELaIjIG+nXg/K9p8cFfW4q5ayRD59a3MOMOOGgpiXZkHJzLPWcouhhyyLAYtaANW4g=="],
|
||||||
|
|
||||||
|
"@sinclair/typebox": ["@sinclair/typebox@0.34.31", "", {}, "sha512-qQ71T9DsITbX3dVCrcBERbs11YuSMg3wZPnT472JhqhWGPdiLgyvihJXU8m+ADJtJvRdjATIiACJD22dEknBrQ=="],
|
||||||
|
|
||||||
|
"@types/bun": ["@types/bun@1.2.8", "", { "dependencies": { "bun-types": "1.2.7" } }, "sha512-t8L1RvJVUghW5V+M/fL3Thbxcs0HwNsXsnTEBEfEVqGteiJToOlZ/fyOEaR1kZsNqnu+3XA4RI/qmnX4w6+S+w=="],
|
||||||
|
|
||||||
|
"@types/node": ["@types/node@22.13.14", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w=="],
|
||||||
|
|
||||||
|
"@types/ws": ["@types/ws@8.18.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw=="],
|
||||||
|
|
||||||
|
"bun-types": ["bun-types@1.2.7", "", { "dependencies": { "@types/node": "*", "@types/ws": "*" } }, "sha512-P4hHhk7kjF99acXqKvltyuMQ2kf/rzIw3ylEDpCxDS9Xa0X0Yp/gJu/vDCucmWpiur5qJ0lwB2bWzOXa2GlHqA=="],
|
||||||
|
|
||||||
|
"clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="],
|
||||||
|
|
||||||
|
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
||||||
|
|
||||||
|
"elysia": ["elysia@1.2.25", "", { "dependencies": { "@sinclair/typebox": "^0.34.27", "cookie": "^1.0.2", "memoirist": "^0.3.0", "openapi-types": "^12.1.3" }, "peerDependencies": { "typescript": ">= 5.0.0" }, "optionalPeers": ["typescript"] }, "sha512-WsdQpORJvb4uszzeqYT0lg97knw1iBW1NTzJ1Jm57tiHg+DfAotlWXYbjmvQ039ssV0fYELDHinLLoUazZkEHg=="],
|
||||||
|
|
||||||
|
"memoirist": ["memoirist@0.3.0", "", {}, "sha512-wR+4chMgVPq+T6OOsk40u9Wlpw1Pjx66NMNiYxCQQ4EUJ7jDs3D9kTCeKdBOkvAiqXlHLVJlvYL01PvIJ1MPNg=="],
|
||||||
|
|
||||||
|
"node-cache": ["node-cache@5.1.2", "", { "dependencies": { "clone": "2.x" } }, "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg=="],
|
||||||
|
|
||||||
|
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="],
|
||||||
|
|
||||||
|
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
61
dev-server/flake.lock
generated
Normal file
61
dev-server/flake.lock
generated
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1742923925,
|
||||||
|
"narHash": "sha256-biPjLws6FiBVUUDHEMFq5pUQL84Wf7PntPYdo3oKkFw=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "25d1b84f5c90632a623c48d83a2faf156451e6b1",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"utils": "utils"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
17
dev-server/flake.nix
Normal file
17
dev-server/flake.nix
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, utils }:
|
||||||
|
utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
in {
|
||||||
|
devShell = with pkgs; mkShell {
|
||||||
|
buildInputs = with pkgs; [ bun ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
35
dev-server/index.ts
Normal file
35
dev-server/index.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { Elysia } from 'elysia'
|
||||||
|
import { staticPlugin } from "@elysiajs/static"
|
||||||
|
import { stat, readdir, readFile } from "node:fs/promises"
|
||||||
|
import { createHash } from "node:crypto";
|
||||||
|
|
||||||
|
type IndexEntry = { src: string, dest: string, hash: string };
|
||||||
|
|
||||||
|
async function scanDir(scanIn: string, base: string, outputBase: string): Promise<IndexEntry[]> {
|
||||||
|
let files = await readdir(scanIn + "/" + base);
|
||||||
|
let results: IndexEntry[] = [];
|
||||||
|
|
||||||
|
for (let file of files) {
|
||||||
|
if (await stat(scanIn + "/" + base + "/" + file).then(r => r.isDirectory())) {
|
||||||
|
results = [...results, ...(await scanDir(scanIn, base + "/" + file, outputBase + file + "/"))]
|
||||||
|
} else {
|
||||||
|
results.push({
|
||||||
|
src: base + "/" + file,
|
||||||
|
dest: outputBase + file,
|
||||||
|
hash: createHash('sha256').update(await readFile(scanIn + "/" + base + "/" + file)).digest('hex')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
new Elysia()
|
||||||
|
.get("/index.json", async () => scanDir("..", "src", "/"))
|
||||||
|
.get("/sha256.lua", async () => Bun.file("../sha256.lua"))
|
||||||
|
.use(staticPlugin({
|
||||||
|
assets: "../src",
|
||||||
|
prefix: "/src"
|
||||||
|
}))
|
||||||
|
.get("/install.lua", async () => Bun.file("../install.lua"))
|
||||||
|
.listen(parseInt(process.env.PORT || "3000"))
|
||||||
16
dev-server/package.json
Normal file
16
dev-server/package.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "dev-server",
|
||||||
|
"module": "index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@elysiajs/static": "^1.2.0",
|
||||||
|
"elysia": "^1.2.25"
|
||||||
|
}
|
||||||
|
}
|
||||||
28
dev-server/tsconfig.json
Normal file
28
dev-server/tsconfig.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Environment setup & latest features
|
||||||
|
"lib": ["esnext"],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
// Best practices
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,11 @@
|
|||||||
{
|
{
|
||||||
"src": "src/startup.lua",
|
"src": "src/startup.lua",
|
||||||
"dest": "/startup.lua",
|
"dest": "/startup.lua",
|
||||||
"hash": "07219cd9561b41ce1f39209958076c471b17855679c968b42767b0122423c782"
|
"hash": "38b4f27b677716688ce5c27f416a3e4605e03d1a07f76df7b5ef1cedf4f355ea"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "src/kernel/entry.lua",
|
||||||
|
"dest": "/kernel/entry.lua",
|
||||||
|
"hash": "5d17a09860a3d14346105e363c0b3333bf720c75c4670add778fd20a736dafb7"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
20
install.lua
20
install.lua
@@ -1,4 +1,5 @@
|
|||||||
local repoRoot = "https://git.colon-three.com/kodi/snowier/raw/branch/main/"
|
local defaultRoot = "https://git.colon-three.com/kodi/snowier/raw/branch/main/"
|
||||||
|
local repoRoot = settings.get("snowier.repo_base") or defaultRoot
|
||||||
|
|
||||||
local URLs = {
|
local URLs = {
|
||||||
fileIndex = repoRoot .. "index.json",
|
fileIndex = repoRoot .. "index.json",
|
||||||
@@ -33,12 +34,12 @@ local function main()
|
|||||||
shafile.close()
|
shafile.close()
|
||||||
sharequest.close()
|
sharequest.close()
|
||||||
end
|
end
|
||||||
log.debug(package.path)
|
package.path = package.path .. ";/?;/?.lua" -- hack to solve 'wget run'
|
||||||
local hash = require("sha256")
|
local hash = require("sha256")
|
||||||
|
|
||||||
log.info("Downloading index file")
|
log.info("Downloading index file")
|
||||||
local indexrequest = http.get(URLs.fileIndex)
|
local indexrequest = http.get(URLs.fileIndex)
|
||||||
local index = textutils.unserializeJson(request.readAll())
|
local index = textutils.unserializeJSON(indexrequest.readAll())
|
||||||
indexrequest.close()
|
indexrequest.close()
|
||||||
|
|
||||||
if (index == nil) then
|
if (index == nil) then
|
||||||
@@ -58,12 +59,13 @@ local function main()
|
|||||||
local destfile = fs.open(v.dest, "r")
|
local destfile = fs.open(v.dest, "r")
|
||||||
local filehash = hash.sha256(destfile.readAll())
|
local filehash = hash.sha256(destfile.readAll())
|
||||||
destfile.close()
|
destfile.close()
|
||||||
if filehash ~= v.sha256 then
|
if filehash ~= v.hash then
|
||||||
toDownload[#toDownload+1] = v
|
toDownload[#toDownload+1] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if #toDownload > 0 then
|
||||||
log.info(#toDownload .. " files to download")
|
log.info(#toDownload .. " files to download")
|
||||||
for k, v in ipairs(toDownload) do
|
for k, v in ipairs(toDownload) do
|
||||||
if not fs.exists("/tmp") then
|
if not fs.exists("/tmp") then
|
||||||
@@ -82,14 +84,20 @@ local function main()
|
|||||||
tempfile.close()
|
tempfile.close()
|
||||||
if filehash ~= v.hash then
|
if filehash ~= v.hash then
|
||||||
log.error("File " .. v.dest .. " (from " .. v.src .. ") has a mismatched hash.")
|
log.error("File " .. v.dest .. " (from " .. v.src .. ") has a mismatched hash.")
|
||||||
log.error("Installation aborted.")
|
log.error("Installation aborted. Remember to clean /tmp manually.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
log.info("Installing")
|
log.info("Installing")
|
||||||
for k, v in ipairs(toDownload) do
|
for k, v in ipairs(toDownload) do
|
||||||
fs.move("/tmp/" .. v.hash .. ".lua", v.dest)
|
fs.delete(v.dest)
|
||||||
|
fs.copy("/tmp/" .. v.hash .. ".lua", v.dest)
|
||||||
|
end
|
||||||
|
|
||||||
|
fs.delete("/tmp/")
|
||||||
|
else
|
||||||
|
log.info("Nothing to do")
|
||||||
end
|
end
|
||||||
|
|
||||||
log.info("Installation complete!")
|
log.info("Installation complete!")
|
||||||
|
|||||||
25
sha256.lua
25
sha256.lua
@@ -193,6 +193,9 @@ if print_debug_messages then
|
|||||||
print(" "..method)
|
print(" "..method)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- For computercraft, use emulated mode for the sake of compatibility
|
||||||
|
branch = "EMUL"
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- BASIC 32-BIT BITWISE FUNCTIONS
|
-- BASIC 32-BIT BITWISE FUNCTIONS
|
||||||
@@ -208,8 +211,6 @@ if branch == "FFI" or branch == "LJ" or branch == "LIB32" then
|
|||||||
|
|
||||||
-- Your system has 32-bit bitwise library (either "bit" or "bit32")
|
-- Your system has 32-bit bitwise library (either "bit" or "bit32")
|
||||||
|
|
||||||
-- ADJUSTED FOR COMPUTERCRAFT
|
|
||||||
|
|
||||||
AND = b.band -- 2 arguments
|
AND = b.band -- 2 arguments
|
||||||
OR = b.bor -- 2 arguments
|
OR = b.bor -- 2 arguments
|
||||||
XOR = b.bxor -- 2..5 arguments
|
XOR = b.bxor -- 2..5 arguments
|
||||||
@@ -219,17 +220,17 @@ if branch == "FFI" or branch == "LJ" or branch == "LIB32" then
|
|||||||
SHR = b.brshift
|
SHR = b.brshift
|
||||||
-- ROL = b.rol or b.lrotate -- second argument is integer 0..31
|
-- ROL = b.rol or b.lrotate -- second argument is integer 0..31
|
||||||
-- ROR = b.ror or b.rrotate -- second argument is integer 0..31
|
-- ROR = b.ror or b.rrotate -- second argument is integer 0..31
|
||||||
function ROL(x, n)
|
--function ROL(x, n)
|
||||||
x = x % 2^32 * 2^n
|
-- x = x % 2^32 * 2^n
|
||||||
local r = x % 2^32
|
-- local r = x % 2^32
|
||||||
return r + (x - r) / 2^32
|
-- return r + (x - r) / 2^32
|
||||||
end
|
--end
|
||||||
|
|
||||||
function ROR(x, n)
|
--function ROR(x, n)
|
||||||
x = x % 2^32 / 2^n
|
-- x = x % 2^32 / 2^n
|
||||||
local r = x % 1
|
-- local r = x % 1
|
||||||
return r * 2^32 + (x - r)
|
-- return r * 2^32 + (x - r)
|
||||||
end
|
--end
|
||||||
|
|
||||||
NOT = b.bnot -- only for LuaJIT
|
NOT = b.bnot -- only for LuaJIT
|
||||||
NORM = b.tobit -- only for LuaJIT
|
NORM = b.tobit -- only for LuaJIT
|
||||||
|
|||||||
7
src/kernel/entry.lua
Normal file
7
src/kernel/entry.lua
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
-- kernel entrypoint
|
||||||
|
-- this is responsible for initializing core kernel services
|
||||||
|
-- required to advance to the next step of the OS
|
||||||
|
|
||||||
|
require 'kernel.system'
|
||||||
|
|
||||||
|
os.run({}, "/rom/programs/advanced/multishell.lua") -- placeholder
|
||||||
117
src/kernel/system.lua
Normal file
117
src/kernel/system.lua
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
--[[
|
||||||
|
The Erica Actor System ([Er]lang + A[kka])
|
||||||
|
|
||||||
|
Each actor has:
|
||||||
|
- Coroutine
|
||||||
|
- Mailbox
|
||||||
|
- Address
|
||||||
|
- Extra Addresses
|
||||||
|
- State
|
||||||
|
- Child IDs
|
||||||
|
|
||||||
|
The Actor System utilizes coroutine yielding for all invocations of the system. No global APIs are exposed by the system.
|
||||||
|
The following calls are available to actors:
|
||||||
|
- spawn function:handler table?:options
|
||||||
|
The options table exposes the following:
|
||||||
|
- addressBase | default: seedocs | If not provided, the address will take this form: "$currentAddress/$childId" and childId gets incremented
|
||||||
|
| in local state.
|
||||||
|
| If provided, the global address base counter gets updated and the provided address base is used.
|
||||||
|
| Actors created without an address base are considered child actors of the current actor,
|
||||||
|
| and their status updates (death) will emit status update events to the next immediate parent.
|
||||||
|
| The death of an actor will kill all of it's children recursively.
|
||||||
|
- localNamespace| default: nil | If set, adds the localNamespace into the address of the newly spawned actor.
|
||||||
|
- extraAddresses| default: {} | Logic for global base addresses, that are used to add receive-only extra addresses to this actor.
|
||||||
|
The returned value is: bStatus, tAddress?
|
||||||
|
- bStatus: True if successful, false if failed
|
||||||
|
- tAddress: Address of newly spawned actor
|
||||||
|
|
||||||
|
- tell addressPredicate:string ...content
|
||||||
|
Any instances of `?` in addressPredicate are replaced with a random valid instance.
|
||||||
|
Adds a message of "content" to the mailbox of the target actor
|
||||||
|
The returned value is: bStatus, sData?
|
||||||
|
- bStatus: True if successful, false if failed
|
||||||
|
- sData: The error string if status is false, for example no valid instances.
|
||||||
|
If status is true, actor address that received this tell.
|
||||||
|
|
||||||
|
- announce addressPredicate:string ...content
|
||||||
|
Any instances of `?` in addressPredicate are replaced with all valid instances.
|
||||||
|
Adds a message of "content" to the mailbox of the target actor
|
||||||
|
The returned value is: bStatus, data?
|
||||||
|
- bStatus: True if successful, false if failed
|
||||||
|
- data: The error string if status is false, for example no valid instances.
|
||||||
|
If status is true, amount of actors that received this announcement.
|
||||||
|
|
||||||
|
- ask addressPredicate:string timeout:number ...content
|
||||||
|
Suspends this actor until the responseHandle is used with the "reply" or "fail" syscall,
|
||||||
|
or until the timeout elapses. The timeout elapsing invalidates the handle and makes calls to "reply" or "fail" fail silently.
|
||||||
|
The return value is:
|
||||||
|
- bStatus: If the ask was successful
|
||||||
|
- ...data: If the status is false, this contains the reason for the error.
|
||||||
|
If the status is true, the first value is the actor asked, and subsequent data contains the response from the actor asked.
|
||||||
|
|
||||||
|
- reply askHandle:string ...data
|
||||||
|
Replies to an ask. Returns nil.
|
||||||
|
|
||||||
|
- fail askHandle:string ...reason
|
||||||
|
Fails an ask. Returns nil.
|
||||||
|
|
||||||
|
- idle timeout:number receiveUnfiltered?:bool
|
||||||
|
Notifies the actor system that this actor is ready to process events. Values returned by this call are described below, in the signals section.
|
||||||
|
If receiveUnfiltered is set, the actor will receive "hostEvent" signals without any filtering.
|
||||||
|
|
||||||
|
Signals:
|
||||||
|
- timeout
|
||||||
|
When the idle call times out. No extra params
|
||||||
|
- message sourceAddress:string {content}
|
||||||
|
When a message is received from another actor.
|
||||||
|
- ask replyHandle:string sourceAddress:string {content}
|
||||||
|
When an ask is received from another actor. Good idea to immediately fail any asks that the current actor doesn't recognize.
|
||||||
|
- childStatus address:string {newStatus}
|
||||||
|
When a child's status updates (coroutine.status() call)
|
||||||
|
- hostEvent {data}
|
||||||
|
ComputerCraft event from the top level coroutine.yield() call. Use with caution, generally this should only be used by actors
|
||||||
|
that propagate events to announcement channels.
|
||||||
|
|
||||||
|
Addresses
|
||||||
|
There are 3 types of address:
|
||||||
|
- Fully Qualified Address
|
||||||
|
- Local Address
|
||||||
|
- Relative Address
|
||||||
|
|
||||||
|
Fully Qualified addresses take on the following format:
|
||||||
|
systemId .. ":/" .. localAddressWithinSystem
|
||||||
|
|
||||||
|
The purpose of fully qualified addresses is to be provided by the system to actors to have unambigous resolution of actors.
|
||||||
|
User-written code generally shouldn't need to use fully qualified addresses, because their primary use case is future compatibility
|
||||||
|
with a version of this system that allows multi-node operation (and setting wildcards on systemId)
|
||||||
|
|
||||||
|
Local Addresses are full addresses within a single system.
|
||||||
|
The "child:" prefix is reserved in address parts only for automatically-generated addresses, and manual usage of it in addresses
|
||||||
|
is considered undefined behavior.
|
||||||
|
|
||||||
|
Here is an example address of the first actor spawned within the "com/colon-three/someApp" namespace:
|
||||||
|
"com/colon-three/someApp/1" (subsequent actors are 2, 3, 4, etc. Monotonically increasing, but not guaranteed. Do not rely on this.)
|
||||||
|
|
||||||
|
If that actor then makes a child, that child's address is:
|
||||||
|
"com/colon-three/someApp/1/child:1"
|
||||||
|
|
||||||
|
And if that child makes another child, that child's address is:
|
||||||
|
"com/colon-three/someApp/1/child:1/child:1"
|
||||||
|
|
||||||
|
If that actor makes a child with the local namespace of "someNs", the address will be:
|
||||||
|
"com/colon-three/someApp/1/someNs/child:2" (because child:1 for this actor already exists, and namespaces are for filtering only.)
|
||||||
|
|
||||||
|
Every address of an actual actor ends with either a plain number, or the "child:number" template.
|
||||||
|
|
||||||
|
Relative Addresses:
|
||||||
|
Used only in calls, and taking the following format:
|
||||||
|
".." - refer to the parent actor. IGNORES NAMESPACES!!!
|
||||||
|
"../someNs" - refer to parent actor's "someNs". Ignores the current actor's namespace.
|
||||||
|
"./someNs" - refer to the current actor's someNs namespace.
|
||||||
|
|
||||||
|
Allows asking the parent something, or the parent broadcasting something to all of it's children, or children in a specific namespace.
|
||||||
|
This is generally only useful with `?` in asks or broadcasts, because a child's ID shouldn't be considered predictable.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local tActors = {}
|
||||||
|
local tAddressBases = {}
|
||||||
@@ -1 +1,48 @@
|
|||||||
print("Hello, World!")
|
-- Bootloader
|
||||||
|
-- This script is only responsible for killing rednet and jumping to the kernel
|
||||||
|
|
||||||
|
-- based on some code rph wrote and gave me
|
||||||
|
|
||||||
|
if settings.get("snowier.auto_update") then
|
||||||
|
local defaultRoot = "https://git.colon-three.com/kodi/snowier/raw/branch/main/"
|
||||||
|
local repoRoot = settings.get("snowier.repo_base") or defaultRoot
|
||||||
|
|
||||||
|
shell.run("wget run " .. repoRoot .. "install.lua")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function main()
|
||||||
|
if not _G["rednet"] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local o = os.pullEventRaw
|
||||||
|
|
||||||
|
os.pullEventRaw = function()
|
||||||
|
local a = table.pack(o())
|
||||||
|
if a[1] == "modem_message" then
|
||||||
|
if string.match(debug.traceback(), "/rom/apis/rednet.lua") then
|
||||||
|
print("[D] Rednet called os.pullEventRaw, crashing")
|
||||||
|
error("nya")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.unpack(a)
|
||||||
|
end
|
||||||
|
|
||||||
|
local p = _G.printError
|
||||||
|
|
||||||
|
_G.printError = function()
|
||||||
|
print("[D] Got printError call, cleaning and jumping to kernel")
|
||||||
|
_G.printError = p
|
||||||
|
_G.os.pullEventRaw = o
|
||||||
|
_G["rednet"] = nil
|
||||||
|
os.run({
|
||||||
|
-- This is an odd hack. We should look into not doing this to run the kernel.
|
||||||
|
["require"]=require
|
||||||
|
}, "/kernel/entry.lua")
|
||||||
|
end
|
||||||
|
|
||||||
|
print("[D] Queueing bogus modem message")
|
||||||
|
os.queueEvent("modem_message")
|
||||||
|
end
|
||||||
|
|
||||||
|
main()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
open index.json
|
open index.json
|
||||||
| each {|entry|
|
| each {|entry|
|
||||||
{src: $entry.src, dest: $entry.dest,
|
{src: $entry.src, dest: $entry.dest,
|
||||||
hash: (cat $entry.src | hash sha256)}
|
hash: (open $entry.src | hash sha256)}
|
||||||
}
|
}
|
||||||
| collect
|
| collect
|
||||||
| save -f index.json
|
| save -f index.json
|
||||||
|
|||||||
Reference in New Issue
Block a user