use bevy::prelude::App;
use lightyear_macros::ChannelInternal;
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::fmt::Debug;
use crate::channel::builder::{Channel, ChannelSettings};
use crate::inputs::UserInput;
use crate::protocol::channel::ChannelRegistry;
use crate::protocol::component::{ComponentProtocol, ComponentProtocolKind};
use crate::protocol::message::MessageProtocol;
use crate::serialize::reader::ReadBuffer;
use crate::serialize::writer::WriteBuffer;
use crate::shared::replication::ReplicationSend;
pub(crate) mod channel;
pub(crate) mod component;
pub(crate) mod message;
pub(crate) mod registry;
pub trait Protocol: Send + Sync + Clone + Debug + 'static {
type Input: UserInput;
type Message: MessageProtocol<Protocol = Self>;
type Components: ComponentProtocol<Protocol = Self>;
type ComponentKinds: ComponentProtocolKind<Protocol = Self>;
fn add_channel<C: Channel>(&mut self, settings: ChannelSettings) -> &mut Self;
fn channel_registry(&self) -> &ChannelRegistry;
fn add_per_component_replication_send_systems<R: ReplicationSend<Self>>(app: &mut App);
}
#[macro_export]
macro_rules! protocolize {
(
Self = $protocol:ident,
Message = $message:ty,
Component = $components:ty,
Input = $input:ty,
Crate = $shared_crate_name:ident,
) => {
use $shared_crate_name::_reexport::paste;
paste! {
mod [<$protocol:lower _module>] {
use super::*;
use bevy::prelude::*;
use $shared_crate_name::prelude::*;
use $shared_crate_name::_reexport::*;
#[derive(Debug, Clone)]
pub struct $protocol {
channel_registry: ChannelRegistry,
}
impl Protocol for $protocol {
type Input = $input;
type Message = $message;
type Components = $components;
type ComponentKinds = [<$components Kind>];
fn add_channel<C: Channel>(&mut self, settings: ChannelSettings) -> &mut Self {
self.channel_registry.add::<C>(settings);
self
}
fn channel_registry(&self) -> &ChannelRegistry {
&self.channel_registry
}
fn add_per_component_replication_send_systems<R: ReplicationSend<Self>>(app: &mut App) {
Self::Components::add_per_component_replication_send_systems::<R>(app);
}
}
impl Default for $protocol {
fn default() -> Self {
let mut protocol = Self {
channel_registry: ChannelRegistry::default(),
};
protocol.add_channel::<EntityActionsChannel>(ChannelSettings {
mode: ChannelMode::UnorderedReliable(ReliableSettings::default()),
direction: ChannelDirection::Bidirectional,
});
protocol.add_channel::<EntityUpdatesChannel>(ChannelSettings {
mode: ChannelMode::UnorderedUnreliableWithAcks,
direction: ChannelDirection::Bidirectional,
});
protocol.add_channel::<PingChannel>(ChannelSettings {
mode: ChannelMode::SequencedUnreliable,
direction: ChannelDirection::Bidirectional,
});
protocol.add_channel::<InputChannel>(ChannelSettings {
mode: ChannelMode::SequencedUnreliable,
direction: ChannelDirection::ClientToServer,
});
protocol.add_channel::<DefaultUnorderedUnreliableChannel>(ChannelSettings {
mode: ChannelMode::UnorderedUnreliable,
direction: ChannelDirection::Bidirectional,
});
protocol.add_channel::<TickBufferChannel>(ChannelSettings {
mode: ChannelMode::TickBuffered,
direction: ChannelDirection::ClientToServer,
});
protocol
}
}
}
pub use [<$protocol:lower _module>]::$protocol;
}
};
(
Self = $protocol:ident,
Message = $message:ty,
Component = $components:ty,
Crate = $shared_crate_name:ident,
) => {
protocolize!{
Self = $protocol,
Message = $message,
Component = $components,
Input = (),
Crate = $shared_crate_name,
}
};
(
Self = $protocol:ident,
Message = $message:ty,
Component = $components:ty,
Input = $input:ty,
) => {
protocolize!{
Self = $protocol,
Message = $message,
Component = $components,
Input = $input,
Crate = lightyear,
}
};
(
Self = $protocol:ident,
Message = $message:ty,
Component = $components:ty,
) => {
protocolize!{
Self = $protocol,
Message = $message,
Component = $components,
Input = (),
Crate = lightyear,
}
};
}
pub trait BitSerializable: Clone {
fn encode(&self, writer: &mut impl WriteBuffer) -> anyhow::Result<()>;
fn decode(reader: &mut impl ReadBuffer) -> anyhow::Result<Self>
where
Self: Sized;
}
impl<T> BitSerializable for T
where
T: Serialize + DeserializeOwned + Clone,
{
fn encode(&self, writer: &mut impl WriteBuffer) -> anyhow::Result<()> {
writer.serialize(self)
}
fn decode(reader: &mut impl ReadBuffer) -> anyhow::Result<Self>
where
Self: Sized,
{
reader.deserialize::<Self>()
}
}
pub trait EventContext: Send + Sync + 'static {}
impl<T: Send + Sync + 'static> EventContext for T {}