naia-server 0.25.0

A server that uses either UDP or WebRTC communication to send/receive messages to/from connected clients, and syncs registered Entities/Components to clients to whom they are in-scope.
use std::collections::HashMap;

use naia_shared::{
    BitReader, ChannelKind, ChannelKinds, ChannelMode, LocalEntityAndGlobalEntityConverter,
    MessageContainer, MessageKinds, Serde, SerdeErr, Tick,
};

use crate::connection::tick_buffer_receiver_channel::TickBufferReceiverChannel;

pub struct TickBufferReceiver {
    channel_receivers: HashMap<ChannelKind, TickBufferReceiverChannel>,
}

impl TickBufferReceiver {
    pub fn new(channel_kinds: &ChannelKinds) -> Self {
        // initialize receivers
        let mut channel_receivers = HashMap::new();
        for (channel_kind, channel_settings) in channel_kinds.channels() {
            if let ChannelMode::TickBuffered(settings) = channel_settings.mode {
                channel_receivers.insert(
                    channel_kind,
                    TickBufferReceiverChannel::new(settings.clone()),
                );
            }
        }

        Self { channel_receivers }
    }

    // Incoming Messages

    /// Read incoming packet data and store in a buffer
    pub fn read_messages(
        &mut self,
        channel_kinds: &ChannelKinds,
        message_kinds: &MessageKinds,
        host_tick: &Tick,
        remote_tick: &Tick,
        converter: &dyn LocalEntityAndGlobalEntityConverter,
        reader: &mut BitReader,
    ) -> Result<(), SerdeErr> {
        loop {
            let channel_continue = bool::de(reader)?;
            if !channel_continue {
                break;
            }

            // read channel index
            let channel_kind = ChannelKind::de(channel_kinds, reader)?;

            // continue read inside channel
            let channel = self.channel_receivers.get_mut(&channel_kind).unwrap();
            channel.read_messages(converter, message_kinds, host_tick, remote_tick, reader)?;
        }

        Ok(())
    }

    /// Directly inject a message into the specified channel's tick buffer (test_utils only)
    #[cfg(feature = "test_utils")]
    pub fn inject_message(
        &mut self,
        channel_kind: &ChannelKind,
        host_tick: &Tick,
        message_tick: &Tick,
        message: MessageContainer,
    ) -> bool {
        if let Some(channel) = self.channel_receivers.get_mut(channel_kind) {
            channel.inject_message(host_tick, message_tick, message)
        } else {
            false
        }
    }

    /// Retrieved stored data from the tick buffer for the given [`Tick`]
    pub fn receive_messages(
        &mut self,
        host_tick: &Tick,
    ) -> Vec<(ChannelKind, Vec<MessageContainer>)> {
        let mut output = Vec::new();
        for (channel_kind, channel) in &mut self.channel_receivers {
            let messages = channel.receive_messages(host_tick);
            output.push((*channel_kind, messages));
        }
        output
    }
}