Repository: bevyengine/bevy
File: crates/bevy_time/src/lib.rs (Rust)

Code before:
#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)]
pub struct TimeSystems;

impl Plugin for TimePlugin {
    fn build(&self, app: &mut App) {
        app.init_resource::<Time>()
            .init_resource::<Time<Real>>()
            .init_resource::<Time<Virtual>>()
            .init_resource::<Time<Fixed>>()
            .init_resource::<TimeUpdateStrategy>();

        #[cfg(feature = "bevy_reflect")]
        {
            app.register_type::<Time>()
                .register_type::<Time<Real>>()
                .register_type::<Time<Virtual>>()
                .register_type::<Time<Fixed>>();
        }

        app.add_systems(
            First,
            time_system
                .in_set(TimeSystems)
                .ambiguous_with(message_update_system),
        )
        .add_systems(PreUpdate, delayed_queues_system)
        .add_systems(
            RunFixedMainLoop,
            run_fixed_main_schedule.in_set(RunFixedMainLoopSystems::FixedMainLoop),
        );

        // Ensure the messages are not dropped until `FixedMain` systems can observe them
        app.add_systems(FixedPostUpdate, signal_message_update_system);
        let mut message_registry = app.world_mut().resource_mut::<MessageRegistry>();
        // We need to start in a waiting state so that the messages are not updated until the first fixed update
        message_registry.should_update = ShouldUpdateMessages::Waiting;
    }
}

/// Configuration resource used to determine how the time system should run.
///
/// For most cases, [`TimeUpdateStrategy::Automatic`] is fine. When writing tests, dealing with
/// networking or similar, you may prefer to set the next [`Time`] value manually.
#[derive(Resource, Default)]
pub enum TimeUpdateStrategy {
    /// [`Time`] will be automatically updated each frame using an [`Instant`] sent from the render world.
    /// If nothing is sent, the system clock will be used instead.
    #[cfg_attr(feature = "std", doc = "See [`TimeSender`] for more details.")]
    #[default]
    Automatic,
    /// [`Time`] will be updated to the specified [`Instant`] value each frame.

Review comment (suggestion):
This will only operate on `Time<Virtual>` because of the location of this system.

I'm fine with that limitation for an initial PR, but I'm also happy to help advise you on how to lift it (`DelayedCommands` + `DelayedCommandQueue` should have a generic, copy the strategy from `Time`).

If we don't lift that limitation in this PR, we should document it clearly.

Code after:
#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)]
pub struct TimeSystems;

impl Plugin for TimePlugin {
    fn build(&self, app: &mut App) {
        app.init_resource::<Time>()
            .init_resource::<Time<Real>>()
            .init_resource::<Time<Virtual>>()
            .init_resource::<Time<Fixed>>()
            .init_resource::<TimeUpdateStrategy>();

        #[cfg(feature = "bevy_reflect")]
        {
            app.register_type::<Time>()
                .register_type::<Time<Real>>()
                .register_type::<Time<Virtual>>()
                .register_type::<Time<Fixed>>();
        }

        app.add_systems(
            First,
            time_system
                .in_set(TimeSystems)
                .ambiguous_with(message_update_system),
        )
        .add_systems(PreUpdate, check_delayed_command_queues)
        .add_systems(
            RunFixedMainLoop,
            run_fixed_main_schedule.in_set(RunFixedMainLoopSystems::FixedMainLoop),
        );

        // Ensure the messages are not dropped until `FixedMain` systems can observe them
        app.add_systems(FixedPostUpdate, signal_message_update_system);
        let mut message_registry = app.world_mut().resource_mut::<MessageRegistry>();
        // We need to start in a waiting state so that the messages are not updated until the first fixed update
        message_registry.should_update = ShouldUpdateMessages::Waiting;
    }
}

/// Configuration resource used to determine how the time system should run.
///
/// For most cases, [`TimeUpdateStrategy::Automatic`] is fine. When writing tests, dealing with
/// networking or similar, you may prefer to set the next [`Time`] value manually.
#[derive(Resource, Default)]
pub enum TimeUpdateStrategy {
    /// [`Time`] will be automatically updated each frame using an [`Instant`] sent from the render world.
    /// If nothing is sent, the system clock will be used instead.
    #[cfg_attr(feature = "std", doc = "See [`TimeSender`] for more details.")]
    #[default]
    Automatic,
    /// [`Time`] will be updated to the specified [`Instant`] value each frame.