Skip to content

Commit

Permalink
component net sync impl
Browse files Browse the repository at this point in the history
  • Loading branch information
JieningYu committed Aug 26, 2023
1 parent f3e3a6a commit 2974a60
Show file tree
Hide file tree
Showing 2 changed files with 232 additions and 22 deletions.
227 changes: 212 additions & 15 deletions core/src/component.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use std::{
any::TypeId,
collections::HashMap,
ops::{Deref, DerefMut},
};

use crate::net::NetSync;
use bytes::Bytes;
use tracing::{trace_span, warn};

use crate::net::{Decode, Encode, NetSync};

/// Represents a type of component that can be attached
/// on [`Components`].
Expand All @@ -18,28 +22,33 @@ pub trait Attach {
}

pub struct Components {
components: std::collections::HashMap<crate::Id, (Box<dyn Attach + Send + Sync>, TypeId)>,
components: HashMap<crate::Id, (Box<dyn Attach + Send + Sync>, TypeId)>,
}

impl Components {
pub fn new() -> Self {
Self {
components: std::collections::HashMap::new(),
components: HashMap::new(),
}
}

pub fn attach<T>(&mut self, id: crate::Id, mut component: T)
#[inline]
pub fn builder() -> ComponentsBuilder {
ComponentsBuilder { inner: Self::new() }
}

pub fn attach<T>(&mut self, id: crate::Id, component: T)
where
T: Attach + Send + Sync + 'static,
{
if self.components.contains_key(&id) {
panic!("component with id {id} already exist in this components!");
}

component.on_attach(self);
assert!(
!self.components.contains_key(&id),
"component with id {id} already exist in this components!"
);

self.components
.insert(id, (Box::new(component), TypeId::of::<T>()));
let mut boxed = Box::new(component);
boxed.on_attach(self);
self.components.insert(id, (boxed, TypeId::of::<T>()));
}

pub fn get<T>(&self, id: &crate::Id) -> Option<&T>
Expand Down Expand Up @@ -79,13 +88,201 @@ impl Components {
}
}

pub struct Synced<T>(pub T)
impl Encode for Components {
fn encode<B>(&self, buf: &mut B) -> anyhow::Result<()>
where
B: bytes::BufMut,
{
let Component(event) =
self.get::<Component<
crate::Event<dyn Fn(&mut HashMap<crate::Id, Bytes>) -> anyhow::Result<()>>,
>>(NET_SEND_ID.deref())
.expect("net send event component not found");

let mut hashmap = HashMap::new();
event.invoker()(&mut hashmap)?;
hashmap.encode(buf)
}
}

impl NetSync for Components {
fn read_buf<B>(&mut self, buf: &mut B) -> anyhow::Result<()>
where
B: bytes::Buf,
{
let Component(event) =
self.get::<Component<
crate::Event<dyn Fn(&mut HashMap<crate::Id, Bytes>) -> anyhow::Result<()>>,
>>(NET_SEND_ID.deref())
.expect("net recv event component not found");

let mut hashmap = HashMap::<crate::Id, Bytes>::decode(buf)?;
event.invoker()(&mut hashmap)
}
}

pub struct ComponentsBuilder {
inner: Components,
}

impl ComponentsBuilder {
pub fn net_sync(mut self) -> Self {
self.inner
.attach(net_send_event_comp_id(), net_send_event_comp());
self.inner
.attach(net_recv_event_comp_id(), net_recv_event_comp());
self
}

#[inline]
pub fn build(self) -> Components {
self.inner
}
}

impl Into<Components> for ComponentsBuilder {
fn into(self) -> Components {
self.build()
}
}

pub struct Component<T>(pub T);

impl<T> Attach for Component<T> {
fn on_attach(&mut self, _components: &mut Components) {}
}

impl<T> Deref for Component<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<T> DerefMut for Component<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

static NET_SEND_ID: once_cell::sync::Lazy<crate::Id> =
once_cell::sync::Lazy::new(net_send_event_comp_id);
static NET_RECV_ID: once_cell::sync::Lazy<crate::Id> =
once_cell::sync::Lazy::new(net_recv_event_comp_id);

