Simulation runs in fixed steps of 1/50 s (50 steps a second) instead of 1/20 s, with at most twelve catch-up steps in one frame
This commit is contained in:
1 parent
dd4bb75b24
commit
35ddfa134c
4 files changed
+9
-9
No files matched your search
+5
-5
@@ -22,7 +22,7 @@ The server does not simulate; it relays:
|
|||||||
|
|
||||||
1. Clients send their **commands** (dig, build, cast, hand, orders, ...) to the server.
|
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.
|
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.
|
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.
|
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
|
`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.
|
`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.
|
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
|
- **Steps**: the simulation runs in fixed steps of `STEP` = 20 ms, 50 steps a second (`Game::update` feeds real
|
||||||
them, `Game::apply_turn(cmds, steps)` is the lockstep entry point). Commands are applied at step
|
time into them, `Game::apply_turn(cmds, steps)` is the lockstep entry point; one server turn of 100 ms is five
|
||||||
boundaries, so single player and a match run exactly the same path. Particles, effects and the camera
|
steps). Commands are applied at step boundaries, so single player and a match run exactly the same path.
|
||||||
keep running in real time: they are local and not part of the shared state.
|
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
|
- **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.
|
(`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
|
- Savegames, tests and the standalone file are unchanged: `cargo test --release` covers the command path
|
||||||
|
|||||||
+1
-1
@@ -239,7 +239,7 @@ mod tests {
|
|||||||
a.queue(Act::Pickup { ent: ogre });
|
a.queue(Act::Pickup { ent: ogre });
|
||||||
a.queue(Act::Drop { x: drop_at.0, y: drop_at.1 });
|
a.queue(Act::Drop { x: drop_at.0, y: drop_at.1 });
|
||||||
for _ in 0..20 {
|
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)
|
// the same game driven like a match (one turn with all commands, then the same steps)
|
||||||
|
|||||||
+2
-2
@@ -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
|
// 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
|
// 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)
|
// 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
|
// torch on a wall face: wall tile + direction (index into DIR4) towards the open side
|
||||||
#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
|
|||||||
Reference in new issue
Block a user