feat(perception): add cognitive delay system for fog recognition (#423)

New CognitiveDelay component buffers perception events before emitting
KnowledgeEvents. Normal delay: 6 ticks (0.6s), urgent: 3 ticks (0.3s).
Drain system runs after emit_observation_events, before process_knowledge_events.

Adds pending_recognitions to ObserverSnapshot (protocol v7) for client
fog entity visualization. Includes cancellation when entity leaves LOS.

Monologue fires during delay (not after) per D-060 — cross-system
wiring deferred to follow-up ticket #451.

Ref: D-060 (cognitive delay), D-031 (10 tps), D-059 (fog layers)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 00:41:08 +01:00
co-authored by Claude Opus 4.6
parent 3a2cfc37e0
commit 4d8fe996fc
17 changed files with 933 additions and 105 deletions
+24 -1
View File
@@ -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 = 6;
pub const PROTOCOL_VERSION: u8 = 7;
/// The ONLY data structure crossing the client-server boundary (D-020)
/// Contains all information visible to the observer at a given tick.
@@ -25,6 +25,7 @@ pub const PROTOCOL_VERSION: u8 = 6;
/// v4 adds: nearby_interactions (D-060, #404 proximity + verbs[]).
/// v5 adds: current_monologue (#414 internal monologue pipeline).
/// v6 adds: player_stance (#449, D-053), player_inventory (#449, D-065).
/// v7 adds: pending_recognitions (#423, D-060 cognitive delay).
/// Future fields: ambient sound events, HUD state (D-020 expansion).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ObserverSnapshot {
@@ -56,6 +57,11 @@ pub struct ObserverSnapshot {
/// None when no monologue is triggered. Client shows text and auto-fades.
#[serde(default)]
pub current_monologue: Option<MonologueEvent>,
/// Entities undergoing cognitive delay recognition (#423, D-060).
/// Client renders these as grey blobs at position until recognition completes.
/// Empty when no recognitions are pending.
#[serde(default)]
pub pending_recognitions: Vec<PendingRecognitionWire>,
}
/// Game time data for client display (D-031)
@@ -382,6 +388,23 @@ pub enum VerbKind {
ExamineObject,
}
/// A recognition pending cognitive delay, included in ObserverSnapshot (#423, D-060).
/// Client renders entity as grey blob at position until recognition completes.
/// Visual transition: grey blob -> D-033 color + silhouette over ~0.3s.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PendingRecognitionWire {
/// Wire entity ID (may match entity_id in VisibleEntity if also in entities list)
pub entity_id: u64,
/// Render position
pub x: f32,
pub y: f32,
pub z: i32,
/// Remaining ticks until recognition completes (for progress animation)
pub remaining_ticks: u64,
/// Total delay for this recognition (for animation timing)
pub total_delay_ticks: u64,
}
/// Internal monologue event sent to the client for display (#414).
/// Contains the text and display duration. Client auto-fades after duration.
#[derive(Debug, Clone, Serialize, Deserialize)]