use std::collections::HashMap;
use bevy::prelude::{Component, Entity};
use crate::connection::events::{
ConnectionEvents, IterEntityDespawnEvent, IterEntitySpawnEvent, IterMessageEvent,
};
use crate::netcode::ClientId;
use crate::packet::message::Message;
use crate::protocol::Protocol;
use crate::shared::ping::message::{Ping, Pong};
pub struct ServerEvents<P: Protocol> {
pub disconnects: Vec<ClientId>,
pub events: HashMap<ClientId, ConnectionEvents<P>>,
pub empty: bool,
}
impl<P: Protocol> ServerEvents<P> {
pub(crate) fn new() -> Self {
Self {
disconnects: Vec::new(),
events: HashMap::new(),
empty: true,
}
}
pub(crate) fn clear(&mut self) {
self.disconnects = Vec::new();
self.empty = true;
self.events = HashMap::new();
}
pub fn is_empty(&self) -> bool {
self.empty
}
pub fn iter_connections(&self) -> impl Iterator<Item = ClientId> + '_ {
self.events
.iter()
.filter_map(|(client_id, events)| events.has_connection().then_some(*client_id))
}
pub fn has_connections(&self) -> bool {
self.events
.iter()
.any(|(_, connection_events)| connection_events.has_connection())
}
pub fn iter_disconnections(&mut self) -> impl Iterator<Item = ClientId> + '_ {
std::mem::take(&mut self.disconnects).into_iter()
}
pub fn has_disconnections(&self) -> bool {
!self.disconnects.is_empty()
}
pub(crate) fn push_disconnects(&mut self, client_id: ClientId) {
self.disconnects.push(client_id);
self.empty = false;
}
pub(crate) fn push_events(&mut self, client_id: ClientId, events: ConnectionEvents<P>) {
if !events.is_empty() {
self.events.insert(client_id, events);
self.empty = false;
}
}
}
impl<P: Protocol> IterMessageEvent<P, ClientId> for ServerEvents<P> {
fn into_iter_messages<M: Message>(&mut self) -> Box<dyn Iterator<Item = (M, ClientId)> + '_>
where
P::Message: TryInto<M, Error = ()>,
{
Box::new(self.events.iter_mut().flat_map(|(client_id, events)| {
let messages = events.into_iter_messages::<M>().map(|(message, _)| message);
let client_ids = std::iter::once(*client_id).cycle();
messages.zip(client_ids)
}))
}
fn has_messages<M: Message>(&self) -> bool {
self.events
.iter()
.any(|(_, connection_events)| connection_events.has_messages::<M>())
}
}
impl<P: Protocol> IterEntitySpawnEvent<ClientId> for ServerEvents<P> {
fn into_iter_entity_spawn(&mut self) -> Box<dyn Iterator<Item = (Entity, ClientId)> + '_> {
Box::new(self.events.iter_mut().flat_map(|(client_id, events)| {
let entities = events.into_iter_entity_spawn().map(|(entity, _)| entity);
let client_ids = std::iter::once(*client_id).cycle();
entities.zip(client_ids)
}))
}
fn has_entity_spawn(&self) -> bool {
self.events
.iter()
.any(|(_, connection_events)| connection_events.has_entity_spawn())
}
}
impl<P: Protocol> IterEntityDespawnEvent<ClientId> for ServerEvents<P> {
fn into_iter_entity_despawn(&mut self) -> Box<dyn Iterator<Item = (Entity, ClientId)> + '_> {
Box::new(self.events.iter_mut().flat_map(|(client_id, events)| {
let entities = events.into_iter_entity_despawn().map(|(entity, _)| entity);
let client_ids = std::iter::once(*client_id).cycle();
entities.zip(client_ids)
}))
}
fn has_entity_despawn(&self) -> bool {
self.events
.iter()
.any(|(_, connection_events)| connection_events.has_entity_despawn())
}
}
pub type ConnectEvent = crate::shared::events::ConnectEvent<ClientId>;
pub type DisconnectEvent = crate::shared::events::DisconnectEvent<ClientId>;
pub type InputEvent<I> = crate::shared::events::InputEvent<I, ClientId>;
pub type EntitySpawnEvent = crate::shared::events::EntitySpawnEvent<ClientId>;
pub type EntityDespawnEvent = crate::shared::events::EntityDespawnEvent<ClientId>;
pub type ComponentUpdateEvent<C> = crate::shared::events::ComponentUpdateEvent<C, ClientId>;
pub type ComponentInsertEvent<C> = crate::shared::events::ComponentInsertEvent<C, ClientId>;
pub type ComponentRemoveEvent<C> = crate::shared::events::ComponentRemoveEvent<C, ClientId>;
pub type MessageEvent<M> = crate::shared::events::MessageEvent<M, ClientId>;
#[cfg(test)]
mod tests {
use crate::protocol::channel::ChannelKind;
use crate::tests::protocol::{
Channel1, Channel2, Message1, Message2, MyMessageProtocol, MyProtocol,
};
use super::*;
#[test]
fn test_iter_messages() {
let mut events_1 = ConnectionEvents::<MyProtocol>::new();
let channel_kind_1 = ChannelKind::of::<Channel1>();
let channel_kind_2 = ChannelKind::of::<Channel2>();
let message1_a = Message1("hello".to_string());
let message1_b = Message1("world".to_string());
events_1.push_message(
channel_kind_1,
MyMessageProtocol::Message1(message1_a.clone()),
);
events_1.push_message(
channel_kind_2,
MyMessageProtocol::Message1(message1_b.clone()),
);
events_1.push_message(channel_kind_1, MyMessageProtocol::Message2(Message2(1)));
let mut server_events = ServerEvents::<MyProtocol>::new();
server_events.push_events(1, events_1);
let mut events_2 = ConnectionEvents::<MyProtocol>::new();
let message1_c = Message1("test".to_string());
events_2.push_message(
channel_kind_1,
MyMessageProtocol::Message1(message1_c.clone()),
);
events_2.push_message(channel_kind_1, MyMessageProtocol::Message2(Message2(2)));
server_events.push_events(2, events_2);
let messages: Vec<(Message1, ClientId)> = server_events.into_iter_messages().collect();
assert_eq!(messages.len(), 3);
assert!(messages.contains(&(message1_a, 1)));
assert!(messages.contains(&(message1_b, 1)));
assert!(messages.contains(&(message1_c, 2)));
assert!(!server_events
.events
.get(&1)
.unwrap()
.has_messages::<Message1>());
assert!(!server_events
.events
.get(&2)
.unwrap()
.has_messages::<Message1>());
assert!(server_events
.events
.get(&2)
.unwrap()
.has_messages::<Message2>());
}
}