Test: volle Spielerliste mit vielen Offline-Spielern wird geladen

Eine Welt kennt bis zu 16 Spieler, von denen höchstens vier online sind.
Kein Test lud eine Welt mit mehr als vier bekannten Spielern; ein Fehler,
der in check_restorable alle bekannten statt der Online-Spieler zählt,
hätte gültige Spielstände zurückgewiesen und blieb unbemerkt. Mit dem
Koop-Spiel in M1c sind mehr als vier bekannte Spieler der Normalfall.

Der neue Test baut die Welt über Befehle auf: 16 Schlüssel treten in
Vierergruppen bei, jede Gruppe außer der letzten geht wieder, bevor die
nächste kommt. from_snapshot muss dieselbe Welt liefern, load alle Spieler
offline. Mit dem Fehler (alle Spieler gezählt) schlägt der Test mit
Invalid("online players") fehl.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Steven Wroblewski
2026-10-01 13:19:23 +02:00
parent fc8d5cb164
commit 8aaeae5cf7
+41 -1
View File
@@ -3,7 +3,7 @@ use grovewright_core::command::Command;
use grovewright_core::hash::fnv1a64;
use grovewright_core::map::{Map, Pos, Terrain};
use grovewright_core::mapgen::outcrop_origin;
use grovewright_core::player::{Player, PlayerId, MAX_ONLINE_PLAYERS};
use grovewright_core::player::{Player, PlayerId, MAX_KNOWN_PLAYERS, MAX_ONLINE_PLAYERS};
use grovewright_core::snapshot::{SnapshotError, MAX_RESTORABLE_TICK, SNAPSHOT_VERSION};
use grovewright_core::world::{Event, World, DIG_COOLDOWN_TICKS};
@@ -256,3 +256,43 @@ fn states_right_at_the_limits_are_accepted() {
let bytes = snapshot_of(1, MAX_RESTORABLE_TICK, &map, &players);
assert!(World::from_snapshot(&bytes).is_ok());
}
/// A world that knows `MAX_KNOWN_PLAYERS` players, built through commands.
/// They join in groups of `MAX_ONLINE_PLAYERS`, and each group but the last
/// leaves before the next one joins, so only the last group is online.
fn world_with_a_full_roster() -> World {
let mut world = World::new(7);
let groups = MAX_KNOWN_PLAYERS / MAX_ONLINE_PLAYERS;
for group in 0..groups {
let first = group * MAX_ONLINE_PLAYERS;
for index in first..first + MAX_ONLINE_PLAYERS {
world.step(&[Command::Join {
key: [index as u8; 16],
name: format!("P{index}"),
}]);
}
if group + 1 < groups {
for index in first..first + MAX_ONLINE_PLAYERS {
world.step(&[Command::Leave {
player: PlayerId(index as u8),
}]);
}
}
}
world
}
#[test]
fn a_full_roster_with_most_players_offline_is_accepted() {
let world = world_with_a_full_roster();
assert_eq!(world.players().len(), MAX_KNOWN_PLAYERS);
let online = world.players().iter().filter(|player| player.online);
assert_eq!(online.count(), MAX_ONLINE_PLAYERS);
let restored = World::from_snapshot(&world.to_snapshot()).unwrap();
assert_eq!(restored, world);
let loaded = World::load(&world.to_snapshot()).unwrap();
assert_eq!(loaded.players().len(), MAX_KNOWN_PLAYERS);
assert!(loaded.players().iter().all(|player| !player.online));
}