Abschlusskorrekturen M1c: Schläge der Gäste, Figuren und Fragebogen
- Der Host hält einen Schlag eines Gastes, der während der Abklingzeit ankommt, bis zum ersten Takt danach. Übers Internet ging sonst etwa jeder fünfte Schlag eines Gastes verloren. - ENet drosselt die Figuren nie mehr; sonst konnten die Figuren eines von zwei Gästen dauerhaft stehen bleiben. Figuren gehen geordnet, und eine stille Verbindung gilt nach höchstens acht Sekunden als verloren. - Positionen, die keine Zahlen sind, und Figuren von Spielern, die nicht online sind, werden verworfen. - Ein Host mit angehaltener Simulation sagt das in der Statuszeile. - Neue Tests: Schlag während der Abklingzeit, Zielauswahl von NetLink, verworfene Figuren, Neuabgleich über die Brücke. - Der Fragebogen sagt, was jeder Rechner braucht, und die Freigabe in der Firewall gehört zum Host. CLAUDE.md beschreibt das Halten der Schläge, die Drosselung und die Zeitüberschreitung und ergänzt die Vertrauensregel um die Schlüssel. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@ use grovewright_core::map::Pos;
|
||||
use grovewright_core::mapgen::outcrop_origin;
|
||||
use grovewright_core::player::{PlayerId, PlayerKey};
|
||||
use grovewright_core::protocol::{Action, Refusal, ToGuest, ToHost, CHECK_INTERVAL_TICKS};
|
||||
use grovewright_core::world::{Event, World};
|
||||
use grovewright_core::world::{Event, World, DIG_COOLDOWN_TICKS};
|
||||
|
||||
const HOST_KEY: PlayerKey = [100; 16];
|
||||
|
||||
@@ -294,3 +294,58 @@ fn a_missing_tick_makes_the_guest_ask_for_the_world() {
|
||||
Some(host.world().state_hash())
|
||||
);
|
||||
}
|
||||
|
||||
/// Hands a pickaxe hit of `guest` at `pos` to the host as from `peer`.
|
||||
fn dig(host: &mut Host, peer: Peer, guest: &mut Guest, pos: Pos) {
|
||||
guest.act(Action::Dig { pos });
|
||||
for bytes in guest.take_outbox() {
|
||||
host.receive(peer, &bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/// The tiles that pickaxe hits landed on, without breaking them.
|
||||
fn hits(events: &[Event]) -> Vec<Pos> {
|
||||
events
|
||||
.iter()
|
||||
.filter_map(|event| match event {
|
||||
Event::TileHit { pos, .. } => Some(*pos),
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_guests_hit_that_comes_during_the_cooldown_waits_for_it() {
|
||||
let (mut host, mut ada) = host_with_ada();
|
||||
let rock = outcrop_origin(host.world().map());
|
||||
let next = Pos::new(rock.x + 1, rock.y);
|
||||
dig(&mut host, 2, &mut ada, rock);
|
||||
let first = host.world().tick();
|
||||
assert_eq!(hits(&host.step()), [rock], "the first hit lands at once");
|
||||
|
||||
// Two more hits come during the cooldown, as if the round trip had
|
||||
// become shorter. The newer one waits for the end of the cooldown.
|
||||
dig(&mut host, 2, &mut ada, rock);
|
||||
dig(&mut host, 2, &mut ada, next);
|
||||
let mut landed = Vec::new();
|
||||
for _ in 0..DIG_COOLDOWN_TICKS {
|
||||
let tick = host.world().tick();
|
||||
for pos in hits(&host.step()) {
|
||||
landed.push((tick, pos));
|
||||
}
|
||||
}
|
||||
assert_eq!(landed, [(first + DIG_COOLDOWN_TICKS, next)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_waiting_hit_is_dropped_when_its_guest_leaves() {
|
||||
let (mut host, mut ada) = host_with_ada();
|
||||
let rock = outcrop_origin(host.world().map());
|
||||
dig(&mut host, 2, &mut ada, rock);
|
||||
host.step();
|
||||
dig(&mut host, 2, &mut ada, rock);
|
||||
host.disconnect(2);
|
||||
for _ in 0..DIG_COOLDOWN_TICKS {
|
||||
assert_eq!(hits(&host.step()), [], "nobody hits");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user