New modding system

This commit is contained in:
2026-09-26 17:33:07 -03:00
parent 86d5c39eab
commit 243ff52063
25 changed files with 1089 additions and 512 deletions
+19 -12
View File
@@ -6,7 +6,7 @@
import { fromFileUrl, join } from "@std/path";
import { type Host, serve_static, start_host } from "../server/host.ts";
// where the project was built from: build/ and server_mods/ are bundled into the app with --include
// where the project was built from: build/ and server_mods/ (the .bmod files) are bundled into the app with --include
const ROOT = fromFileUrl(new URL("../", import.meta.url));
const BUILD_DIR = join(ROOT, "build");
@@ -19,17 +19,16 @@ const default_server = Deno.env.get("BWORLD_SERVER") ?? config.server ?? "";
const win = new Deno.BrowserWindow({ title: "bworld", width: 1280, height: 720 });
// the singleplayer game server, started the first time singleplayer connects so players who only join other servers
// don't get a world made for them
let host: Host | undefined;
// don't get a world made for them. it plays the .bmod files the app was built with
let host: Promise<Host> | undefined;
function singleplayer_host(): Host {
if (!host) {
function singleplayer_host(): Promise<Host> {
host ??= (async () => {
const worlds = join(data_dir(), "worlds");
Deno.mkdirSync(worlds, { recursive: true });
host = start_host({
return await start_host({
build_dir: BUILD_DIR,
server_mods_dir: join(ROOT, "server_mods"),
root: ROOT,
world_file: join(worlds, "world.json"),
on_fatal(message) {
console.error(message);
@@ -37,7 +36,7 @@ function singleplayer_host(): Host {
Deno.exit(1);
},
});
}
})();
return host;
}
@@ -48,7 +47,7 @@ win.addEventListener("close", async (event) => {
}
event.preventDefault();
try {
await host.shutdown();
await (await host).shutdown();
} catch (e) {
console.error((e as Error).message);
}
@@ -56,7 +55,7 @@ win.addEventListener("close", async (event) => {
});
// deno desktop binds this to a private local address and opens the window on it, the port given here is ignored
Deno.serve((req) => {
Deno.serve(async (req) => {
const url = new URL(req.url);
if (url.pathname === "/") {
// ?server= fills in the address field, without it the field would start with this app's own address.
@@ -66,8 +65,16 @@ Deno.serve((req) => {
start.searchParams.set("singleplayer", "");
return Response.redirect(start, 302);
}
if (url.pathname === "/ws") {
return singleplayer_host().handle(req);
// the singleplayer server's socket and its .bmod downloads
if (url.pathname === "/ws" || url.pathname.startsWith("/mods/")) {
try {
return (await singleplayer_host()).handle(req);
} catch (e) {
// its mods have problems, the title screen shows why the connection failed
console.error((e as Error).message);
host = undefined;
return new Response((e as Error).message, { status: 500 });
}
}
return serve_static(BUILD_DIR, req, url);
});