refactor(simulation): replace ad-hoc system ordering with TickPhase pipeline (#843)

10-phase linear pipeline: PreInput → Input → Movement → Simulation →
Economy → Storyteller → Snapshot → PostSnapshot → Knowledge → TickAdvance.

Each system assigned to exactly one phase via .in_set(TickPhase::X).
Cross-phase .after()/.before() eliminated — only intra-phase ordering
remains. Prevents schedule cycles by construction.

SimulationPlugin refactored into sub-plugins by domain:
  - InputPlugin (player actions, interactions, dialogue dispatch)
  - MovementPlugin (pathfinding, movement validation, spatial indexing)
  - SocialPlugin (conversations, sound, voice enrichment, follow state)
  - EconomyPlugin (tâtonnement tick, IPC query serving)
  - TimePlugin (chunk streaming, news ticker, tick advancement)

All other plugins (NPC, Knowledge, Perception, Storyteller, Settings,
Bridge) updated to use TickPhase assignments instead of cross-plugin
ordering constraints. BridgePlugin trimmed to bridge I/O concerns only.

Part A of #843. Parts B (multi-threaded executor) and C (background
workers) follow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-10 23:51:06 +02:00
co-authored by Claude Opus 4.6
parent d434235985
commit 47d4918cc8
15 changed files with 443 additions and 274 deletions
+55 -60
View File
@@ -31,6 +31,8 @@ pub struct NpcPlugin;
impl Plugin for NpcPlugin {
fn build(&self, app: &mut App) {
use crate::tick_phases::TickPhase;
app.init_resource::<relationships::RelationshipGraph>()
.init_resource::<relationships::TrustEventQueue>()
.init_resource::<relationships::PropagationQueue>()
@@ -41,73 +43,66 @@ impl Plugin for NpcPlugin {
.init_resource::<routine::RoutineDeviationEventQueue>()
.init_resource::<disclosure::DisclosureGlobalRateLimit>()
.init_resource::<trait_modifiers::TraitModifierConfig>()
// PreInput: routine phase transition (before pathfinding in Movement)
.add_systems(
Update,
routine::check_phase_transition.in_set(TickPhase::PreInput),
)
// Input: dialogue systems (consume player talk/walk-away/confrontation actions)
.add_systems(
Update,
(
routine::check_phase_transition
.before(crate::simulation::pathfinding::compute_paths),
mood::update_mood
.after(routine::check_phase_transition)
.before(crate::simulation::dialogue::process_talk_interaction),
relationships::update_trust
.after(crate::simulation::dialogue::process_talk_interaction)
.after(crate::simulation::dialogue::process_walk_away)
.after(crate::simulation::dialogue::process_confrontation_response)
.after(crate::simulation::dialogue::process_dialogue_response)
.before(crate::simulation::time::advance_tick),
relationships::propagate_social_actions
.after(relationships::update_trust)
.before(crate::simulation::time::advance_tick),
relationships::update_relationship_dynamics
.after(relationships::update_trust)
.before(crate::simulation::time::advance_tick),
routine::enter_activity
.after(crate::simulation::movement::validate_movement)
.before(crate::perception::observer::compute_observer_snapshot),
crate::simulation::dialogue::process_talk_interaction,
crate::simulation::dialogue::process_walk_away
.after(crate::simulation::dialogue::process_talk_interaction),
crate::simulation::dialogue::process_confrontation_response,
crate::simulation::dialogue::process_dialogue_response
.after(crate::simulation::dialogue::process_talk_interaction),
)
.in_set(TickPhase::Input),
)
// Simulation: NPC behavior — vision, awareness, mood, tolerance, routine,
// disclosure, background tick. Intra-phase ordering where needed.
.add_systems(
Update,
(
vision::compute_npc_vision,
vision::emit_npc_vision_events
.after(vision::compute_npc_vision),
awareness::detect_player_awareness
.after(vision::compute_npc_vision),
mood::update_mood,
tolerance::check_tolerance_threshold
.after(mood::update_mood)
.before(crate::simulation::time::advance_tick),
.after(awareness::detect_player_awareness),
routine::enter_activity,
routine::detect_routine_deviation
.after(routine::enter_activity)
.before(crate::perception::observer::compute_observer_snapshot),
tell_state::derive_tell_state
.after(mood::update_mood)
.after(routine::detect_routine_deviation)
.before(crate::perception::observer::compute_observer_snapshot),
background::background_tick
.after(crate::simulation::movement::validate_movement)
.before(crate::simulation::time::advance_tick),
disclosure::derive_disclosure_candidates
.before(crate::perception::observer::compute_observer_snapshot),
.after(routine::enter_activity),
background::background_tick,
disclosure::derive_disclosure_candidates,
disclosure::process_unprompted_disclosure
.after(disclosure::derive_disclosure_candidates)
.before(crate::perception::observer::compute_observer_snapshot),
// NPC player-awareness (#244)
awareness::detect_player_awareness
.after(vision::compute_npc_vision)
.before(tolerance::check_tolerance_threshold),
// NPC vision system (#115, D-011)
vision::compute_npc_vision
.after(crate::simulation::movement::validate_movement)
.after(crate::simulation::tier::update_tier_markers)
.before(crate::perception::observer::compute_observer_snapshot),
vision::emit_npc_vision_events
.after(vision::compute_npc_vision)
.before(crate::knowledge::events::process_knowledge_events),
vision::degrade_npc_inferences
.after(vision::emit_npc_vision_events)
.before(crate::simulation::time::advance_tick),
crate::simulation::dialogue::process_talk_interaction
.after(crate::simulation::input::process_player_input),
crate::simulation::dialogue::process_walk_away
.after(crate::simulation::input::process_player_input)
.after(crate::simulation::dialogue::process_talk_interaction),
crate::simulation::dialogue::process_confrontation_response
.after(crate::simulation::input::process_player_input),
crate::simulation::dialogue::process_dialogue_response
.after(crate::simulation::input::process_player_input)
.after(crate::simulation::dialogue::process_talk_interaction),
),
.after(disclosure::derive_disclosure_candidates),
)
.in_set(TickPhase::Simulation),
)
// Storyteller: tell state derivation (reads mood + routine deviation)
.add_systems(
Update,
tell_state::derive_tell_state
.in_set(TickPhase::Storyteller),
)
// Knowledge: relationships (trust, propagation, dynamics), vision degradation
.add_systems(
Update,
(
relationships::update_trust,
relationships::propagate_social_actions
.after(relationships::update_trust),
relationships::update_relationship_dynamics
.after(relationships::update_trust),
vision::degrade_npc_inferences,
)
.in_set(TickPhase::Knowledge),
);
tracing::debug!("NpcPlugin initialized");