fix(simulation): wire triangle crisis event queue into observer snapshot

The TriangleCrisisEventQueue was populated by tick_triangle_escalation
but never drained into ObserverSnapshot — clients always saw an empty
vec despite protocol v16 advertising the field. Now drains the queue
each tick and converts to TriangleCrisisEventWire.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 22:48:11 +01:00
co-authored by Claude Opus 4.6
parent d34fc970a7
commit 9bc5925220
4 changed files with 22 additions and 1 deletions
+1
View File
@@ -213,6 +213,7 @@ mod tests {
world.init_resource::<ObservationEventQueue>(); world.init_resource::<ObservationEventQueue>();
world.init_resource::<VisibilityGeometry>(); world.init_resource::<VisibilityGeometry>();
world.init_resource::<ActivePerceptionMode>(); world.init_resource::<ActivePerceptionMode>();
world.init_resource::<crate::content::template::TriangleCrisisEventQueue>();
world world
} }
+1
View File
@@ -168,6 +168,7 @@ mod tests {
world.init_resource::<EntityRegistry>(); world.init_resource::<EntityRegistry>();
world.init_resource::<VisibilityGeometry>(); world.init_resource::<VisibilityGeometry>();
world.init_resource::<ActivePerceptionMode>(); world.init_resource::<ActivePerceptionMode>();
world.init_resource::<crate::content::template::TriangleCrisisEventQueue>();
world world
} }
+19 -1
View File
@@ -27,6 +27,7 @@ use crate::simulation::monologue::{MonologueBuffer, SprintAnomalyQueue};
use crate::simulation::movement::{PlayerCharacter, TilePosition, WalkabilityMap}; use crate::simulation::movement::{PlayerCharacter, TilePosition, WalkabilityMap};
use crate::simulation::poi::PointOfInterest; use crate::simulation::poi::PointOfInterest;
use crate::simulation::rng::SimRng; use crate::simulation::rng::SimRng;
use crate::content::template::TriangleCrisisEventQueue;
use crate::simulation::sound::SoundEventQueue; use crate::simulation::sound::SoundEventQueue;
use crate::simulation::stance::Stance; use crate::simulation::stance::Stance;
use crate::simulation::time::SimulationTime; use crate::simulation::time::SimulationTime;
@@ -99,6 +100,7 @@ pub fn compute_observer_snapshot(
inventory_items: Query<(Entity, &CarriedBy, &ItemName, &InventorySlot)>, inventory_items: Query<(Entity, &CarriedBy, &ItemName, &InventorySlot)>,
poi_query: Query<&PointOfInterest>, poi_query: Query<&PointOfInterest>,
mut buffer: ResMut<SnapshotBuffer>, mut buffer: ResMut<SnapshotBuffer>,
mut crisis_queue: ResMut<TriangleCrisisEventQueue>,
sim_rng: Option<Res<SimRng>>, sim_rng: Option<Res<SimRng>>,
pressure_query: Query<&crate::simulation::pressure::CharacterPressure, With<PlayerCharacter>>, pressure_query: Query<&crate::simulation::pressure::CharacterPressure, With<PlayerCharacter>>,
) { ) {
@@ -387,6 +389,22 @@ pub fn compute_observer_snapshot(
// Consume pending save/load result for this tick (#553). // Consume pending save/load result for this tick (#553).
let save_result = buffer.pending_save_result.take(); let save_result = buffer.pending_save_result.take();
// Drain triangle crisis events (#250) and convert to wire format.
let triangle_crisis_events = crisis_queue
.drain()
.into_iter()
.map(|e| TriangleCrisisEventWire {
triangle_id: e.triangle_id.0,
role_assignments: e
.role_assignments
.into_iter()
.map(|(role, sid)| (role.0, sid.0))
.collect(),
trigger_npc_id: e.trigger_npc.0,
tick: e.tick,
})
.collect();
buffer.snapshot = Some(ObserverSnapshot { buffer.snapshot = Some(ObserverSnapshot {
version: crate::bridge::types::PROTOCOL_VERSION, version: crate::bridge::types::PROTOCOL_VERSION,
tick: time.tick, tick: time.tick,
@@ -414,7 +432,7 @@ pub fn compute_observer_snapshot(
examine_result, examine_result,
player_knowledge, player_knowledge,
save_result, save_result,
triangle_crisis_events: vec![], triangle_crisis_events,
}); });
} }
+1
View File
@@ -16,6 +16,7 @@ fn setup_world(width: i32, height: i32) -> World {
world.init_resource::<VisibilityGeometry>(); world.init_resource::<VisibilityGeometry>();
world.init_resource::<ActivePerceptionMode>(); world.init_resource::<ActivePerceptionMode>();
world.init_resource::<crate::simulation::sound::SoundEventQueue>(); world.init_resource::<crate::simulation::sound::SoundEventQueue>();
world.init_resource::<crate::content::template::TriangleCrisisEventQueue>();
world world
} }