diff --git a/core/src/component.rs b/core/src/component.rs index 9d4ce13..ee39f4f 100644 --- a/core/src/component.rs +++ b/core/src/component.rs @@ -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`]. @@ -18,28 +22,33 @@ pub trait Attach { } pub struct Components { - components: std::collections::HashMap, TypeId)>, + components: HashMap, TypeId)>, } impl Components { pub fn new() -> Self { Self { - components: std::collections::HashMap::new(), + components: HashMap::new(), } } - pub fn attach(&mut self, id: crate::Id, mut component: T) + #[inline] + pub fn builder() -> ComponentsBuilder { + ComponentsBuilder { inner: Self::new() } + } + + pub fn attach(&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::())); + let mut boxed = Box::new(component); + boxed.on_attach(self); + self.components.insert(id, (boxed, TypeId::of::())); } pub fn get(&self, id: &crate::Id) -> Option<&T> @@ -79,13 +88,201 @@ impl Components { } } -pub struct Synced(pub T) +impl Encode for Components { + fn encode(&self, buf: &mut B) -> anyhow::Result<()> + where + B: bytes::BufMut, + { + let Component(event) = + self.get::) -> 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(&mut self, buf: &mut B) -> anyhow::Result<()> + where + B: bytes::Buf, + { + let Component(event) = + self.get::) -> anyhow::Result<()>>, + >>(NET_SEND_ID.deref()) + .expect("net recv event component not found"); + + let mut hashmap = HashMap::::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 for ComponentsBuilder { + fn into(self) -> Components { + self.build() + } +} + +pub struct Component(pub T); + +impl Attach for Component { + fn on_attach(&mut self, _components: &mut Components) {} +} + +impl Deref for Component { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Component { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +static NET_SEND_ID: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(net_send_event_comp_id); +static NET_RECV_ID: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(net_recv_event_comp_id); + +pub struct Synced(pub T, pub crate::Id) where - T: Attach + NetSync; + T: Attach + NetSync + 'static; impl Attach for Synced 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::() + ); + + let _ = span.enter(); + + if let Some(Component(event)) = components.get_mut::) -> 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::) -> 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 Deref for Synced +where + T: Attach + NetSync + 'static, { - fn on_attach(&mut self, components: &mut Components) {} + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Synced +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) -> 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) -> 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()) } diff --git a/core/src/net/mod.rs b/core/src/net/mod.rs index 18fe24a..a2cd01e 100644 --- a/core/src/net/mod.rs +++ b/core/src/net/mod.rs @@ -24,13 +24,6 @@ pub trait NetSync: Encode { fn read_buf(&mut self, buf: &mut B) -> anyhow::Result<()> where B: bytes::Buf; - - fn write_buf(&self, buf: &mut B) -> anyhow::Result<()> - where - B: bytes::BufMut, - { - self.encode(buf) - } } impl NetSync for T @@ -59,6 +52,26 @@ mod packet_buf_imp { use super::*; + impl Encode for bytes::Bytes { + fn encode(&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(buf: &'de mut B) -> anyhow::Result + where + B: bytes::Buf, + { + Vec::::decode(buf).map(bytes::Bytes::from) + } + } + impl Encode for u8 { fn encode(&self, buf: &mut B) -> anyhow::Result<()> where