diff --git a/VERSION b/VERSION index a91e939..789af57 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v202611-00002 +v202611-00003 diff --git a/docs/MULTIPLAYER.md b/docs/MULTIPLAYER.md index 6c6a645..ece24fa 100644 --- a/docs/MULTIPLAYER.md +++ b/docs/MULTIPLAYER.md @@ -22,7 +22,7 @@ The server does not simulate; it relays: 1. Clients send their **commands** (dig, build, cast, hand, orders, ...) to the server. 2. Every 100 ms the server sends **turn N**: the commands of all players for that turn. -3. Each client applies turn N and simulates two fixed steps of 50 ms. Turns arrive in order; a client waits +3. Each client applies turn N and simulates five fixed steps of 20 ms. Turns arrive in order; a client waits for the next turn, so a missing player stalls everybody - exactly the "pause while missing" rule. 4. Clients send a **checksum** of the game state every few seconds; a mismatch (desync) is reported. @@ -38,10 +38,10 @@ per turn. Fog of war, particles and the camera are local and not part of the sha `Cast`, `Flag`, `Pickup`, `Drop`, `Slap`, `Attack`, `Guard`, `CancelOrders`, ...) wrapped in a `Command { side, seq, act }`. Creature targets are *ids*, so they mean the same on every client. The tools in `main.rs` only queue commands now - nothing touches the world directly. -- **Steps**: the simulation runs in fixed steps of `STEP` = 50 ms (`Game::update` feeds real time into - them, `Game::apply_turn(cmds, steps)` is the lockstep entry point). Commands are applied at step - boundaries, so single player and a match run exactly the same path. Particles, effects and the camera - keep running in real time: they are local and not part of the shared state. +- **Steps**: the simulation runs in fixed steps of `STEP` = 20 ms, 50 steps a second (`Game::update` feeds real + time into them, `Game::apply_turn(cmds, steps)` is the lockstep entry point; one server turn of 100 ms is five + steps). Commands are applied at step boundaries, so single player and a match run exactly the same path. + Particles, effects and the camera keep running in real time: they are local and not part of the shared state. - **Who speaks**: messages, hints and interface sounds belong to the master who is being processed (`Game::speaking`); what another master orders never shows up on my screen. - Savegames, tests and the standalone file are unchanged: `cargo test --release` covers the command path diff --git a/src/commands.rs b/src/commands.rs index 6c23cb4..db8569d 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -239,7 +239,7 @@ mod tests { a.queue(Act::Pickup { ent: ogre }); a.queue(Act::Drop { x: drop_at.0, y: drop_at.1 }); for _ in 0..20 { - a.update(0.05); + a.update(STEP); } // the same game driven like a match (one turn with all commands, then the same steps) diff --git a/src/game.rs b/src/game.rs index 33bbbea..ec36435 100644 --- a/src/game.rs +++ b/src/game.rs @@ -605,9 +605,9 @@ fn hint_times() -> [f32; 32] { // every simulation step has the same length: on every client of a match the same commands are // applied and then the same number of steps runs, so the worlds stay identical -pub const STEP: f32 = 0.05; +pub const STEP: f32 = 1.0 / 50.0; // 50 steps a second // one frame never runs away into the future (a lagging tab catches up at most this much) -const MAX_STEPS_PER_FRAME: usize = 4; +const MAX_STEPS_PER_FRAME: usize = 12; // torch on a wall face: wall tile + direction (index into DIR4) towards the open side #[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]