|
|
|
@@ -22,6 +22,7 @@ fn test_snapshot(tick: u64, entities: Vec<VisibleEntity>) -> ObserverSnapshot {
|
|
|
|
|
visible_tiles: vec![],
|
|
|
|
|
nearby_interactions: vec![],
|
|
|
|
|
current_monologue: None,
|
|
|
|
|
pending_recognitions: vec![],
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -86,7 +87,10 @@ fn all_player_action_variants_roundtrip() {
|
|
|
|
|
PlayerAction::MoveNorthwest,
|
|
|
|
|
PlayerAction::MoveSoutheast,
|
|
|
|
|
PlayerAction::MoveSouthwest,
|
|
|
|
|
PlayerAction::Interact { target_entity_id: None, verb: None },
|
|
|
|
|
PlayerAction::Interact {
|
|
|
|
|
target_entity_id: None,
|
|
|
|
|
verb: None,
|
|
|
|
|
},
|
|
|
|
|
PlayerAction::UsePerceptionMode("thermal".to_string()),
|
|
|
|
|
PlayerAction::Pause,
|
|
|
|
|
PlayerAction::Unpause,
|
|
|
|
@@ -134,7 +138,11 @@ fn all_fixtures_deserialize() {
|
|
|
|
|
if name.starts_with("snapshot") {
|
|
|
|
|
let snap = rmp_serde::from_slice::<ObserverSnapshot>(&bytes)
|
|
|
|
|
.unwrap_or_else(|e| panic!("deserialize snapshot fixture {}: {}", name, e));
|
|
|
|
|
assert_eq!(snap.version, PROTOCOL_VERSION, "fixture {} has wrong version", name);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
snap.version, PROTOCOL_VERSION,
|
|
|
|
|
"fixture {} has wrong version",
|
|
|
|
|
name
|
|
|
|
|
);
|
|
|
|
|
} else if name.starts_with("input_batch") {
|
|
|
|
|
rmp_serde::from_slice::<Vec<PlayerInput>>(&bytes)
|
|
|
|
|
.unwrap_or_else(|e| panic!("deserialize batch input fixture {}: {}", name, e));
|
|
|
|
@@ -225,6 +233,7 @@ fn snapshot_v2_fields_roundtrip() {
|
|
|
|
|
],
|
|
|
|
|
nearby_interactions: vec![],
|
|
|
|
|
current_monologue: None,
|
|
|
|
|
pending_recognitions: vec![],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let bytes = rmp_serde::to_vec_named(&snapshot).expect("serialize");
|
|
|
|
@@ -237,8 +246,14 @@ fn snapshot_v2_fields_roundtrip() {
|
|
|
|
|
assert_eq!(decoded.game_time.tick_rate, TickRate::Paused);
|
|
|
|
|
assert_eq!(decoded.player_facing, FacingDirection::Southeast);
|
|
|
|
|
assert_eq!(decoded.visible_tiles.len(), 2);
|
|
|
|
|
assert_eq!(decoded.visible_tiles[0].visibility, VisibilitySector::Forward);
|
|
|
|
|
assert_eq!(decoded.visible_tiles[1].visibility, VisibilitySector::Peripheral);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
decoded.visible_tiles[0].visibility,
|
|
|
|
|
VisibilitySector::Forward
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
decoded.visible_tiles[1].visibility,
|
|
|
|
|
VisibilitySector::Peripheral
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(decoded.entities[0].visibility, VisibilitySector::Forward);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -259,7 +274,11 @@ fn entity_to_bits_roundtrip() {
|
|
|
|
|
for entity in [e1, e2, e3, e4] {
|
|
|
|
|
let bits = entity.to_bits();
|
|
|
|
|
let restored = Entity::from_bits(bits);
|
|
|
|
|
assert_eq!(entity, restored, "Entity::to_bits() roundtrip failed for {:?}", entity);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
entity, restored,
|
|
|
|
|
"Entity::to_bits() roundtrip failed for {:?}",
|
|
|
|
|
entity
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -268,7 +287,10 @@ fn entity_to_bits_roundtrip() {
|
|
|
|
|
fn protocol_version_constant_matches_snapshot() {
|
|
|
|
|
let snapshot = test_snapshot(0, vec![]);
|
|
|
|
|
assert_eq!(snapshot.version, PROTOCOL_VERSION);
|
|
|
|
|
assert_eq!(PROTOCOL_VERSION, 6, "bump this assertion when protocol version changes");
|
|
|
|
|
assert_eq!(
|
|
|
|
|
PROTOCOL_VERSION, 7,
|
|
|
|
|
"bump this assertion when protocol version changes"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// All FacingDirection variants round-trip
|
|
|
|
@@ -302,6 +324,7 @@ fn all_facing_direction_variants_roundtrip() {
|
|
|
|
|
visible_tiles: vec![],
|
|
|
|
|
nearby_interactions: vec![],
|
|
|
|
|
current_monologue: None,
|
|
|
|
|
pending_recognitions: vec![],
|
|
|
|
|
};
|
|
|
|
|
let bytes = rmp_serde::to_vec_named(&snapshot).expect("serialize");
|
|
|
|
|
let decoded: ObserverSnapshot = rmp_serde::from_slice(&bytes).expect("deserialize");
|
|
|
|
@@ -412,19 +435,35 @@ fn v5_payload_deserializes_into_v6_struct() {
|
|
|
|
|
// New fields should get their defaults
|
|
|
|
|
assert_eq!(decoded.version, 5, "version field preserved from v5");
|
|
|
|
|
assert_eq!(decoded.tick, 42);
|
|
|
|
|
assert_eq!(decoded.player_stance, MovementStance::Walk, "missing stance should default to Walk");
|
|
|
|
|
assert!(decoded.player_inventory.is_empty(), "missing inventory should default to empty");
|
|
|
|
|
assert!(decoded.current_monologue.is_none(), "missing monologue should default to None");
|
|
|
|
|
assert_eq!(
|
|
|
|
|
decoded.player_stance,
|
|
|
|
|
MovementStance::Walk,
|
|
|
|
|
"missing stance should default to Walk"
|
|
|
|
|
);
|
|
|
|
|
assert!(
|
|
|
|
|
decoded.player_inventory.is_empty(),
|
|
|
|
|
"missing inventory should default to empty"
|
|
|
|
|
);
|
|
|
|
|
assert!(
|
|
|
|
|
decoded.current_monologue.is_none(),
|
|
|
|
|
"missing monologue should default to None"
|
|
|
|
|
);
|
|
|
|
|
assert!(
|
|
|
|
|
decoded.pending_recognitions.is_empty(),
|
|
|
|
|
"missing pending_recognitions should default to empty"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Full 9-slot inventory roundtrip (D-065: 3x3 grid = 9 slots universal)
|
|
|
|
|
#[test]
|
|
|
|
|
fn snapshot_v6_full_inventory_roundtrip() {
|
|
|
|
|
let items: Vec<InventoryItem> = (0..9).map(|i| InventoryItem {
|
|
|
|
|
item_id: 100 + i as u64,
|
|
|
|
|
name: format!("Item {}", i),
|
|
|
|
|
slot: i,
|
|
|
|
|
}).collect();
|
|
|
|
|
let items: Vec<InventoryItem> = (0..9)
|
|
|
|
|
.map(|i| InventoryItem {
|
|
|
|
|
item_id: 100 + i as u64,
|
|
|
|
|
name: format!("Item {}", i),
|
|
|
|
|
slot: i,
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
let mut snapshot = test_snapshot(0, vec![]);
|
|
|
|
|
snapshot.player_inventory = items;
|
|
|
|
@@ -482,7 +521,8 @@ fn all_verb_kind_variants_roundtrip() {
|
|
|
|
|
assert_eq!(decoded.nearby_interactions.len(), 1);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
decoded.nearby_interactions[0].verbs[0].kind, kind,
|
|
|
|
|
"VerbKind::{:?} did not roundtrip", kind
|
|
|
|
|
"VerbKind::{:?} did not roundtrip",
|
|
|
|
|
kind
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -506,7 +546,11 @@ fn all_object_type_variants_roundtrip() {
|
|
|
|
|
for obj_type in types {
|
|
|
|
|
let bytes = rmp_serde::to_vec_named(&obj_type).expect("serialize");
|
|
|
|
|
let decoded: ObjectType = rmp_serde::from_slice(&bytes).expect("deserialize");
|
|
|
|
|
assert_eq!(decoded, obj_type, "ObjectType::{:?} roundtrip failed", obj_type);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
decoded, obj_type,
|
|
|
|
|
"ObjectType::{:?} roundtrip failed",
|
|
|
|
|
obj_type
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -533,7 +577,10 @@ fn verb_kind_confront_roundtrip() {
|
|
|
|
|
let decoded: ObserverSnapshot = rmp_serde::from_slice(&bytes).expect("deserialize");
|
|
|
|
|
|
|
|
|
|
assert_eq!(decoded.nearby_interactions.len(), 1);
|
|
|
|
|
assert_eq!(decoded.nearby_interactions[0].verbs[0].kind, VerbKind::Confront);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
decoded.nearby_interactions[0].verbs[0].kind,
|
|
|
|
|
VerbKind::Confront
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(decoded.nearby_interactions[0].verbs[0].label, "Confront");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -541,15 +588,16 @@ fn verb_kind_confront_roundtrip() {
|
|
|
|
|
/// Used in Phase 2 label relabeling — must survive the wire.
|
|
|
|
|
#[test]
|
|
|
|
|
fn all_character_archetype_variants_roundtrip() {
|
|
|
|
|
let archetypes = [
|
|
|
|
|
CharacterArchetype::Smuggler,
|
|
|
|
|
CharacterArchetype::Detective,
|
|
|
|
|
];
|
|
|
|
|
let archetypes = [CharacterArchetype::Smuggler, CharacterArchetype::Detective];
|
|
|
|
|
|
|
|
|
|
for archetype in archetypes {
|
|
|
|
|
let bytes = rmp_serde::to_vec_named(&archetype).expect("serialize");
|
|
|
|
|
let decoded: CharacterArchetype = rmp_serde::from_slice(&bytes).expect("deserialize");
|
|
|
|
|
assert_eq!(decoded, archetype, "CharacterArchetype::{:?} roundtrip failed", archetype);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
decoded, archetype,
|
|
|
|
|
"CharacterArchetype::{:?} roundtrip failed",
|
|
|
|
|
archetype
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -575,7 +623,10 @@ fn nearby_interaction_contradicted_roundtrip() {
|
|
|
|
|
let bytes = rmp_serde::to_vec_named(&snapshot).expect("serialize");
|
|
|
|
|
let decoded: ObserverSnapshot = rmp_serde::from_slice(&bytes).expect("deserialize");
|
|
|
|
|
|
|
|
|
|
assert!(decoded.nearby_interactions[0].contradicted, "contradicted flag should survive roundtrip");
|
|
|
|
|
assert!(
|
|
|
|
|
decoded.nearby_interactions[0].contradicted,
|
|
|
|
|
"contradicted flag should survive roundtrip"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// NearbyInteraction.object_type round-trips through MessagePack (#422).
|
|
|
|
@@ -600,5 +651,8 @@ fn nearby_interaction_object_type_roundtrip() {
|
|
|
|
|
let bytes = rmp_serde::to_vec_named(&snapshot).expect("serialize");
|
|
|
|
|
let decoded: ObserverSnapshot = rmp_serde::from_slice(&bytes).expect("deserialize");
|
|
|
|
|
|
|
|
|
|
assert_eq!(decoded.nearby_interactions[0].object_type, Some(ObjectType::Container));
|
|
|
|
|
assert_eq!(
|
|
|
|
|
decoded.nearby_interactions[0].object_type,
|
|
|
|
|
Some(ObjectType::Container)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|