feat(simulation): #523 add zone_id to ObserverSnapshot (D-077, protocol v11)

Server-tracked zone_id on VisibleTile for D-073 zone crossfade and
D-059 deep fog temperature tint. ZoneMap resource backed by BTreeMap,
observer enrichment in snapshot assembly. Backwards-compatible: v10
payloads deserialize with zone_id: None.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 18:10:06 +01:00
co-authored by Claude Opus 4.6
parent c2de509c01
commit 51abc3e3c1
20 changed files with 213 additions and 6 deletions
+1
View File
@@ -268,6 +268,7 @@ mod tests {
z: 0,
visibility: VisibilitySector::Forward,
tile_kind: TileKind::Floor,
zone_id: None,
}],
nearby_interactions: vec![NearbyInteraction {
entity_id: 100,
+10 -2
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 = 10;
pub const PROTOCOL_VERSION: u8 = 11;
/// The ONLY data structure crossing the client-server boundary (D-020)
/// Contains all information visible to the observer at a given tick.
@@ -30,10 +30,11 @@ pub const PROTOCOL_VERSION: u8 = 10;
/// v9 adds: blocked_entities (#514, debug field for LOS-blocked entities).
/// 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).
/// Future fields: ambient sound events, HUD state (D-020 expansion).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ObserverSnapshot {
/// Protocol version for forward compatibility. Current: 10.
/// Protocol version for forward compatibility. Current: 11.
pub version: u8,
/// Simulation tick when this snapshot was produced
pub tick: u64,
@@ -209,6 +210,13 @@ pub struct VisibleTile {
/// Tile type for client rendering (floor, wall, door, object)
#[serde(default)]
pub tile_kind: TileKind,
/// Zone identifier for this tile (D-077 OQ-09, D-073 crossfade).
/// Server-authoritative zone assignment. Client maps zone_id to:
/// - Audio crossfade target (D-073)
/// - Deep fog temperature tint (D-059 layer 3)
/// None for tiles outside any defined zone (corridors, transition spaces).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub zone_id: Option<u16>,
}
/// Tile type for rendering. Derived from WalkabilityMap on the server side.