lucaspoffo / renet

Server/Client network library for multiplayer games with authentication and connection management made with Rust
Apache License 2.0
663 stars 68 forks source link

Rechannel: split channels into Sender/Receiver channels #23

Closed lucaspoffo closed 2 years ago

lucaspoffo commented 2 years ago

These changes make it possible for the server and the client to have different channels. As an example, the client can now receive messages from 3 unreliable channels and send messages to 2 reliable channels, before the server and the client would need to have all equal channels and with the same configuration (with 3 unreliable channels and 2 reliables) . Now you can have different configurations for the channels you send and channels you receive from.

The configuration stays the same, internally when you create a channel it creates a sender and a receiver channel, but you need to pass 2 channel configurations, one for the senders and one for the receivers.

These changes came from the bad usability when trying to implement the bevy demo, I had channels that the server didn't use and the same thing for the client. Now it server/client has the exactly channels they use and you can give more meaningful names for the channels if you use an enum.

You can check the usuability change for the demo in this commit 6604e20759e7fe0be94fc85420ab5be0aeb4bf30

Before, channels didn't have meaningful names and some were unused:

pub enum Channel {
    Reliable,
    ReliableCritical,
    Unreliable,
}

pub fn channels_config() -> Vec<ChannelConfig> {
    vec![
        ReliableChannelConfig {
            channel_id: Channel::Reliable.id(),
            message_resend_time: Duration::from_millis(200),
            ..Default::default()
        }
        .into(),
        ReliableChannelConfig {
            channel_id: Channel::ReliableCritical.id(),
            message_resend_time: Duration::ZERO,
            ..Default::default()
        }
        .into(),
        UnreliableChannelConfig {
            channel_id: Channel::Unreliable.id(),
            ..Default::default()
        }
        .into(),
    ]
}

Now, you can give more explicit names for the channels and make sure no channel is unused and have different configuration for sending and receiving messages:

pub enum ClientChannel {
    Input,
    Command,
}

pub enum ServerChannel {
    ServerMessages,
    NetworkFrame,
}

impl ClientChannel {
    pub fn channels_config() -> Vec<ChannelConfig> {
        vec![
            ReliableChannelConfig {
                channel_id: Self::Input.id(),
                message_resend_time: Duration::ZERO,
                ..Default::default()
            }
            .into(),
            ReliableChannelConfig {
                channel_id: Self::Command.id(),
                message_resend_time: Duration::ZERO,
                ..Default::default()
            }
            .into(),
        ]
    }
}

impl ServerChannel {
    pub fn channels_config() -> Vec<ChannelConfig> {
        vec![
            UnreliableChannelConfig {
                channel_id: Self::NetworkFrame.id(),
                ..Default::default()
            }
            .into(),
            ReliableChannelConfig {
                channel_id: Self::ServerMessages.id(),
                message_resend_time: Duration::from_millis(200),
                ..Default::default()
            }
            .into(),
        ]
    }
}