Implement main game as a mod
This commit is contained in:
+40
-19
@@ -1,41 +1,30 @@
|
||||
/// <reference lib="deno.worker" />
|
||||
|
||||
// runs the game in a worker without any permissions, the host does files and networking
|
||||
import { GameServer, TICK_MS } from "./game_server.ts";
|
||||
import type { GameServer } from "./game_server.ts";
|
||||
import { TICK_MS } from "./game_server.ts";
|
||||
import { GameToHost, HostToGame } from "./host_protocol.ts";
|
||||
import { data_url, start_game } from "./load_mods.ts";
|
||||
|
||||
const SAVE_INTERVAL_MS = 30_000;
|
||||
|
||||
let game: GameServer | undefined;
|
||||
let starting: Promise<void> | undefined;
|
||||
|
||||
function post(message: GameToHost) {
|
||||
self.postMessage(message);
|
||||
}
|
||||
|
||||
self.onmessage = (event: MessageEvent<HostToGame>) => {
|
||||
self.onmessage = async (event: MessageEvent<HostToGame>) => {
|
||||
const message = event.data;
|
||||
|
||||
if (message.type === "init") {
|
||||
game = new GameServer(
|
||||
{
|
||||
send: (conn, data) => post({ type: "send", conn, data }),
|
||||
close: (conn) => post({ type: "close", conn }),
|
||||
},
|
||||
message.save,
|
||||
message.default_seed,
|
||||
);
|
||||
|
||||
setInterval(() => game!.tick(), TICK_MS);
|
||||
setInterval(() => {
|
||||
if (game!.world.dirty) {
|
||||
post({ type: "save", data: game!.save(), final: false });
|
||||
}
|
||||
}, SAVE_INTERVAL_MS);
|
||||
|
||||
post({ type: "ready", seed: game.world.seed });
|
||||
starting = init(message);
|
||||
return;
|
||||
}
|
||||
|
||||
// players can connect while mods are still loading
|
||||
await starting;
|
||||
if (!game) {
|
||||
return;
|
||||
}
|
||||
@@ -55,3 +44,35 @@ self.onmessage = (event: MessageEvent<HostToGame>) => {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
async function init(message: Extract<HostToGame, { type: "init" }>) {
|
||||
try {
|
||||
game = await start_game(
|
||||
{
|
||||
send: (conn, data) => post({ type: "send", conn, data }),
|
||||
close: (conn) => post({ type: "close", conn }),
|
||||
},
|
||||
message.save,
|
||||
message.default_seed,
|
||||
message.mods.map((mod) => ({
|
||||
listing: mod.listing,
|
||||
data: mod.data,
|
||||
// the worker has no file access, so the host sends the code and it's imported from memory
|
||||
server_url: mod.server_code ? data_url(mod.server_code) : undefined,
|
||||
worldgen_url: mod.worldgen_code ? data_url(mod.worldgen_code) : undefined,
|
||||
})),
|
||||
);
|
||||
} catch (e) {
|
||||
post({ type: "failed", error: e instanceof Error ? e.message : String(e) });
|
||||
return;
|
||||
}
|
||||
|
||||
setInterval(() => game!.tick(), TICK_MS);
|
||||
setInterval(() => {
|
||||
if (game!.world.dirty) {
|
||||
post({ type: "save", data: game!.save(), final: false });
|
||||
}
|
||||
}, SAVE_INTERVAL_MS);
|
||||
|
||||
post({ type: "ready", seed: game.world.seed });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user