use crate::channel::builder::{Channel, EntityActionsChannel, EntityUpdatesChannel};
use crate::netcode::ClientId;
use crate::protocol::channel::ChannelKind;
use crate::server::room::{ClientVisibility, RoomId};
use bevy::prelude::{Component, Entity};
use bevy::utils::{HashMap, HashSet};
use lightyear_macros::MessageInternal;
use serde::{Deserialize, Serialize};
#[derive(Component, Clone, Copy)]
pub struct DespawnTracker;
#[derive(Component, Clone)]
pub struct Replicate {
pub replication_target: NetworkTarget,
pub prediction_target: NetworkTarget,
pub interpolation_target: NetworkTarget,
pub replication_clients_cache: HashMap<ClientId, ClientVisibility>,
pub replication_mode: ReplicationMode,
pub replication_group: ReplicationGroup,
}
impl Replicate {
pub(crate) fn group_id(&self, entity: Option<Entity>) -> ReplicationGroupId {
match self.replication_group {
ReplicationGroup::FromEntity => {
ReplicationGroupId(entity.expect("need to provide an entity").to_bits())
}
ReplicationGroup::Group(id) => ReplicationGroupId(id),
}
}
}
#[derive(Debug, Default, Copy, Clone)]
pub enum ReplicationGroup {
#[default]
FromEntity,
Group(u64),
}
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ReplicationGroupId(pub u64);
#[derive(Clone, Copy, Default, Debug, PartialEq)]
pub enum ReplicationMode {
Room,
#[default]
NetworkTarget,
}
impl Default for Replicate {
fn default() -> Self {
Self {
replication_target: NetworkTarget::All,
prediction_target: NetworkTarget::None,
interpolation_target: NetworkTarget::None,
replication_clients_cache: HashMap::new(),
replication_mode: ReplicationMode::default(),
replication_group: Default::default(),
}
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub enum NetworkTarget {
#[default]
None,
AllExcept(Vec<ClientId>),
All,
Only(Vec<ClientId>),
}
impl NetworkTarget {
pub(crate) fn should_send_to(&self, client_id: &ClientId) -> bool {
match self {
NetworkTarget::All => true,
NetworkTarget::AllExcept(client_ids) => !client_ids.contains(client_id),
NetworkTarget::Only(client_ids) => client_ids.contains(client_id),
NetworkTarget::None => false,
}
}
pub(crate) fn exclude(&mut self, client_ids: Vec<ClientId>) {
match self {
NetworkTarget::All => {
*self = NetworkTarget::AllExcept(client_ids);
}
NetworkTarget::AllExcept(existing_client_ids) => {
let mut new_excluded_ids = HashSet::from_iter(existing_client_ids.clone());
client_ids.into_iter().for_each(|id| {
new_excluded_ids.insert(id);
});
*existing_client_ids = Vec::from_iter(new_excluded_ids);
}
NetworkTarget::Only(existing_client_ids) => {
let mut new_ids = HashSet::from_iter(existing_client_ids.clone());
client_ids.into_iter().for_each(|id| {
new_ids.remove(&id);
});
if new_ids.is_empty() {
*self = NetworkTarget::None;
} else {
*existing_client_ids = Vec::from_iter(new_ids);
}
}
NetworkTarget::None => {}
}
}
}
#[derive(Component, MessageInternal, Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct ShouldBeInterpolated;
#[derive(Component, MessageInternal, Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct ShouldBePredicted;
#[cfg(test)]
mod tests {
use super::*;
use crate::prelude::ClientId;
#[test]
fn test_network_target() {
let mut target = NetworkTarget::All;
assert!(target.should_send_to(&0));
target.exclude(vec![1, 2]);
assert_eq!(target, NetworkTarget::AllExcept(vec![1, 2]));
target = NetworkTarget::AllExcept(vec![0]);
assert!(!target.should_send_to(&0));
assert!(target.should_send_to(&1));
target.exclude(vec![0, 1]);
assert!(matches!(target, NetworkTarget::AllExcept(_)));
if let NetworkTarget::AllExcept(ids) = target {
assert!(ids.contains(&0));
assert!(ids.contains(&1));
}
target = NetworkTarget::Only(vec![0]);
assert!(target.should_send_to(&0));
assert!(!target.should_send_to(&1));
target.exclude(vec![1]);
assert_eq!(target, NetworkTarget::Only(vec![0]));
target.exclude(vec![0, 2]);
assert_eq!(target, NetworkTarget::None);
target = NetworkTarget::None;
assert!(!target.should_send_to(&0));
target.exclude(vec![1]);
assert_eq!(target, NetworkTarget::None);
}
}