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:
@@ -354,32 +354,28 @@ pub struct StorytellerPlugin;
|
||||
|
||||
impl Plugin for StorytellerPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
use crate::tick_phases::TickPhase;
|
||||
|
||||
app.init_resource::<ContaminationActive>()
|
||||
.init_resource::<ContaminationEventQueue>()
|
||||
.init_resource::<ActivationState>()
|
||||
.init_resource::<TriangleActivatedQueue>()
|
||||
.init_resource::<MovementHistoryBuffer>()
|
||||
.add_systems(Update, tick_contamination_activation)
|
||||
// Storyteller phase: contamination, activation, tell escalation.
|
||||
// Intra-phase ordering: contamination + history → activation → escalation
|
||||
.add_systems(
|
||||
Update,
|
||||
append_player_history.after(crate::simulation::movement::validate_movement),
|
||||
)
|
||||
.add_systems(
|
||||
Update,
|
||||
activation_pass
|
||||
.after(append_player_history)
|
||||
.after(tick_contamination_activation)
|
||||
.before(crate::simulation::time::advance_tick),
|
||||
)
|
||||
.add_systems(
|
||||
Update,
|
||||
escalate_tells_on_activation
|
||||
.after(activation_pass)
|
||||
.before(crate::npc::tell_state::derive_tell_state),
|
||||
)
|
||||
.add_systems(
|
||||
Update,
|
||||
expire_routine_deviations.before(crate::npc::tell_state::derive_tell_state),
|
||||
(
|
||||
tick_contamination_activation,
|
||||
append_player_history,
|
||||
activation_pass
|
||||
.after(append_player_history)
|
||||
.after(tick_contamination_activation),
|
||||
escalate_tells_on_activation
|
||||
.after(activation_pass),
|
||||
expire_routine_deviations,
|
||||
)
|
||||
.in_set(TickPhase::Storyteller),
|
||||
);
|
||||
|
||||
tracing::debug!("StorytellerPlugin initialized");
|
||||
@@ -510,7 +506,7 @@ pub fn activation_pass(
|
||||
.collect();
|
||||
|
||||
if simmering.is_empty() {
|
||||
tracing::warn!("activation_pass: no Simmering triangles — holding");
|
||||
// Normal state — no triangles ready for activation yet. Silent return.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user