diff --git a/NOTES.md b/NOTES.md index eac58b8..dfd9432 100644 --- a/NOTES.md +++ b/NOTES.md @@ -135,9 +135,9 @@ New custom events are written to the bevy event queue, to be consumed by my game During rollback, we check if we should exit rollback, having resimulated everything in the requested rollback range. -CheckIfRollbackNeeded +NotInRollback not in rb -Check if a newly added ServerSnapshot or ABAF/ICAF means we should rollback +Check if a newly added ServerSnapshot or ABAF/ICAF means we request a rollback StartRollback @@ -258,7 +258,7 @@ record component births. -DuringRollback +InRollback in rb wipe removed component queue, remove components which shouldn't exist at this frame @@ -287,7 +287,7 @@ wipe removed component queue, remove components which shouldn't exist at this fr ## How rollbacks happen Systems that initiate rollbacks write a `RollbackRequest` to an event queue, specifying the frame they -wish to start resimulating from. These are in the `CheckIfRollbackNeeded` set. +wish to start resimulating from. These are in the `NotInRollback` set. All rollback requests are consolidated, and a `Rollback` resource is written. The `RollbackConsolidationStrategy` from `TimewarpConfig` determines if the oldest or newest frame from the list of requests is used. diff --git a/src/components.rs b/src/components.rs index fe10796..cc19482 100644 --- a/src/components.rs +++ b/src/components.rs @@ -1,10 +1,10 @@ use crate::{prelude::TimewarpError, FrameBuffer, FrameNumber, TimewarpComponent}; use bevy::prelude::*; -/// entities with NotRollbackable are ignored, even if they have components which +/// entities with NoRollback are ignored, even if they have components which /// have been registered for rollback. #[derive(Component)] -pub struct NotRollbackable; +pub struct NoRollback; /// Added to every entity, for tracking which frame they were last synced to a snapshot /// Deduct `last_snapshot_frame` from the current frame to determine how many frames this @@ -32,6 +32,9 @@ impl TimewarpStatus { /// Used when you want to insert a component T, but for an older frame. /// insert this to an entity for an older frame will trigger a rollback. +/// +/// Note: this is for timewarp-registered components. +/// /// eg: /// ```rust,ignore /// commands.entity(e).insert(InsertComponentAtFrame::(shield_comp, past_frame)) @@ -47,13 +50,18 @@ impl InsertComponentAtFrame { } } -/// For assembling a blueprint in the past - testing. +/// When you want to rollback to insert a non-timewarp component at a specific frame, insert this. +/// +/// Note: this is for non-timewarp registered components. (ones without ComponentHistory) +/// +/// I use this for blueprints. The blueprint assembly function runs during rollback and +/// adds the various timewarp-registered (and other) components to the entity during rollback. #[derive(Component, Debug)] -pub struct AssembleBlueprintAtFrame { +pub struct AssembleBlueprintAtFrame { pub component: T, pub frame: FrameNumber, } -impl AssembleBlueprintAtFrame { +impl AssembleBlueprintAtFrame { pub fn new(frame: FrameNumber, component: T) -> Self { Self { component, frame } } @@ -62,12 +70,6 @@ impl AssembleBlueprintAtFrame { } } -/// presence on an entity during rollback means there will be no older values available, -/// since the entity is being assembled from blueprint this frame. -/// so we load in component values matching the origin frame (not one frame prior, like usual) -#[derive(Component, Debug, Clone)] -pub struct OriginFrame(pub FrameNumber); - /// entities with components that were registered with error correction logging will receive /// one of these components, updated with before/after values when a simulation correction /// resulting from a rollback and resimulate causes a snap. diff --git a/src/lib.rs b/src/lib.rs index 88c83d8..460a7d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -205,47 +205,25 @@ pub mod prelude { use bevy::prelude::*; use prelude::*; +/// bevy_timewarp's pre-game systems run in these sets, which get configured to run +/// before the main game logic (the set for which is provided in the plugin setup) #[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum TimewarpPrefixSet { First, - InRollback, - - /// Doesn't run in rollback - /// - /// Contains: - /// * detect_misuse_of_icaf - /// * trigger_rollback_when_snapshot_added - /// * trigger_rollback_when_icaf_added - /// then: - /// * consolidate_rollback_requests - /// then: - /// * apply_deferred (so the Rollback res might exist, Ch/SS added.) - CheckIfRollbackNeeded, - - /// Runs only if the Rollback resource was just Added<> - /// - /// * rollback_initiated - /// then: - /// * rollback_component - /// * rollback_component - /// ... + NotInRollback, StartRollback, - - /// Runs always, unpacks non-timewarp components at this frame. - /// Current used for blueprints. UnwrapBlueprints, - Last, } -/// bevy_timewarp's systems run in these three sets, which get configured to run +/// bevy_timewarp's post-game systems run in these sets, which get configured to run /// after the main game logic (the set for which is provided in the plugin setup) #[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum TimewarpPostfixSet { First, Components, - DuringRollback, + InRollback, Last, } @@ -276,8 +254,7 @@ impl Plugin for TimewarpPlugin { TimewarpPrefixSet::First, TimewarpPrefixSet::InRollback.run_if(resource_exists::()), // -- apply_deferred -- // - TimewarpPrefixSet::CheckIfRollbackNeeded - .run_if(not(resource_exists::())), + TimewarpPrefixSet::NotInRollback.run_if(not(resource_exists::())), // -- apply_deferred -- // TimewarpPrefixSet::StartRollback.run_if(resource_added::()), TimewarpPrefixSet::UnwrapBlueprints, @@ -293,12 +270,12 @@ impl Plugin for TimewarpPlugin { self.config.schedule(), apply_deferred .after(TimewarpPrefixSet::InRollback) - .before(TimewarpPrefixSet::CheckIfRollbackNeeded), + .before(TimewarpPrefixSet::NotInRollback), ) .add_systems( self.config.schedule(), apply_deferred - .after(TimewarpPrefixSet::CheckIfRollbackNeeded) + .after(TimewarpPrefixSet::NotInRollback) .before(TimewarpPrefixSet::StartRollback), ) // @@ -358,11 +335,11 @@ impl Plugin for TimewarpPlugin { .add_systems( self.config.schedule(), ( - systems::prefix_check_if_rollback_needed::consolidate_rollback_requests, + systems::prefix_not_in_rollback::consolidate_rollback_requests, apply_deferred, ) .chain() - .in_set(TimewarpPrefixSet::CheckIfRollbackNeeded), + .in_set(TimewarpPrefixSet::NotInRollback), ) .add_systems( self.config.schedule(), @@ -381,7 +358,7 @@ impl Plugin for TimewarpPlugin { ( TimewarpPostfixSet::First, TimewarpPostfixSet::Components, - TimewarpPostfixSet::DuringRollback.run_if(resource_exists::()), + TimewarpPostfixSet::InRollback.run_if(resource_exists::()), TimewarpPostfixSet::Last, ) .chain(), diff --git a/src/systems.rs b/src/systems.rs index b4709ae..3c91baf 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -2,13 +2,13 @@ use crate::prelude::*; use bevy::prelude::*; pub(crate) mod postfix_components; -pub(crate) mod postfix_during_rollback; +pub(crate) mod postfix_in_rollback; pub(crate) mod postfix_last; pub(crate) mod prefix_blueprints; -pub(crate) mod prefix_check_if_rollback_needed; pub(crate) mod prefix_first; pub(crate) mod prefix_in_rollback; +pub(crate) mod prefix_not_in_rollback; pub(crate) mod prefix_start_rollback; /// footgun protection - in case your clock ticking fn isn't running properly, this avoids diff --git a/src/systems/postfix_components.rs b/src/systems/postfix_components.rs index a466357..b83c743 100644 --- a/src/systems/postfix_components.rs +++ b/src/systems/postfix_components.rs @@ -17,7 +17,7 @@ fn debug_type() -> bool { pub(crate) fn remove_components_from_despawning_entities( mut q: Query< (Entity, &mut ComponentHistory, &DespawnMarker), - (Added, With), + (Added, With, Without), >, mut commands: Commands, game_clock: Res, @@ -36,12 +36,15 @@ pub(crate) fn remove_components_from_despawning_entities( /// Write current value of component to the ComponentHistory buffer for this frame pub(crate) fn record_component_history( - mut q: Query<( - Entity, - &T, - &mut ComponentHistory, - Option<&mut TimewarpCorrection>, - )>, + mut q: Query< + ( + Entity, + &T, + &mut ComponentHistory, + Option<&mut TimewarpCorrection>, + ), + Without, + >, game_clock: Res, mut commands: Commands, opt_rb: Option>, @@ -96,14 +99,7 @@ pub(crate) fn record_component_history( /// add the ComponentHistory and ServerSnapshot whenever an entity gets the T component. /// NB: you must have called `app.register_rollback::()` for this to work. pub(crate) fn add_timewarp_components( - q: Query< - (Entity, &T), - ( - Added, - Without, - Without>, - ), - >, + q: Query<(Entity, &T), (Added, Without, Without>)>, mut commands: Commands, game_clock: Res, timewarp_config: Res, @@ -142,7 +138,7 @@ pub(crate) fn add_timewarp_components( - mut q: Query<(Entity, &mut ComponentHistory), (Added, Without)>, + mut q: Query<(Entity, &mut ComponentHistory), (Added, Without)>, game_clock: Res, rb: Option>, ) { diff --git a/src/systems/postfix_during_rollback.rs b/src/systems/postfix_in_rollback.rs similarity index 100% rename from src/systems/postfix_during_rollback.rs rename to src/systems/postfix_in_rollback.rs diff --git a/src/systems/prefix_first.rs b/src/systems/prefix_first.rs index 4133248..6ec6b34 100644 --- a/src/systems/prefix_first.rs +++ b/src/systems/prefix_first.rs @@ -8,6 +8,7 @@ use crate::prelude::*; use bevy::prelude::*; +/// for when we add the ComponentHistory via a trait on EntityMut which doesn't know the error reporting setting pub(crate) fn enable_error_correction_for_new_component_histories( mut q: Query<&mut ComponentHistory, Added>>, ) { @@ -19,7 +20,7 @@ pub(crate) fn enable_error_correction_for_new_component_histories( mut removed: RemovedComponents, - mut q: Query<&mut ComponentHistory>, + mut q: Query<&mut ComponentHistory, Without>, game_clock: Res, ) { for entity in &mut removed { diff --git a/src/systems/prefix_check_if_rollback_needed.rs b/src/systems/prefix_not_in_rollback.rs similarity index 100% rename from src/systems/prefix_check_if_rollback_needed.rs rename to src/systems/prefix_not_in_rollback.rs diff --git a/src/systems/prefix_start_rollback.rs b/src/systems/prefix_start_rollback.rs index cad30e3..dfda512 100644 --- a/src/systems/prefix_start_rollback.rs +++ b/src/systems/prefix_start_rollback.rs @@ -77,25 +77,12 @@ enum Provenance { pub(crate) fn rollback_component( rb: Res, // T is None in case where component removed but ComponentHistory persists - mut q: Query< - ( - Entity, - Option<&mut T>, - &ComponentHistory, - Option<&OriginFrame>, - ), - Without, - >, + mut q: Query<(Entity, Option<&mut T>, &ComponentHistory), Without>, mut commands: Commands, game_clock: Res, ) { - for (entity, opt_comp, comp_hist, opt_originframe) in q.iter_mut() { - let rollback_frame = if let Some(OriginFrame(of)) = opt_originframe { - game_clock.frame().max(*of) - } else { - **game_clock - }; - + for (entity, opt_comp, comp_hist) in q.iter_mut() { + let rollback_frame = **game_clock; let end_frame = rb.range.end; let prefix = if rollback_frame != **game_clock { diff --git a/src/traits.rs b/src/traits.rs index ef635d9..7eb31d9 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -58,9 +58,9 @@ impl TimewarpTraits for App { ); self.add_systems( schedule.clone(), - prefix_check_if_rollback_needed::request_rollback_for_blueprints:: - .before(prefix_check_if_rollback_needed::consolidate_rollback_requests) - .in_set(TimewarpPrefixSet::CheckIfRollbackNeeded), + prefix_not_in_rollback::request_rollback_for_blueprints:: + .before(prefix_not_in_rollback::consolidate_rollback_requests) + .in_set(TimewarpPrefixSet::NotInRollback), ) } fn register_rollback_with_options( @@ -84,8 +84,7 @@ impl TimewarpTraits for App { } self.add_systems( schedule.clone(), // TODO RJRJR move to _first file? - prefix_check_if_rollback_needed::detect_misuse_of_icaf:: - .in_set(TimewarpPrefixSet::First), + prefix_not_in_rollback::detect_misuse_of_icaf::.in_set(TimewarpPrefixSet::First), ); self.add_systems( schedule.clone(), // TODO RJRJ MOVE FILE @@ -102,15 +101,12 @@ impl TimewarpTraits for App { self.add_systems( schedule.clone(), ( - prefix_check_if_rollback_needed::detect_misuse_of_icaf::, - prefix_check_if_rollback_needed::unpack_icafs_and_maybe_rollback::< - T, - CORRECTION_LOGGING, - >, - prefix_check_if_rollback_needed::apply_snapshots_and_maybe_rollback::, + prefix_not_in_rollback::detect_misuse_of_icaf::, + prefix_not_in_rollback::unpack_icafs_and_maybe_rollback::, + prefix_not_in_rollback::apply_snapshots_and_maybe_rollback::, ) - .before(prefix_check_if_rollback_needed::consolidate_rollback_requests) - .in_set(TimewarpPrefixSet::CheckIfRollbackNeeded), + .before(prefix_not_in_rollback::consolidate_rollback_requests) + .in_set(TimewarpPrefixSet::NotInRollback), ); self.add_systems( schedule.clone(), @@ -135,10 +131,10 @@ impl TimewarpTraits for App { self.add_systems( schedule.clone(), ( - postfix_during_rollback::rekill_components_during_rollback::, - postfix_during_rollback::clear_removed_components_queue::, + postfix_in_rollback::rekill_components_during_rollback::, + postfix_in_rollback::clear_removed_components_queue::, ) - .in_set(TimewarpPostfixSet::DuringRollback), + .in_set(TimewarpPostfixSet::InRollback), ) } }