Merge remote-tracking branch 'origin/ci'

# Conflicts:
#	client/tests/fixtures/msgpack/snapshot_boundary_tick_0.msgpack
#	client/tests/fixtures/msgpack/snapshot_boundary_tick_127.msgpack
#	client/tests/fixtures/msgpack/snapshot_boundary_tick_2b31m1.msgpack
#	client/tests/fixtures/msgpack/snapshot_boundary_tick_2b32.msgpack
#	client/tests/fixtures/msgpack/snapshot_boundary_tick_32767.msgpack
#	client/tests/fixtures/msgpack/snapshot_empty.msgpack
#	client/tests/fixtures/msgpack/snapshot_multi_entity.msgpack
#	client/tests/fixtures/msgpack/snapshot_one_npc.msgpack
#	client/tests/fixtures/msgpack/snapshot_player.msgpack
#	client/tests/fixtures/msgpack/snapshot_v2_full.msgpack
#	server/Cargo.toml
#	server/src/bridge/text_renderer.rs
#	server/src/bridge/types.rs
#	server/src/perception/observer/mod.rs
#	server/src/simulation/path_follow.rs
#	server/tests/bridge_ipc.rs
#	server/tests/bridge_tcp.rs
#	server/tests/gen_fixtures.rs
#	server/tests/serialization.rs
This commit is contained in:
2026-02-19 15:35:56 +01:00
38 changed files with 307 additions and 50 deletions
+80
View File
@@ -27,6 +27,7 @@ fn test_snapshot(tick: u64, entities: Vec<VisibleEntity>) -> ObserverSnapshot {
blocked_entities: vec![],
scan_events: vec![],
sound_events: vec![],
rng_seed: None,
}
}
@@ -256,6 +257,7 @@ fn snapshot_v2_fields_roundtrip() {
blocked_entities: vec![],
scan_events: vec![],
sound_events: vec![],
rng_seed: None,
};
let bytes = rmp_serde::to_vec_named(&snapshot).expect("serialize");
@@ -350,7 +352,11 @@ fn all_facing_direction_variants_roundtrip() {
dialogue_response: None,
blocked_entities: vec![],
scan_events: vec![],
<<<<<<< HEAD
sound_events: vec![],
=======
rng_seed: None,
>>>>>>> origin/ci
};
let bytes = rmp_serde::to_vec_named(&snapshot).expect("serialize");
let decoded: ObserverSnapshot = rmp_serde::from_slice(&bytes).expect("deserialize");
@@ -1187,6 +1193,80 @@ fn v8_payload_deserializes_into_v9_struct() {
);
}
/// rng_seed round-trips through MessagePack (#527).
/// Verifies Some(seed) survives the wire and None is omitted.
#[test]
fn rng_seed_roundtrip() {
let mut snapshot = test_snapshot(0, vec![]);
snapshot.rng_seed = Some(123456789);
let bytes = rmp_serde::to_vec_named(&snapshot).expect("serialize");
let decoded: ObserverSnapshot = rmp_serde::from_slice(&bytes).expect("deserialize");
assert_eq!(decoded.rng_seed, Some(123456789));
// None case: skip_serializing_if omits the field, default restores it
let mut snapshot_none = test_snapshot(0, vec![]);
snapshot_none.rng_seed = None;
let bytes_none = rmp_serde::to_vec_named(&snapshot_none).expect("serialize");
let decoded_none: ObserverSnapshot = rmp_serde::from_slice(&bytes_none).expect("deserialize");
assert_eq!(decoded_none.rng_seed, None);
}
/// v9 payloads (without rng_seed) must deserialize into the v10 struct
/// via #[serde(default)]. Guards backwards compat during migration (#527).
#[test]
fn v9_payload_deserializes_into_v10_struct() {
#[derive(serde::Serialize)]
struct ObserverSnapshotV9 {
version: u8,
tick: u64,
game_time: GameTime,
player_facing: FacingDirection,
player_stance: MovementStance,
player_inventory: Vec<InventoryItem>,
entities: Vec<VisibleEntity>,
visible_tiles: Vec<VisibleTile>,
nearby_interactions: Vec<NearbyInteraction>,
current_monologue: Option<MonologueEvent>,
pending_recognitions: Vec<PendingRecognitionWire>,
dialogue_response: Option<DialogueResponseEvent>,
blocked_entities: Vec<u64>,
scan_events: Vec<settled_reach_server::simulation::contraband::ScanEvent>,
}
let v9 = ObserverSnapshotV9 {
version: 9,
tick: 200,
game_time: GameTime {
day: 0,
time_of_day: 0,
day_phase: DayPhase::Morning,
tick_rate: TickRate::Full,
},
player_facing: FacingDirection::North,
player_stance: MovementStance::Walk,
player_inventory: vec![],
entities: vec![],
visible_tiles: vec![],
nearby_interactions: vec![],
current_monologue: None,
pending_recognitions: vec![],
dialogue_response: None,
blocked_entities: vec![],
scan_events: vec![],
};
let bytes = rmp_serde::to_vec_named(&v9).expect("serialize v9");
let decoded: ObserverSnapshot = rmp_serde::from_slice(&bytes)
.expect("v9 payload should deserialize into v10 struct via serde(default)");
assert_eq!(decoded.version, 9, "version field preserved from v9");
assert_eq!(decoded.tick, 200);
assert_eq!(
decoded.rng_seed, None,
"missing rng_seed should default to None"
);
}
/// NearbyInteraction.object_type round-trips through MessagePack (#422).
/// Verifies object_type=Some(Container) survives the wire.
#[test]