Server authority

This commit is contained in:
2026-09-24 19:34:07 -03:00
parent 1bef94ce0c
commit 79faa556de
75 changed files with 2247 additions and 1632 deletions
+8 -23
View File
@@ -4,7 +4,7 @@ Status: **draft, format_version 1**. Nothing here is implemented yet, see [Imple
Mods add blocks, items, textures, recipes, world generation, game logic and GUIs to bworld. A mod is installed **on the
server**. Players who join download its client code, data and textures from the server automatically, so they don't
install anything themselves. Single player works the same way, with a server running inside the browser.
install anything themselves. bworld is always played on a server; there is no single player mode.
This borrows from Minecraft Bedrock add-ons: data lives in JSON, blocks get behavior from named custom components, and
scripts use before/after events. Bedrock servers also push resource packs to joining players, and their server scripts
@@ -27,7 +27,6 @@ too, since the client is already a web page.
- [Mod channels](#mod-channels)
- [World generation](#world-generation)
- [Delivery to clients](#delivery-to-clients)
- [Single player](#single-player)
- [Security](#security)
- [Example mod](#example-mod)
- [Implementation plan](#implementation-plan)
@@ -256,9 +255,8 @@ export function setup(ctx: ServerContext) {
}
```
Server scripts run in the game server worker. They get the mod API and standard JavaScript, and **no Deno, Node or DOM
APIs**. That lets the same script run on a dedicated server and in the browser for [single player](#single-player). They
have no file or network access; persistent state goes through `ctx.storage`.
Server scripts run in the game server worker with **no Deno permissions** (see [Security](#security)). They get the mod
API and standard JavaScript, but no file, network or subprocess access; persistent state goes through `ctx.storage`.
```ts
interface ServerContext {
@@ -750,20 +748,6 @@ client server
- The `protocol` in `hello` is the game's protocol version. A mismatch is rejected before any mod code is downloaded.
- Leaving a server reloads the page, so one server's mod code never stays loaded while playing on another.
## Single player
Single player runs the same game server inside the browser, like Minecraft's integrated server:
- The game server core (world, inventories, tile data, mod server scripts) is written against a small host interface for
**transport** and **storage**, with no Deno or DOM APIs.
- On a dedicated server, the host is `server/main.ts`: WebSocket transport, files for storage. The core runs in a Deno
worker.
- In single player, the host is the page: `postMessage` transport, IndexedDB for storage. The core runs in a web worker,
and `server.js` bundles are loaded from `server_mods/`, which the local build serves only to this page.
The client uses the same protocol either way, so a mod written and tested in single player behaves the same on a
dedicated server.
## Security
**Client scripts.** Mod client code runs in the game page with the page's full access. How much that matters depends on
@@ -900,16 +884,17 @@ class SmelterStats implements ModScreen {
## Implementation plan
None of this exists yet. Each step keeps the game working:
Steps 1–3 are done; the mod steps (4 onwards) aren't started. Each step keeps the game working:
1. **Game server core.** Move `client/generation.ts` to `common/` (it already only needs constants and the rng package)
and have the server generate terrain. Pull world state, chunks, tile data and player inventories into an
environment-free module behind a transport and storage interface. Run it in a Deno worker from `server/main.ts`.
and have the server generate terrain. Move world state, chunks, tile data and player inventories into a game server
module that runs in a Deno worker, with `server/main.ts` handling HTTP, WebSockets and files.
2. **Server authority.** Change the protocol from "here's the block I changed" to intents (`break_block`, `place_block`,
`interact`, `select_slot`, `container_click`). The client keeps showing breaks and places immediately and accepts
corrections. Move inventories, drops and `/give` to the server. Replace `GuiChest` / `GuiFurnace` with server-synced
containers.
3. **Integrated server.** Run the same core in a web worker for single player, with IndexedDB storage.
3. **Server only.** Remove the offline fallback in `client/main.ts`, which currently starts a local game when it can't
reach a server, and show a connection error instead.
4. **Mod loader and build.** Discover mods, check manifests, sort by dependencies, turn JSON into registry entries,
build the combined atlas (textures are currently all named `bworld:<file>`), bundle scripts per side, and write
hashed output to `build/mods/` and `server_mods/`.