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:
@@ -62,6 +62,7 @@ fn snapshot_roundtrip_over_unix_socket() {
|
||||
blocked_entities: vec![],
|
||||
scan_events: vec![],
|
||||
sound_events: vec![],
|
||||
rng_seed: None,
|
||||
};
|
||||
|
||||
bridge
|
||||
|
||||
@@ -48,6 +48,7 @@ fn snapshot_roundtrip_over_tcp() {
|
||||
blocked_entities: vec![],
|
||||
scan_events: vec![],
|
||||
sound_events: vec![],
|
||||
rng_seed: None,
|
||||
};
|
||||
|
||||
bridge
|
||||
|
||||
@@ -21,7 +21,9 @@ use std::time::Instant;
|
||||
use settled_reach_server::bridge::types::*;
|
||||
use settled_reach_server::bridge::BridgePlugin;
|
||||
use settled_reach_server::knowledge::registry::{EntityRegistry, StableEntityId};
|
||||
use settled_reach_server::knowledge::{KnowledgeConfidence, KnowledgeGraph, KnowledgePlugin, StableId};
|
||||
use settled_reach_server::knowledge::{
|
||||
KnowledgeConfidence, KnowledgeGraph, KnowledgePlugin, StableId,
|
||||
};
|
||||
use settled_reach_server::npc::{Contentment, Npc, NpcPlugin, ToleranceThreshold, Want, WantKind};
|
||||
use settled_reach_server::simulation::interaction::Interactable;
|
||||
use settled_reach_server::simulation::movement::TilePosition;
|
||||
@@ -462,10 +464,8 @@ fn max_npc_pack_behavioral_regression() {
|
||||
.clone();
|
||||
let stress_kg = player_kg_snapshot(&stress_app, max_gauntlet_id);
|
||||
|
||||
let baseline_snap = baseline_snapshot
|
||||
.expect("baseline Gauntlet should produce a snapshot");
|
||||
let stress_snap = stress_snapshot
|
||||
.expect("80-NPC stress run should produce a snapshot");
|
||||
let baseline_snap = baseline_snapshot.expect("baseline Gauntlet should produce a snapshot");
|
||||
let stress_snap = stress_snapshot.expect("80-NPC stress run should produce a snapshot");
|
||||
|
||||
// Tick index must match (same number of updates).
|
||||
assert_eq!(
|
||||
|
||||
@@ -349,10 +349,7 @@ fn t4_knowledge_graph_survives_room_transition() {
|
||||
"T4 post: KG entry must persist after player moves to Hub"
|
||||
);
|
||||
assert_eq!(
|
||||
world
|
||||
.get::<KnowledgeGraph>(player)
|
||||
.unwrap()
|
||||
.entity_count(),
|
||||
world.get::<KnowledgeGraph>(player).unwrap().entity_count(),
|
||||
1,
|
||||
"T4 post: exactly 1 KG entry after room transition"
|
||||
);
|
||||
@@ -542,7 +539,10 @@ fn t7_confrontation_verb_disappears_on_retreat_beyond_mid_range() {
|
||||
"T7 close: NPC at distance 2 must appear in interaction buffer"
|
||||
);
|
||||
assert!(
|
||||
interactions[0].verbs.iter().any(|v| v.kind == VerbKind::Talk),
|
||||
interactions[0]
|
||||
.verbs
|
||||
.iter()
|
||||
.any(|v| v.kind == VerbKind::Talk),
|
||||
"T7 close: Talk must be available at CLOSE_RANGE (confrontation possible)"
|
||||
);
|
||||
|
||||
@@ -599,7 +599,10 @@ fn t8_sprint_blocks_eavesdrop_then_careful_enables_accumulation() {
|
||||
run_listening_system(&mut world);
|
||||
}
|
||||
assert_eq!(
|
||||
world.get::<ListeningFocus>(player).unwrap().stationary_ticks,
|
||||
world
|
||||
.get::<ListeningFocus>(player)
|
||||
.unwrap()
|
||||
.stationary_ticks,
|
||||
0,
|
||||
"T8 sprint: Sprint must block stationary_ticks (50 ticks at sprint, still 0)"
|
||||
);
|
||||
@@ -613,7 +616,10 @@ fn t8_sprint_blocks_eavesdrop_then_careful_enables_accumulation() {
|
||||
// resets stationary_ticks to 0, and updates last_position to alcove_pos.
|
||||
run_listening_system(&mut world);
|
||||
assert_eq!(
|
||||
world.get::<ListeningFocus>(player).unwrap().stationary_ticks,
|
||||
world
|
||||
.get::<ListeningFocus>(player)
|
||||
.unwrap()
|
||||
.stationary_ticks,
|
||||
0,
|
||||
"T8 transition: movement tick must reset stationary_ticks to 0"
|
||||
);
|
||||
|
||||
@@ -38,6 +38,7 @@ fn fixture_snapshot(tick: u64, entities: Vec<VisibleEntity>) -> ObserverSnapshot
|
||||
blocked_entities: vec![],
|
||||
scan_events: vec![],
|
||||
sound_events: vec![],
|
||||
rng_seed: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,6 +211,7 @@ fn generate_msgpack_fixtures() {
|
||||
blocked_entities: vec![],
|
||||
scan_events: vec![],
|
||||
sound_events: vec![],
|
||||
rng_seed: None,
|
||||
};
|
||||
write_fixture(
|
||||
"snapshot_v2_full",
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
"player_facing": "North",
|
||||
"player_inventory": [],
|
||||
"player_stance": "Sprint",
|
||||
"rng_seed": 42,
|
||||
"scan_events": [],
|
||||
"sound_events": [],
|
||||
"tick": 8,
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user