pub struct Synced<T>(pub T, pub crate::Id)
where
T: Attach + NetSync;
T: Attach + NetSync + 'static;

impl<T> Attach for Synced<T>
where
T: Attach + NetSync,
T: Attach + NetSync + 'static,
{
fn on_attach(&mut self, components: &mut Components) {
self.0.on_attach(components);

let ptr = self as *mut Self;

let span = trace_span!(
"attach synced component",
comp_type = std::any::type_name::<T>()
);

let _ = span.enter();

if let Some(Component(event)) = components.get_mut::<Component<
crate::Event<dyn Fn(&mut HashMap<crate::Id, Bytes>) -> anyhow::Result<()>>,
>>(NET_SEND_ID.deref())
{
event.register(Box::new(move |map| {
let this = unsafe { &*ptr };

map.insert(this.1.clone(), {
let mut bytes_mut = bytes::BytesMut::new();
this.0.encode(&mut bytes_mut)?;

bytes_mut.into()
});

Ok(())
}))
} else {
warn!("network sending event not found");
}

if let Some(Component(event)) = components.get_mut::<Component<
crate::Event<dyn Fn(&mut HashMap<crate::Id, Bytes>) -> anyhow::Result<()>>,
>>(NET_RECV_ID.deref())
{
event.register(Box::new(move |map| {
let this = unsafe { &mut *ptr };
let mut bytes = map.insert(this.1.clone(), Bytes::new()).unwrap();

this.0.read_buf(&mut bytes)
}))
} else {
warn!("network receiving event not found");
}
}
}

impl<T> Deref for Synced<T>
where
T: Attach + NetSync + 'static,
{
fn on_attach(&mut self, components: &mut Components) {}
type Target = T;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<T> DerefMut for Synced<T>
where
T: Attach + NetSync + 'static,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

/// Creates a new event that handle network packet buf sending mapping,
/// which component id is `core:net_send`.
pub fn net_send_event_comp(
) -> Component<crate::Event<dyn Fn(&mut HashMap<crate::Id, Bytes>) -> anyhow::Result<()>>> {
Component(crate::Event::new(|listeners| {
Box::new(move |map| {
for listener in listeners {
listener(map)?;
}

Ok(())
})
}))
}

#[inline]
pub fn net_send_event_comp_id() -> crate::Id {
crate::Id::new("core", "net_send".to_string())
}

/// Creates a new event that handle network packet buf receiving mapping,
/// which component id is `core:net_recv`.
pub fn net_recv_event_comp(
) -> Component<crate::Event<dyn Fn(&mut HashMap<crate::Id, Bytes>) -> anyhow::Result<()>>> {
Component(crate::Event::new(|listeners| {
Box::new(move |map| {
for listener in listeners {
listener(map)?;
}

Ok(())
})
}))
}

#[inline]
pub fn net_recv_event_comp_id() -> crate::Id {
crate::Id::new("core", "net_recv".to_string())
}
27 changes: 20 additions & 7 deletions core/src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,6 @@ pub trait NetSync: Encode {
fn read_buf<B>(&mut self, buf: &mut B) -> anyhow::Result<()>
where
B: bytes::Buf;

fn write_buf<B>(&self, buf: &mut B) -> anyhow::Result<()>
where
B: bytes::BufMut,
{
self.encode(buf)
}
}

impl<T> NetSync for T
Expand Down Expand Up @@ -59,6 +52,26 @@ mod packet_buf_imp {

use super::*;

impl Encode for bytes::Bytes {
fn encode<B>(&self, buf: &mut B) -> anyhow::Result<()>
where
B: bytes::BufMut,
{
self.slice(..).encode(buf)
}
}

impl<'de> Decode<'de> for bytes::Bytes {
type Output = bytes::Bytes;

fn decode<B>(buf: &'de mut B) -> anyhow::Result<Self::Output>
where
B: bytes::Buf,
{
Vec::<u8>::decode(buf).map(bytes::Bytes::from)
}
}

impl Encode for u8 {
fn encode<B>(&self, buf: &mut B) -> anyhow::Result<()>
where
Expand Down

0 comments on commit 2974a60

Please sign in to comment.