Improve networking

This commit is contained in:
2026-09-25 00:08:01 -03:00
parent 6458bc0440
commit 2a2ccae9ce
18 changed files with 600 additions and 162 deletions
+39 -20
View File
@@ -1,8 +1,11 @@
import { AssetManager } from "./assets.ts";
import { ClientWorld } from "./client_world.ts";
import { InputManager } from "./input_manager.ts";
import { Connection, get_player_name, get_server_url } from "./network.ts";
import { begin_drawing, clear_background, end_drawing, init_font, init_window } from "./renderer/mod.ts";
import { Connection, get_player_name } from "./network.ts";
import { connect, HandshakeError, is_trusted, join, load_atlas, remember_trust, server_address } from "./handshake.ts";
import { confirm_mods } from "./confirm_mods.ts";
import { ModLoadError } from "$/common/mod_loader.ts";
import { begin_drawing, clear_background, end_drawing, init_font, init_window, load_texture } from "./renderer/mod.ts";
import { is_stopped, show_fatal_error } from "./fatal.ts";
import { load_client_mods, set_mods_world } from "./mods.ts";
@@ -76,9 +79,6 @@ InputManager.initialize(canvas);
AssetManager.instance.load("bworld:assets_text", "/assets/ASSETS.md");
AssetManager.instance.load("bworld:textures", "/assets/sprites/textures.png");
AssetManager.instance.load("bworld:textures_info", "/assets/sprites/textures.json");
AssetManager.instance.load("bworld:player", "/assets/sprites/player.png");
AssetManager.instance.load("bworld:roguelike", "/assets/sprites/roguelike.png");
AssetManager.instance.load("bworld:ui", "/assets/sprites/ui.png");
@@ -90,24 +90,37 @@ await AssetManager.instance.load_all();
init_font();
// the game only runs against a server, it owns the world and everything in it
const connection = await Connection.open(get_server_url(), get_player_name());
let mods_loaded = false;
if (connection) {
console.log(`Connected to ${get_server_url()}`);
// the game only runs against a server, it owns the world and everything in it. see "Delivery to clients" in MODS.md
async function join_server(): Promise<Connection> {
const address = server_address();
const { socket, welcome } = await connect(address, get_player_name());
console.log(`Connected to ${address.ws_url}`);
try {
// blocks, items and textures all come from mods, so this happens before anything else
await load_client_mods(connection.mods);
console.log(`Mods: ${connection.mods.map((mod) => `${mod.id} ${mod.version}`).join(", ") || "none"}`);
mods_loaded = true;
if (address.cross_origin && !is_trusted(address, welcome)) {
if (!await confirm_mods(address, welcome)) {
throw new HandshakeError(`You didn't join ${address.base.host}`);
}
remember_trust(address, welcome);
}
// textures, blocks and items all come from the server's mods, so this happens before anything else
const atlas = await load_atlas(address, welcome.atlas);
AssetManager.instance.assets["bworld:textures"] = load_texture(atlas.image);
AssetManager.instance.assets["bworld:textures_info"] = atlas.regions;
await load_client_mods(welcome.mods, address.base);
console.log(`Mods: ${welcome.mods.map((mod) => `${mod.id} ${mod.version}`).join(", ") || "none"}`);
const joined = await join(socket);
return new Connection(socket, welcome, joined);
} catch (e) {
console.error(e);
show_fatal_error(`Couldn't load the server's mods: ${e instanceof Error ? e.message : e}`);
connection.socket.close();
socket.close();
throw e;
}
}
if (connection && mods_loaded) {
try {
const connection = await join_server();
const client_world = new ClientWorld(connection);
set_mods_world(client_world);
client_world.add_chat("Connected to the server");
@@ -116,6 +129,12 @@ if (connection && mods_loaded) {
loop.start();
console.log("Game started");
} else if (!connection) {
show_fatal_error(`Couldn't connect to the server at ${get_server_url()}`);
} catch (e) {
console.error(e);
const message = e instanceof HandshakeError
? e.message
: e instanceof ModLoadError
? `Couldn't load the server's mods: ${e.message}`
: `Something went wrong joining the server: ${e instanceof Error ? e.message : e}`;
show_fatal_error(message);
}