Bevy Renet

A Bevy Plugin for the renet crate.
A network crate for Server/Client with cryptographically secure authentication and encrypted 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
fn main() {
let mut app = App::new();
app.add_plugin(RenetServerPlugin);
let server = RenetServer::new(ConnectionConfig::default());
app.insert_resource(server);
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);
}
fn send_message_system(mut server: ResMut<RenetServer>) {
let channel_id = 0;
server.broadcast_message(DefaultChannel::ReliableOrdered, "server message");
}
fn receive_message_system(mut server: ResMut<RenetServer>) {
for client_id in server.clients_id() {
while let Some(message) = server.receive_message(client_id, DefaultChannel::ReliableOrdered) {
}
}
}
fn handle_events_system(mut server_events: MessageReader<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
fn main() {
let mut app = App::new();
app.add_plugin(RenetClientPlugin);
let client = RenetClient::new(ConnectionConfig::default());
app.insert_resource(client);
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);
}
fn send_message_system(mut client: ResMut<RenetClient>) {
client.send_message(DefaultChannel::ReliableOrdered, "server message");
}
fn receive_message_system(mut client: ResMut<RenetClient>) {
while let Some(message) = client.receive_message(DefaultChannel::ReliableOrdered) {
}
}
Example
You can run the simple example with:
- Server:
cargo run --features="netcode" --example simple -- server
- Client:
cargo run --features="netcode" --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.17 |
3.0 |
| 0.16 |
2.0 |
| 0.15 |
1.0 |
| 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 |
Steam
By default bevy_renet uses renet_netcode as the transport layer, but you can also use the steam transport layer if you wish by enabling the steam feature.
This adds the transport structs SteamServerTransport, SteamClientTransport and the bevy plugins SteamServerPlugin, SteamClientPlugin, the setup should be similar to default transport layer.
You can check the Bevy Demo for how to use the default and steam transport switching between them using feature flags.
Custom Schedules
If you want more control over how renet is run, instead of adding the RenetServerPlugin, RenetClientPlugin, you can manually setup the functions they implement (they are all public). Make sure to also setup the plugins for the desired Transport layer.