- workers/pool.rs: 5 new tests; catch_unwind keeps worker threads alive on handler panic (in-flight request loss unchanged, pinned by test + #843 docs); stubs.rs no longer falsely claims the pool is tested - save/load: execute_save_load pinned .after(Storyteller) so the scheduler cannot legally save pre-Input state; exclusive-system exception recorded in tick_phases.rs rules - surname corpus extracted to bin/shared/surname_corpus.rs (both economy generators import it; byte-identical output verified on 23.6MB+1.45MB TOMLs); all three stamp/watch registries updated - generator_spike gated behind non-default 'generator-spike' feature - economy.rs: 11 new D-181 signal-derivation tests on the new econ_sim Simulation::from_economy in-memory constructor - perception exemption comments now state the consumer sort contract; unused bytemuck removed; rayon comment corrected; the 22 allow(dead_code) documented as serde schema enforcement Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
90 lines
3.5 KiB
Rust
90 lines
3.5 KiB
Rust
//! Server tick cycle — named system set phases (#843).
|
|
//!
|
|
//! Replaces ad-hoc `.after()`/`.before()` constraints with a linear pipeline.
|
|
//! Each system belongs to exactly one phase. Phases execute sequentially.
|
|
//! Within a phase, systems with no intra-phase ordering run in parallel
|
|
//! (when the multi-threaded executor is enabled).
|
|
//!
|
|
//! ```text
|
|
//! PreInput → Input → Movement → Simulation → Economy
|
|
//! → Storyteller → Snapshot → PostSnapshot → Knowledge → TickAdvance
|
|
//! ```
|
|
//!
|
|
//! ## Rules
|
|
//!
|
|
//! 1. Every system in the Update schedule MUST have `.in_set(TickPhase::X)`.
|
|
//! 2. Cross-phase `.after()`/`.before()` is FORBIDDEN — if you need it,
|
|
//! the system is in the wrong phase.
|
|
//! 3. Intra-phase `.after()`/`.before()` is allowed for systems within
|
|
//! the same phase that have a real data dependency.
|
|
//!
|
|
//! **Exception — exclusive systems.** Exclusive systems (`&mut World`) cannot
|
|
//! use `.in_set()` in Bevy 0.18, so rule 1 is unsatisfiable for them. Instead
|
|
//! they MUST be pinned into their phase window with explicit constraints on
|
|
//! BOTH sides: `.after(TickPhase::<previous phase>)` for the lower bound and
|
|
//! `.before(...)`/`.after(...)` against systems or the phase sets around them
|
|
//! for the upper bound. A one-sided constraint leaves the scheduler free to
|
|
//! run the system anywhere earlier/later in the tick. Sole current instance:
|
|
//! `save_io::execute_save_load` (simulation/mod.rs), pinned after
|
|
//! `Storyteller` and before `compute_observer_snapshot` (Snapshot phase).
|
|
|
|
use bevy_app::prelude::*;
|
|
use bevy_ecs::prelude::*;
|
|
use bevy_ecs::schedule::IntoScheduleConfigs;
|
|
|
|
/// The 10 phases of the server tick cycle.
|
|
///
|
|
/// Ordered linearly: each phase completes before the next begins.
|
|
/// Configure once in the App with `configure_sets(Update, ...)`.
|
|
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
pub enum TickPhase {
|
|
/// Setup before player input: chunk streaming, bridge input, NPC routine transitions.
|
|
PreInput,
|
|
/// Process player actions: input dispatch, door/terminal/examine interactions, dialogue.
|
|
Input,
|
|
/// Position resolution: pathfinding, path following, movement validation, spatial indexing.
|
|
Movement,
|
|
/// Game logic: NPC behavior, vision, conversations, monologue, sound, visibility geometry.
|
|
Simulation,
|
|
/// Economics: tick the economy simulation, serve economy state queries.
|
|
Economy,
|
|
/// Storyteller: contamination, activation, tell escalation, tell state derivation.
|
|
Storyteller,
|
|
/// Assemble tick output: observer snapshot, ticker, settings, debug commands, save/load.
|
|
Snapshot,
|
|
/// React to snapshot: observation events, send to client, anomaly detection.
|
|
PostSnapshot,
|
|
/// Update persistent state: knowledge events, cognitive delay, relationships.
|
|
Knowledge,
|
|
/// Increment the clock. Must be last.
|
|
TickAdvance,
|
|
}
|
|
|
|
impl TickPhase {
|
|
/// Configure the linear phase ordering on the app.
|
|
///
|
|
/// Call once during plugin setup:
|
|
/// ```ignore
|
|
/// TickPhase::configure(&mut app);
|
|
/// ```
|
|
pub fn configure(app: &mut bevy_app::App) {
|
|
use TickPhase::*;
|
|
app.configure_sets(
|
|
Update,
|
|
(
|
|
PreInput,
|
|
Input,
|
|
Movement,
|
|
Simulation,
|
|
Economy,
|
|
Storyteller,
|
|
Snapshot,
|
|
PostSnapshot,
|
|
Knowledge,
|
|
TickAdvance,
|
|
)
|
|
.chain(),
|
|
);
|
|
}
|
|
}
|