bevy_client_server_events/
server.rs

1use bevy::prelude::{Commands, Event, EventReader, EventWriter, Res, ResMut};
2use bevy_renet::renet::{
3    transport::{ServerAuthentication, ServerConfig},
4    ClientId, ConnectionConfig, RenetServer,
5};
6use renet::{transport::NetcodeServerTransport, DisconnectReason, ServerEvent};
7use serde::{de::DeserializeOwned, Serialize};
8
9use std::net::UdpSocket;
10use std::time::SystemTime;
11
12use crate::NetworkConfigs;
13
14#[derive(Debug, Event)]
15pub struct StartServer {
16    pub ip: String,
17    pub port: u16,
18    pub max_clients: usize,
19    pub protocol_id: u64,
20    pub available_bytes_per_tick: u64,
21    pub private_key: Option<[u8; 32]>,
22}
23
24impl Default for StartServer {
25    fn default() -> Self {
26        Self {
27            ip: "127.0.0.1".to_string(),
28            port: 5000,
29            max_clients: 64,
30            protocol_id: 1,
31            available_bytes_per_tick: 60_000,
32            private_key: None,
33        }
34    }
35}
36
37impl StartServer {
38    fn get_server_and_transport(
39        &self,
40        channel_configs: NetworkConfigs,
41    ) -> (RenetServer, NetcodeServerTransport) {
42        let server = RenetServer::new(ConnectionConfig {
43            available_bytes_per_tick: self.available_bytes_per_tick,
44            server_channels_config: channel_configs.clone().into(),
45            client_channels_config: channel_configs.into(),
46        });
47        let public_addr = format!("{}:{}", self.ip, self.port).parse().unwrap();
48        let socket = UdpSocket::bind(public_addr).unwrap();
49        let current_time = SystemTime::now()
50            .duration_since(SystemTime::UNIX_EPOCH)
51            .unwrap();
52        let authentication = if let Some(private_key) = self.private_key {
53            ServerAuthentication::Secure { private_key }
54        } else {
55            ServerAuthentication::Unsecure
56        };
57        let server_config = ServerConfig {
58            current_time,
59            max_clients: self.max_clients,
60            protocol_id: self.protocol_id,
61            public_addresses: vec![public_addr],
62            authentication,
63        };
64
65        let transport = NetcodeServerTransport::new(server_config, socket).unwrap();
66        (server, transport)
67    }
68}
69
70#[derive(Debug, Event)]
71pub struct StopServer;
72
73#[derive(Debug, Event)]
74pub struct ClientConnected {
75    pub client_id: u64,
76}
77
78#[derive(Debug, Event)]
79pub struct ClientDisconnected {
80    pub client_id: u64,
81    pub reason: DisconnectReason,
82}
83
84#[derive(Debug, Event)]
85pub struct ReceiveFromClient<T: Event + Serialize + DeserializeOwned> {
86    pub client_id: u64,
87    pub content: T,
88}
89
90#[derive(Debug, Event)]
91pub struct SendToClient<T: Event + Serialize + DeserializeOwned> {
92    pub client_id: u64,
93    pub content: T,
94}
95
96#[derive(Debug, Event)]
97pub struct SendToClients<T: Event + Serialize + DeserializeOwned> {
98    pub content: T,
99}
100
101pub fn server_starts(
102    mut start_server_events: EventReader<StartServer>,
103    channel_configs: Res<NetworkConfigs>,
104    mut commands: Commands,
105) {
106    for start_server in start_server_events.read() {
107        let (server, transport) = start_server.get_server_and_transport(channel_configs.clone());
108        commands.insert_resource(server);
109        commands.insert_resource(transport);
110    }
111}
112
113pub fn server_stops(
114    mut stop_server_events: EventReader<StopServer>,
115    mut server: ResMut<RenetServer>,
116    mut transport: ResMut<NetcodeServerTransport>,
117    mut commands: Commands,
118) {
119    for _ in stop_server_events.read() {
120        server.disconnect_all();
121        transport.disconnect_all(&mut server);
122        commands.remove_resource::<RenetServer>();
123        // bevy_renet crashes due to missing resource if we remove the transport on this tick.
124        // Removing it on the next tick instead (see cleanup_transport).
125        //commands.remove_resource::<NetcodeServerTransport>();
126    }
127}
128
129pub fn server_tracks_connected_and_disconnected_clients(
130    mut server_events: EventReader<ServerEvent>,
131    mut client_connected_events: EventWriter<ClientConnected>,
132    mut client_disconnected_events: EventWriter<ClientDisconnected>,
133) {
134    for server_event in server_events.read() {
135        match server_event {
136            ServerEvent::ClientConnected { client_id } => {
137                client_connected_events.send(ClientConnected {
138                    client_id: client_id.raw(),
139                });
140            },
141            ServerEvent::ClientDisconnected { client_id, reason } => {
142                client_disconnected_events.send(ClientDisconnected {
143                    client_id: client_id.raw(),
144                    reason: *reason,
145                });
146            },
147        }
148    }
149}
150
151pub fn server_receives_messages_from_clients<
152    const I: u8,
153    T: Event + Serialize + DeserializeOwned,
154>(
155    mut server: ResMut<RenetServer>,
156    mut client_message_events: EventWriter<ReceiveFromClient<T>>,
157) {
158    for client_id in server.clients_id().into_iter() {
159        while let Some(message) = server.receive_message(client_id, I) {
160            let (content, _): (T, usize) =
161                bincode::serde::decode_from_slice(&message, bincode::config::standard()).unwrap();
162            client_message_events.send(ReceiveFromClient {
163                client_id: client_id.raw(),
164                content,
165            });
166        }
167    }
168}
169
170pub fn server_sends_messages_to_clients<const I: u8, T: Event + Serialize + DeserializeOwned>(
171    mut server: ResMut<RenetServer>,
172    mut send_message_to_client_events: EventReader<SendToClient<T>>,
173) {
174    for message in send_message_to_client_events.read() {
175        let payload =
176            bincode::serde::encode_to_vec(&message.content, bincode::config::standard()).unwrap();
177        server.send_message(ClientId::from_raw(message.client_id), I, payload);
178    }
179}
180
181pub fn server_broadcasts_messages_to_clients<
182    const I: u8,
183    T: Event + Serialize + DeserializeOwned,
184>(
185    mut server: ResMut<RenetServer>,
186    mut broadcast_message_events: EventReader<SendToClients<T>>,
187) {
188    for message in broadcast_message_events.read() {
189        let payload =
190            bincode::serde::encode_to_vec(&message.content, bincode::config::standard()).unwrap();
191        server.broadcast_message(I, payload);
192    }
193}
194
195pub fn cleanup_transport(mut commands: Commands) {
196    commands.remove_resource::<renet::transport::NetcodeServerTransport>();
197}