lightyear_interpolation/
lib.rs

1//! Handles interpolation of entities between server updates
2#![no_std]
3
4extern crate alloc;
5#[cfg(feature = "std")]
6extern crate std;
7
8use bevy_ecs::{
9    component::{Component, HookContext, Mutable},
10    world::DeferredWorld,
11};
12pub use interpolate::InterpolateStatus;
13pub use interpolation_history::ConfirmedHistory;
14use lightyear_replication::prelude::Replicated;
15pub use plugin::{add_interpolation_systems, add_prepare_interpolation_systems};
16use tracing::error;
17
18use crate::manager::InterpolationManager;
19
20mod despawn;
21/// Contains the `InterpolateStatus` component and interpolation logic.
22pub mod interpolate;
23/// Defines `ConfirmedHistory` for storing historical states of confirmed entities.
24pub mod interpolation_history;
25mod manager;
26/// Provides the `InterpolationPlugin` and related systems for Bevy integration.
27pub mod plugin;
28mod registry;
29mod spawn;
30mod timeline;
31
32/// Commonly used items for client-side interpolation.
33pub mod prelude {
34    pub use crate::manager::InterpolationManager;
35    pub use crate::plugin::InterpolationSet;
36    pub use crate::registry::{InterpolationRegistrationExt, InterpolationRegistry};
37    pub use crate::timeline::InterpolationTimeline;
38    pub use crate::{Interpolated, InterpolationMode};
39}
40
41pub use lightyear_core::interpolation::Interpolated;
42
43pub(crate) fn interpolated_on_add_hook(mut deferred_world: DeferredWorld, context: HookContext) {
44    let interpolated = context.entity;
45    let confirmed = deferred_world
46        .get::<Interpolated>(interpolated)
47        .unwrap()
48        .confirmed_entity;
49    // TODO: maybe we need InitialReplicated? in case Replicated gets removed?
50    let Some(replicated) = deferred_world.get::<Replicated>(confirmed) else {
51        error!(
52            "Could not find the receiver associated with the interpolated entity {:?}",
53            interpolated
54        );
55        return;
56    };
57    if let Some(mut manager) = deferred_world.get_mut::<InterpolationManager>(replicated.receiver) {
58        manager
59            .interpolated_entity_map
60            .get_mut()
61            .confirmed_to_interpolated
62            .insert(confirmed, interpolated);
63    };
64}
65
66pub(crate) fn interpolated_on_remove_hook(mut deferred_world: DeferredWorld, context: HookContext) {
67    let interpolated = context.entity;
68    let confirmed = deferred_world
69        .get::<Interpolated>(interpolated)
70        .unwrap()
71        .confirmed_entity;
72    let Some(replicated) = deferred_world.get::<Replicated>(confirmed) else {
73        error!(
74            "Could not find the receiver associated with the interpolated entity {:?}",
75            interpolated
76        );
77        return;
78    };
79    if let Some(mut manager) = deferred_world.get_mut::<InterpolationManager>(replicated.receiver) {
80        manager
81            .interpolated_entity_map
82            .get_mut()
83            .confirmed_to_interpolated
84            .remove(&confirmed);
85    };
86}
87
88#[derive(Debug, Default, Clone, Copy, PartialEq)]
89/// Defines how interpolated component will be copied from the confirmed entity to the interpolated entity
90pub enum InterpolationMode {
91    /// Sync the component from the confirmed to the interpolated entity with the most precision
92    /// Interpolated: we will run interpolation between the last 2 confirmed states
93    Full,
94
95    /// Simple sync: whenever the confirmed entity gets updated, we propagate the update to the interpolated entity
96    /// Use this for components that don't get updated often or are not time-sensitive
97    ///
98    /// Interpolated: that means the component might not be rendered smoothly as it will only be updated after we receive a server update
99    Simple,
100
101    /// The component will be copied only-once from the confirmed to the interpolated entity, and then won't stay in sync
102    /// Useful for components that you want to modify yourself on the interpolated entity
103    Once,
104
105    #[default]
106    /// The component is not copied from the Confirmed entity to the interpolated entity
107    None,
108}
109
110/// Trait for components that can be synchronized for interpolation.
111///
112/// This is a marker trait, requiring `Component<Mutability=Mutable> + Clone + PartialEq`.
113/// Components implementing this trait can have their state managed by the interpolation systems
114/// according to the specified `InterpolationMode`.
115pub trait SyncComponent: Component<Mutability = Mutable> + Clone + PartialEq {}
116impl<T> SyncComponent for T where T: Component<Mutability = Mutable> + Clone + PartialEq {}