Implement main game as a mod
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { resolve, toFileUrl } from "@std/path";
|
||||
import { EverythingRegistry } from "$/common/everything_registry.ts";
|
||||
import { load_and_check, load_order } from "$/tools/check_mods.ts";
|
||||
import type { ServerModSource } from "$/server/game/load_mods.ts";
|
||||
import { GameServer } from "$/server/game/game_server.ts";
|
||||
import { start_game } from "$/server/game/load_mods.ts";
|
||||
|
||||
// mods straight from their source folders, skipping the build: scripts are imported as typescript
|
||||
export function mod_sources(mods_dir: string): ServerModSource[] {
|
||||
const mods = load_and_check(mods_dir);
|
||||
const errors = mods.flatMap((mod) => mod.report.errors.map((e) => `${mod.id}: ${e}`));
|
||||
if (errors.length) throw new Error(errors.join("\n"));
|
||||
return load_order(mods).map((mod) => {
|
||||
const scripts = (mod.manifest?.scripts ?? {}) as Record<string, string>;
|
||||
const url = (path?: string) => path ? toFileUrl(resolve(mod.dir, path)).href : undefined;
|
||||
return {
|
||||
listing: {
|
||||
id: mod.id,
|
||||
name: String(mod.manifest?.name),
|
||||
version: String(mod.manifest?.version),
|
||||
hash: "source",
|
||||
data: `mods/${mod.id}/source/data.json`,
|
||||
},
|
||||
data: {
|
||||
blocks: mod.blocks.map((b) => b.json),
|
||||
items: mod.items.map((i) => i.json),
|
||||
recipes: mod.recipes.map((r) => r.json),
|
||||
ores: mod.ores.map((o) => o.json),
|
||||
},
|
||||
server_url: url(scripts.server),
|
||||
worldgen_url: url(scripts.worldgen),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// a game with an in memory host that remembers what it sent to each connection
|
||||
export async function test_game(mods_dir: string, save?: string, seed = "test-seed") {
|
||||
EverythingRegistry.clear();
|
||||
const outbox = new Map<number, unknown[]>();
|
||||
const host = {
|
||||
send: (conn: number, data: string) => {
|
||||
if (!outbox.has(conn)) outbox.set(conn, []);
|
||||
outbox.get(conn)!.push(JSON.parse(data));
|
||||
},
|
||||
close() {},
|
||||
};
|
||||
const game: GameServer = await start_game(host, save, seed, mod_sources(mods_dir));
|
||||
// deno-lint-ignore no-explicit-any
|
||||
const take = (conn: number): any[] => {
|
||||
const messages = outbox.get(conn) ?? [];
|
||||
outbox.set(conn, []);
|
||||
return messages;
|
||||
};
|
||||
const send = (conn: number, message: unknown) => game.on_message(conn, JSON.stringify(message));
|
||||
return { game, take, send };
|
||||
}
|
||||
|
||||
export function copy_dir(from: string, to: string) {
|
||||
if (Deno.statSync(from).isDirectory) {
|
||||
Deno.mkdirSync(to, { recursive: true });
|
||||
for (const entry of Deno.readDirSync(from)) copy_dir(`${from}/${entry.name}`, `${to}/${entry.name}`);
|
||||
} else {
|
||||
Deno.copyFileSync(from, to);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user