#multiplayer-game #networking #connection #bevy-plugin #game-networking #gamedev #renet

bevy_renet

Bevy plugin for the renet crate: Server/Client network library for multiplayer games with authentication and connection management

12 releases

0.0.12 Jul 20, 2024
0.0.11 Feb 21, 2024
0.0.10 Nov 12, 2023
0.0.9 Jul 20, 2023
0.0.4 Jul 25, 2022

#1158 in Network programming

Download history 389/week @ 2024-07-18 246/week @ 2024-07-25 218/week @ 2024-08-01 266/week @ 2024-08-08 288/week @ 2024-08-15 153/week @ 2024-08-22 255/week @ 2024-08-29 225/week @ 2024-09-05 228/week @ 2024-09-12 261/week @ 2024-09-19 298/week @ 2024-09-26 194/week @ 2024-10-03 195/week @ 2024-10-10 231/week @ 2024-10-17 189/week @ 2024-10-24 164/week @ 2024-10-31

793 downloads per month
Used in 6 crates (5 directly)

MIT/Apache

160KB
2.5K SLoC

Bevy Renet

Latest version Documentation MIT Apache

A Bevy Plugin for the renet crate. A network crate for Server/Client with cryptographically secure authentication and encypted packets. Designed for fast paced competitive multiplayer games.

Usage

Bevy renet is a small layer over the renet crate, it adds systems to call the update function from the client/server. RenetClient, RenetServer, NetcodeClientTransport and NetcodeServerTransport need to be added as a resource, so the setup is similar to renet itself:

Server

let mut app = App::new();
app.add_plugin(RenetServerPlugin);

let server = RenetServer::new(ConnectionConfig::default());
app.insert_resource(server);

// Transport layer setup
app.add_plugin(NetcodeServerPlugin);
let server_addr = "127.0.0.1:5000".parse().unwrap();
let socket = UdpSocket::bind(server_addr).unwrap();
let server_config = ServerConfig {
    current_time: SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(),
    max_clients: 64, 
    protocol_id: 0,
    public_addresses: vec![server_addr], 
    authentication: ServerAuthentication::Unsecure
};
let transport = NetcodeServerTransport::new(server_config, socket).unwrap();
app.insert_resource(transport);

app.add_system(send_message_system);
app.add_system(receive_message_system);
app.add_system(handle_events_system);

// Systems

fn send_message_system(mut server: ResMut<RenetServer>) {
    let channel_id = 0;
    // Send a text message for all clients
    // The enum DefaultChannel describe the channels used by the default configuration
    server.broadcast_message(DefaultChannel::ReliableOrdered, "server message");
}

fn receive_message_system(mut server: ResMut<RenetServer>) {
    // Receive message from all clients
    for client_id in server.clients_id() {
        while let Some(message) = server.receive_message(client_id, DefaultChannel::ReliableOrdered) {
            // Handle received message
        }
    }
}

fn handle_events_system(mut server_events: EventReader<ServerEvent>) {
    for event in server_events.read() {
        match event {
            ServerEvent::ClientConnected { client_id } => {
                println!("Client {client_id} connected");
            }
            ServerEvent::ClientDisconnected { client_id, reason } => {
                println!("Client {client_id} disconnected: {reason}");
            }
        }
    }
}

Client

let mut app = App::new();
app.add_plugin(RenetClientPlugin);

let client = RenetClient::new(ConnectionConfig::default());
app.insert_resource(client);

// Setup the transport layer
app.add_plugin(NetcodeClientPlugin);

let authentication = ClientAuthentication::Unsecure {
    server_addr: SERVER_ADDR,
    client_id: 0,
    user_data: None,
    protocol_id: 0,
};
let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let mut transport = NetcodeClientTransport::new(current_time, authentication, socket).unwrap();

app.insert_resource(transport);

app.add_system(send_message_system);
app.add_system(receive_message_system);

// Systems

fn send_message_system(mut client: ResMut<RenetClient>) {
    // Send a text message to the server
    client.send_message(DefaultChannel::ReliableOrdered, "server message");
}

fn receive_message_system(mut client: ResMut<RenetClient>) {
    while let Some(message) = client.receive_message(DefaultChannel::ReliableOrdered) {
        // Handle received message
    }
}

Example

You can run the simple example with:

  • Server: cargo run --features="serde transport" --example simple -- server
  • Client: cargo run --features="serde transport" --example simple -- client

If you want a more complex example you can checkout the demo_bevy sample:

Bevy Demo.webm

Bevy Compatibility

bevy bevy_renet
0.14 0.0.12
0.13 0.0.11
0.12 0.0.10
0.11 0.0.9
0.10 0.0.8
0.9 0.0.6
0.8 0.0.5
0.7 0.0.4

Dependencies

~25MB
~462K SLoC