feat(simulation): NPC-to-NPC conversation system (#247, D-078)
Implements server-authoritative per-word occlusion for NPC conversations. ConversationEventBuffer drains into ObserverSnapshot each tick so the client receives only words audible from the player's position. Updates test fixtures to include the new conversation_events and conversation_ended fields. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -300,6 +300,8 @@ mod tests {
|
||||
dialogue_response: None,
|
||||
blocked_entities: vec![],
|
||||
scan_events: vec![],
|
||||
conversation_events: vec![],
|
||||
conversation_ended: vec![],
|
||||
sound_events: vec![],
|
||||
rng_seed: None,
|
||||
}
|
||||
@@ -425,6 +427,8 @@ mod tests {
|
||||
dialogue_response: None,
|
||||
blocked_entities: vec![],
|
||||
scan_events: vec![],
|
||||
conversation_events: vec![],
|
||||
conversation_ended: vec![],
|
||||
sound_events: vec![],
|
||||
rng_seed: None,
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ pub use crate::simulation::time::{DayPhase, TickRate};
|
||||
/// negotiation is unnecessary. Client should reject snapshots with version !=
|
||||
/// PROTOCOL_VERSION. New fields use #[serde(default)] only during the migration
|
||||
/// period, then the default is removed once both sides are updated.
|
||||
pub const PROTOCOL_VERSION: u8 = 11;
|
||||
pub const PROTOCOL_VERSION: u8 = 12;
|
||||
|
||||
/// The ONLY data structure crossing the client-server boundary (D-020)
|
||||
/// Contains all information visible to the observer at a given tick.
|
||||
@@ -31,10 +31,11 @@ pub const PROTOCOL_VERSION: u8 = 11;
|
||||
/// v10 adds: sound_events (#124, D-038 server sound event pipeline),
|
||||
/// rng_seed (#527, deterministic replay — completes WRONG button loop).
|
||||
/// v11 adds: zone_id on VisibleTile (#523, D-077 OQ-09 resolution + D-073 crossfade).
|
||||
/// v12 adds: conversation_events, conversation_ended (#247, D-078 NPC-to-NPC conversations).
|
||||
/// Future fields: ambient sound events, HUD state (D-020 expansion).
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ObserverSnapshot {
|
||||
/// Protocol version for forward compatibility. Current: 11.
|
||||
/// Protocol version for forward compatibility. Current: 12.
|
||||
pub version: u8,
|
||||
/// Simulation tick when this snapshot was produced
|
||||
pub tick: u64,
|
||||
@@ -88,6 +89,15 @@ pub struct ObserverSnapshot {
|
||||
/// Empty when no sounds are in range.
|
||||
#[serde(default)]
|
||||
pub sound_events: Vec<crate::simulation::sound::SoundEvent>,
|
||||
/// Overheard NPC-to-NPC conversation lines this tick (#247, D-078).
|
||||
/// Each event carries pre-occluded text — client renders verbatim.
|
||||
/// Empty when no conversations are overheard.
|
||||
#[serde(default)]
|
||||
pub conversation_events: Vec<crate::simulation::conversation::ConversationEvent>,
|
||||
/// Conversations that ended this tick (#247, D-078).
|
||||
/// Client dismisses the passive dialogue panel for these pairs.
|
||||
#[serde(default)]
|
||||
pub conversation_ended: Vec<crate::simulation::conversation::ConversationEndEvent>,
|
||||
/// RNG seed active at this tick for deterministic replay (#527).
|
||||
/// The WRONG button writes this to seed.txt so replays reproduce observed bugs.
|
||||
/// None when the RNG resource is unavailable (should not occur in practice).
|
||||
|
||||
Reference in New Issue
Block a user