Skip to main content

naia_shared/messages/
message.rs

1use std::{any::Any, collections::HashSet};
2
3use naia_serde::{BitReader, BitWrite, SerdeErr};
4
5use crate::{
6    messages::message_kinds::{MessageKind, MessageKinds},
7    named::Named,
8    world::entity::entity_converters::LocalEntityAndGlobalEntityConverterMut,
9    LocalEntityAndGlobalEntityConverter, MessageContainer, RemoteEntity,
10};
11
12/// Factory trait that deserializes a concrete `Message` from raw bits.
13pub trait MessageBuilder: Send + Sync {
14    /// Create new Message from incoming bit stream
15    fn read(
16        &self,
17        reader: &mut BitReader,
18        converter: &dyn LocalEntityAndGlobalEntityConverter,
19    ) -> Result<MessageContainer, SerdeErr>;
20
21    /// Returns a heap-allocated clone of this builder.
22    fn box_clone(&self) -> Box<dyn MessageBuilder>;
23}
24
25/// Core trait for all naia message types — provides serialization, kind lookup, and entity-relation hooks.
26pub trait Message: Send + Sync + Named + MessageClone + Any {
27    /// Gets the MessageKind of this type
28    fn kind(&self) -> MessageKind;
29    /// Converts this boxed message into a `Box<dyn Any>` for downcasting.
30    fn to_boxed_any(self: Box<Self>) -> Box<dyn Any>;
31    /// Creates the `MessageBuilder` used to deserialize instances of this type.
32    fn create_builder() -> Box<dyn MessageBuilder>
33    where
34        Self: Sized;
35    /// Returns the bit length of this message when serialized with `converter`.
36    fn bit_length(
37        &self,
38        message_kinds: &MessageKinds,
39        converter: &mut dyn LocalEntityAndGlobalEntityConverterMut,
40    ) -> u32;
41    /// Returns `true` if this message is a fragment of a larger logical message.
42    fn is_fragment(&self) -> bool;
43    /// Returns `true` if this message envelope carries a request or response payload.
44    fn is_request(&self) -> bool;
45    /// Writes data into an outgoing byte stream
46    fn write(
47        &self,
48        message_kinds: &MessageKinds,
49        writer: &mut dyn BitWrite,
50        converter: &mut dyn LocalEntityAndGlobalEntityConverterMut,
51    );
52    /// Returns a list of RemoteEntities contained within the Message's EntityProperty fields, which have not yet been received.
53    fn relations_waiting(&self) -> Option<HashSet<RemoteEntity>>;
54    /// Converts any LocalEntities contained within the Message's EntityProperty fields to GlobalEntities
55    fn relations_complete(&mut self, converter: &dyn LocalEntityAndGlobalEntityConverter);
56    // /// Returns whether has any EntityRelations
57    // fn has_entity_relations(&self) -> bool;
58    // /// Returns a list of Entities contained within the Message's EntityRelation fields
59    // fn entities(&self) -> Vec<GlobalEntity>;
60}
61
62// Named
63impl Named for Box<dyn Message> {
64    fn name(&self) -> String {
65        self.as_ref().name()
66    }
67
68    fn protocol_name() -> &'static str
69    where
70        Self: Sized,
71    {
72        // This is unreachable since Box<dyn Message> is not Sized
73        unimplemented!("protocol_name() is not available for Box<dyn Message>")
74    }
75}
76
77/// Helper trait enabling `Box<dyn Message>` to be cloned without knowing the concrete type.
78pub trait MessageClone {
79    /// Returns a heap-allocated clone of `self` as a `Box<dyn Message>`.
80    fn clone_box(&self) -> Box<dyn Message>;
81}
82
83impl<T: 'static + Clone + Message> MessageClone for T {
84    fn clone_box(&self) -> Box<dyn Message> {
85        Box::new(self.clone())
86    }
87}
88
89impl Clone for Box<dyn Message> {
90    fn clone(&self) -> Box<dyn Message> {
91        MessageClone::clone_box(self.as_ref())
92    }
93}