M2.3: the shared world (trees, pickups, pieces, chests, fires, doors, graves, clock on the server)
This commit is contained in:
@@ -18,10 +18,10 @@ concrete decisions for this codebase, as it stands after M1.
|
||||
|
||||
## 2. Running a server
|
||||
*Built in M2.1* (`scripts/net/net.gd`, `server_config.gd`, `identity.gd`).
|
||||
As of M2.1 the server accepts players, checks who they are and keeps the
|
||||
player list. The world itself isn't served yet (M2.3). Flags: `--server`,
|
||||
The server accepts players, checks who they are and keeps the player list.
|
||||
Since M2.3 it also runs the shared island (§5). Flags: `--server`,
|
||||
`--port`, `--config`, `--server-name`, `--max-players`, `--password`,
|
||||
`--world`, and `--exit-with <pid>` (quit when that process exits; the tests
|
||||
`--world`, `--seed`, and `--exit-with <pid>` (quit when that process exits; the tests
|
||||
use it so a crashed test never leaves a server running). Flags apply to
|
||||
that run only and are never written to `server.json`.
|
||||
```bash
|
||||
@@ -161,8 +161,9 @@ A refused move sends the player back to their last good position.
|
||||
Respawning is a flagged teleport, allowed if it lands within 25 m of the
|
||||
island spawn. Normal play is never corrected, so there's no rubber-banding.
|
||||
This is the Valheim model, and simpler than replaying inputs on the server.
|
||||
Through-wall checks come with the shared world (M2.3), since the server
|
||||
doesn't know about buildings yet.
|
||||
Since M2.3 the server also refuses a move whose straight line crosses a
|
||||
wall, door frame (or closed door) or gable at waist height, checked from
|
||||
both ends so someone a wall was built on top of can still step out.
|
||||
|
||||
The server sends everyone's positions 20 times a second. Each one is stamped
|
||||
with when the player moved (their clock plus a smoothed per-player offset),
|
||||
@@ -177,9 +178,38 @@ Measured in `tests/test_net_world.gd` at 100 ms ± 30 ms simulated latency:
|
||||
a 4 m/s walk is seen at a median of 4.2 m/s, top 5.0, with no freezes, and
|
||||
it ends within a centimetre of where the walker stopped.
|
||||
|
||||
Until later phases, while online: animals are off (M2.5), and building,
|
||||
gathering and other world changes are local only and aren't saved (M2.3,
|
||||
M2.4). The HUD says so. Respawning ignores beds.
|
||||
**The shared world** *(built in M2.3: `world_net.gd`, autoload WorldNet)*.
|
||||
The dedicated server runs the real world scene headless with nobody of its
|
||||
own in it (`world.gd` `server_mode`), and saves it like a single-player
|
||||
world, in `worlds/<world>/` next to `server.json`. It owns trees and rocks
|
||||
(damage, felling, regrowth), pickups, berry bushes, dropped items, every
|
||||
placed piece (walls, doors, chests, graves, fires, beds), fire fuel, door
|
||||
state and the clock. Weather is worked out from the seed and the clock, so
|
||||
it needs no syncing.
|
||||
- A client's `Actions.*` intents that change the island become requests
|
||||
(`_c2s_hit`, `_c2s_place`, `_c2s_take`, `_c2s_chest_click`...). The server
|
||||
checks reach (from where it last saw that player), applies the change,
|
||||
and tells everyone (`_s2c_node`, `_s2c_piece_added`...). Nothing changes
|
||||
on your screen until the server says so, so two people grabbing the same
|
||||
stick get one stick between them.
|
||||
- Whatever a change earns you (wood, a pickup, a dismantled wall and
|
||||
anything that collapsed with it, items out of a chest) the server sends
|
||||
to you (`_s2c_give`). What doesn't fit lands at your feet.
|
||||
- Pieces have a net id that's saved with them, so they keep it across
|
||||
server restarts.
|
||||
- Chest clicks happen on the server (someone else may be using the chest),
|
||||
which hands back what you're holding.
|
||||
- On joining, your world asks for a snapshot of everything once its
|
||||
scenery is up, then gets each change in order. Regrowth only happens on
|
||||
the server, never on top of a player.
|
||||
- The world (fires, regrowth, the clock) pauses while nobody's on.
|
||||
|
||||
Until later phases, while online: your inventory, stats and crafting stay on
|
||||
your own game and aren't saved by the server (M2.4), so the server trusts
|
||||
what you say you're putting into the world (a wall, a chest deposit, a
|
||||
grave's contents) but decides everything taken out. Animals are off (M2.5).
|
||||
Sleeping is off (it needs the sleep rule, M2.5). Respawning ignores beds.
|
||||
The HUD says so.
|
||||
|
||||
**Interest.** On a 320 m worldlet with 8 players, the server sends every
|
||||
entity to everyone at first. Distance-based interest is a later
|
||||
@@ -208,6 +238,12 @@ worlds/<world>/
|
||||
friends, name, appearance
|
||||
backups/<timestamp>/ rolling copies (backups_kept)
|
||||
```
|
||||
*As of M2.3:* `worlds/<world>/meta.json` and `world.json` (with pieces'
|
||||
net ids, no owners yet) are written next to `server.json` within 10 s of
|
||||
any change, when a player leaves, and every `autosave_minutes`. (Ctrl+C
|
||||
kills Godot without running any code, so there's no save on the way out.) An
|
||||
existing world keeps the seed it was made with, even if `server.json`
|
||||
changes. Player files, owners and backups come in M2.4 and M2.7.
|
||||
- Single-player saves (today's `world.json` with a `"player"` block) are
|
||||
migrated on first load. That block becomes the local player's file. The
|
||||
test suite keeps an old-format save fixture to prove it.
|
||||
@@ -237,7 +273,7 @@ player" or "this player":
|
||||
| **M2.0** | worldlet W0 (terrain from data, no visible change), recommended first | seed 1337 generates the same height grid as today; all suites pass |
|
||||
| **M2.1** *(done)* | network skeleton: `--server`, ENet on 24242, Join screen (address, name), handshake with identity and challenge, name rules, player list | two clients and a headless server on one Mac connect, see the player list, and disconnect cleanly |
|
||||
| **M2.2** *(done)* | player bodies and name tags; predicted movement, interpolation for others | two players walk around together at 100 ms simulated latency without visible rubber-banding |
|
||||
| **M2.3** | world state replicated: resource nodes, pickups, pieces, chests, fires, doors, clock, weather | one chops a tree and the other sees it fall; one builds a wall and the other walks into it |
|
||||
| **M2.3** *(done)* | world state replicated: resource nodes, pickups, pieces, chests, fires, doors, clock, weather | one chops a tree and the other sees it fall; one builds a wall and the other walks into it |
|
||||
| **M2.4** | intents as RPCs; per-player inventory, stats, diet, death and graves; per-player saves and migration | two players craft, eat, die and loot their own graves; an old single-player save loads |
|
||||
| **M2.5** | wildlife and wolves server-side, projectiles, fishing, sleeping with the rule | a pack hunts two players at once; arrows hit on both screens |
|
||||
| **M2.6** | server rules: PvP, raiding, locks and friends, death penalty, difficulty; admin console and chat | each preset (co-op, rivals, adversarial) behaves as described in §4 |
|
||||
@@ -255,6 +291,10 @@ player" or "this player":
|
||||
- **Save tests:** world and player file round trips, migration of old
|
||||
saves, backups.
|
||||
- The existing 9 suites keep running in single-player (loopback) mode.
|
||||
- `tests/test_net_shared.gd` (M2.3) is the two-world version: this test is
|
||||
one player and `tests/net_world_bot.gd` (a second process with its own
|
||||
world, following commands the test writes as files) is the other. A
|
||||
`--debug-regrow <k>` server flag speeds regrowth up for it.
|
||||
|
||||
## 11. Risks
|
||||
- **Prediction feel** is the hard part. It gets an early phase (M2.2) so
|
||||
|
||||
Reference in New Issue
Block a user