use std::ops::Deref;
use bevy::prelude::{
Commands, Component, DetectChanges, Entity, EventReader, Query, Ref, Res, ResMut, With, Without,
};
use tracing::{debug, error, info, trace};
use crate::client::components::Confirmed;
use crate::client::components::{ComponentSyncMode, SyncComponent};
use crate::client::events::ComponentUpdateEvent;
use crate::client::interpolation::interpolate::InterpolateStatus;
use crate::client::interpolation::Interpolated;
use crate::client::resource::Client;
use crate::protocol::Protocol;
use crate::shared::tick_manager::Tick;
use crate::utils::ready_buffer::ReadyBuffer;
#[derive(Component, Debug)]
pub struct ConfirmedHistory<T: SyncComponent> {
pub buffer: ReadyBuffer<Tick, T>,
}
impl<T: SyncComponent> Default for ConfirmedHistory<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: SyncComponent> PartialEq for ConfirmedHistory<T> {
fn eq(&self, other: &Self) -> bool {
self.buffer.heap.iter().eq(other.buffer.heap.iter())
}
}
impl<T: SyncComponent> ConfirmedHistory<T> {
pub fn new() -> Self {
Self {
buffer: ReadyBuffer::new(),
}
}
pub(crate) fn clear(&mut self) {
self.buffer = ReadyBuffer::new();
}
pub(crate) fn peek(&mut self) -> Option<(Tick, &T)> {
self.buffer.heap.peek().map(|item| (item.key, &item.item))
}
pub(crate) fn pop(&mut self) -> Option<(Tick, T)> {
self.buffer.heap.pop().map(|item| (item.key, item.item))
}
pub(crate) fn pop_until_tick(&mut self, tick: Tick) -> Option<(Tick, T)> {
self.buffer.pop_until(&tick)
}
}
pub(crate) fn add_component_history<T: SyncComponent, P: Protocol>(
mut commands: Commands,
client: ResMut<Client<P>>,
interpolated_entities: Query<Entity, (Without<ConfirmedHistory<T>>, With<Interpolated>)>,
confirmed_entities: Query<(&Confirmed, Ref<T>)>,
) {
for (confirmed_entity, confirmed_component) in confirmed_entities.iter() {
if let Some(p) = confirmed_entity.interpolated {
if let Ok(interpolated_entity) = interpolated_entities.get(p) {
if confirmed_component.is_added() {
let mut interpolated_entity_mut =
commands.get_entity(interpolated_entity).unwrap();
let history = ConfirmedHistory::<T>::new();
match T::mode() {
ComponentSyncMode::Full => {
debug!("spawn interpolation history");
interpolated_entity_mut.insert((
confirmed_component.deref().clone(),
history,
InterpolateStatus::<T> {
start: None,
end: None,
current: client.interpolation_tick(),
},
));
}
_ => {
debug!("copy interpolation component");
interpolated_entity_mut.insert(confirmed_component.deref().clone());
}
}
}
}
}
}
}
pub(crate) fn apply_confirmed_update<T: SyncComponent, P: Protocol>(
client: Res<Client<P>>,
mut interpolated_entities: Query<
(&mut T, Option<&mut ConfirmedHistory<T>>),
(With<Interpolated>, Without<Confirmed>),
>,
confirmed_entities: Query<(Entity, &Confirmed, Ref<T>)>,
) {
for (confirmed_entity, confirmed, confirmed_component) in confirmed_entities.iter() {
if let Some(p) = confirmed.interpolated {
if confirmed_component.is_changed() {
if let Ok((mut interpolated_component, history_option)) =
interpolated_entities.get_mut(p)
{
match T::mode() {
ComponentSyncMode::Full => {
let Some(mut history) = history_option else {
error!(
"Interpolated entity {:?} doesn't have a ComponentHistory",
p
);
continue;
};
let Some(channel) = client
.replication_manager()
.channel_by_local(confirmed_entity)
else {
error!(
"Could not find replication channel for entity {:?}",
confirmed_entity
);
continue;
};
trace!(tick = ?channel.latest_tick, "adding confirmed update to history");
history
.buffer
.add_item(channel.latest_tick, confirmed_component.deref().clone());
}
ComponentSyncMode::Simple => {
*interpolated_component = confirmed_component.deref().clone();
}
ComponentSyncMode::Once => {}
}
}
}
}
}
}