Skip to content

Commit

Permalink
DemoBevy: use sequenced unreliable channel for syncing entities
Browse files Browse the repository at this point in the history
Now we don't need to use the a tick for discarding old frames, we can use the sequenced option in the unreliable channel.
  • Loading branch information
lucaspoffo committed Oct 22, 2022
1 parent 30411c9 commit 1edd0f9
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 80 deletions.
32 changes: 10 additions & 22 deletions demo_bevy/src/bin/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use bevy_renet::{
run_if_client_connected, RenetClientPlugin,
};
use demo_bevy::{
client_connection_config, setup_level, ClientChannel, NetworkFrame, PlayerCommand, PlayerInput, Ray3d, ServerChannel, ServerMessages,
PROTOCOL_ID,
client_connection_config, setup_level, ClientChannel, NetworkedEntities, PlayerCommand, PlayerInput, Ray3d, ServerChannel,
ServerMessages, PROTOCOL_ID,
};
use renet_visualizer::{RenetClientVisualizer, RenetVisualizerStyle};
use smooth_bevy_cameras::{LookTransform, LookTransformBundle, LookTransformPlugin, Smoother};
Expand All @@ -33,9 +33,6 @@ struct ClientLobby {
players: HashMap<u64, PlayerInfo>,
}

#[derive(Debug)]
struct MostRecentTick(Option<u32>);

fn new_renet_client() -> RenetClient {
let server_addr = "127.0.0.1:5000".parse().unwrap();
let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
Expand Down Expand Up @@ -65,7 +62,6 @@ fn main() {

app.insert_resource(ClientLobby::default());
app.insert_resource(PlayerInput::default());
app.insert_resource(MostRecentTick(None));
app.insert_resource(new_renet_client());
app.insert_resource(NetworkMapping::default());

Expand Down Expand Up @@ -116,13 +112,11 @@ fn player_input(
mouse_button_input: Res<Input<MouseButton>>,
target_query: Query<&Transform, With<Target>>,
mut player_commands: EventWriter<PlayerCommand>,
most_recent_tick: Res<MostRecentTick>,
) {
player_input.left = keyboard_input.pressed(KeyCode::A) || keyboard_input.pressed(KeyCode::Left);
player_input.right = keyboard_input.pressed(KeyCode::D) || keyboard_input.pressed(KeyCode::Right);
player_input.up = keyboard_input.pressed(KeyCode::W) || keyboard_input.pressed(KeyCode::Up);
player_input.down = keyboard_input.pressed(KeyCode::S) || keyboard_input.pressed(KeyCode::Down);
player_input.most_recent_tick = most_recent_tick.0;

if mouse_button_input.just_pressed(MouseButton::Left) {
let target_transform = target_query.single();
Expand All @@ -135,13 +129,13 @@ fn player_input(
fn client_send_input(player_input: Res<PlayerInput>, mut client: ResMut<RenetClient>) {
let input_message = bincode::serialize(&*player_input).unwrap();

client.send_message(ClientChannel::Input.id(), input_message);
client.send_message(ClientChannel::Input, input_message);
}

fn client_send_player_commands(mut player_commands: EventReader<PlayerCommand>, mut client: ResMut<RenetClient>) {
for command in player_commands.iter() {
let command_message = bincode::serialize(command).unwrap();
client.send_message(ClientChannel::Command.id(), command_message);
client.send_message(ClientChannel::Command, command_message);
}
}

Expand All @@ -152,10 +146,9 @@ fn client_sync_players(
mut client: ResMut<RenetClient>,
mut lobby: ResMut<ClientLobby>,
mut network_mapping: ResMut<NetworkMapping>,
mut most_recent_tick: ResMut<MostRecentTick>,
) {
let client_id = client.client_id();
while let Some(message) = client.receive_message(ServerChannel::ServerMessages.id()) {
while let Some(message) = client.receive_message(ServerChannel::ServerMessages) {
let server_message = bincode::deserialize(&message).unwrap();
match server_message {
ServerMessages::PlayerCreate { id, translation, entity } => {
Expand Down Expand Up @@ -209,17 +202,12 @@ fn client_sync_players(
}
}

while let Some(message) = client.receive_message(ServerChannel::NetworkFrame.id()) {
let frame: NetworkFrame = bincode::deserialize(&message).unwrap();
match most_recent_tick.0 {
None => most_recent_tick.0 = Some(frame.tick),
Some(tick) if tick < frame.tick => most_recent_tick.0 = Some(frame.tick),
_ => continue,
}
while let Some(message) = client.receive_message(ServerChannel::NetworkedEntities) {
let networked_entities: NetworkedEntities = bincode::deserialize(&message).unwrap();

for i in 0..frame.entities.entities.len() {
if let Some(entity) = network_mapping.0.get(&frame.entities.entities[i]) {
let translation = frame.entities.translations[i].into();
for i in 0..networked_entities.entities.len() {
if let Some(entity) = network_mapping.0.get(&networked_entities.entities[i]) {
let translation = networked_entities.translations[i].into();
let transform = Transform {
translation,
..Default::default()
Expand Down
50 changes: 16 additions & 34 deletions demo_bevy/src/bin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use bevy_renet::{
RenetServerPlugin,
};
use demo_bevy::{
server_connection_config, setup_level, spawn_fireball, ClientChannel, NetworkFrame, Player, PlayerCommand, PlayerInput, Projectile,
ServerChannel, ServerMessages, PROTOCOL_ID,
server_connection_config, setup_level, spawn_fireball, ClientChannel, NetworkedEntities, Player, PlayerCommand, PlayerInput,
Projectile, ServerChannel, ServerMessages, PROTOCOL_ID,
};
use renet_visualizer::RenetServerVisualizer;

Expand All @@ -21,13 +21,6 @@ pub struct ServerLobby {
pub players: HashMap<u64, Entity>,
}

#[derive(Debug, Default)]
struct NetworkTick(u32);

// Clients last received ticks
#[derive(Debug, Default)]
struct ClientTicks(HashMap<u64, Option<u32>>);

const PLAYER_MOVE_SPEED: f32 = 5.0;

fn new_renet_server() -> RenetServer {
Expand All @@ -51,8 +44,6 @@ fn main() {
app.add_plugin(EguiPlugin);

app.insert_resource(ServerLobby::default());
app.insert_resource(NetworkTick(0));
app.insert_resource(ClientTicks::default());
app.insert_resource(new_renet_server());
app.insert_resource(RenetServerVisualizer::<200>::default());

Expand All @@ -79,7 +70,6 @@ fn server_update_system(
mut lobby: ResMut<ServerLobby>,
mut server: ResMut<RenetServer>,
mut visualizer: ResMut<RenetServerVisualizer<200>>,
mut client_ticks: ResMut<ClientTicks>,
players: Query<(Entity, &Player, &Transform)>,
) {
for event in server_events.iter() {
Expand All @@ -97,7 +87,7 @@ fn server_update_system(
translation,
})
.unwrap();
server.send_message(*id, ServerChannel::ServerMessages.id(), message);
server.send_message(*id, ServerChannel::ServerMessages, message);
}

// Spawn new player
Expand Down Expand Up @@ -126,24 +116,23 @@ fn server_update_system(
translation,
})
.unwrap();
server.broadcast_message(ServerChannel::ServerMessages.id(), message);
server.broadcast_message(ServerChannel::ServerMessages, message);
}
ServerEvent::ClientDisconnected(id) => {
println!("Player {} disconnected.", id);
visualizer.remove_client(*id);
client_ticks.0.remove(id);
if let Some(player_entity) = lobby.players.remove(id) {
commands.entity(player_entity).despawn();
}

let message = bincode::serialize(&ServerMessages::PlayerRemove { id: *id }).unwrap();
server.broadcast_message(ServerChannel::ServerMessages.id(), message);
server.broadcast_message(ServerChannel::ServerMessages, message);
}
}
}

for client_id in server.clients_id().into_iter() {
while let Some(message) = server.receive_message(client_id, ClientChannel::Command.id()) {
while let Some(message) = server.receive_message(client_id, ClientChannel::Command) {
let command: PlayerCommand = bincode::deserialize(&message).unwrap();
match command {
PlayerCommand::BasicAttack { mut cast_at } => {
Expand All @@ -163,15 +152,14 @@ fn server_update_system(
translation: translation.into(),
};
let message = bincode::serialize(&message).unwrap();
server.broadcast_message(ServerChannel::ServerMessages.id(), message);
server.broadcast_message(ServerChannel::ServerMessages, message);
}
}
}
}
}
while let Some(message) = server.receive_message(client_id, ClientChannel::Input.id()) {
while let Some(message) = server.receive_message(client_id, ClientChannel::Input) {
let input: PlayerInput = bincode::deserialize(&message).unwrap();
client_ticks.0.insert(client_id, input.most_recent_tick);
if let Some(player_entity) = lobby.players.get(&client_id) {
commands.entity(*player_entity).insert(input);
}
Expand All @@ -198,21 +186,15 @@ fn update_visulizer_system(
}

#[allow(clippy::type_complexity)]
fn server_network_sync(
mut tick: ResMut<NetworkTick>,
mut server: ResMut<RenetServer>,
networked_entities: Query<(Entity, &Transform), Or<(With<Player>, With<Projectile>)>>,
) {
let mut frame = NetworkFrame::default();
for (entity, transform) in networked_entities.iter() {
frame.entities.entities.push(entity);
frame.entities.translations.push(transform.translation.into());
fn server_network_sync(mut server: ResMut<RenetServer>, query: Query<(Entity, &Transform), Or<(With<Player>, With<Projectile>)>>) {
let mut networked_entities = NetworkedEntities::default();
for (entity, transform) in query.iter() {
networked_entities.entities.push(entity);
networked_entities.translations.push(transform.translation.into());
}

frame.tick = tick.0;
tick.0 += 1;
let sync_message = bincode::serialize(&frame).unwrap();
server.broadcast_message(ServerChannel::NetworkFrame.id(), sync_message);
let sync_message = bincode::serialize(&networked_entities).unwrap();
server.broadcast_message(ServerChannel::NetworkedEntities, sync_message);
}

fn move_players_system(mut query: Query<(&mut Velocity, &PlayerInput)>) {
Expand Down Expand Up @@ -255,6 +237,6 @@ fn projectile_on_removal_system(mut server: ResMut<RenetServer>, removed_project
let message = ServerMessages::DespawnProjectile { entity };
let message = bincode::serialize(&message).unwrap();

server.broadcast_message(ServerChannel::ServerMessages.id(), message);
server.broadcast_message(ServerChannel::ServerMessages, message);
}
}
42 changes: 20 additions & 22 deletions demo_bevy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ pub struct Player {

#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, Component)]
pub struct PlayerInput {
pub most_recent_tick: Option<u32>,
pub up: bool,
pub down: bool,
pub left: bool,
Expand All @@ -34,7 +33,7 @@ pub enum ClientChannel {

pub enum ServerChannel {
ServerMessages,
NetworkFrame,
NetworkedEntities,
}

#[derive(Debug, Serialize, Deserialize, Component)]
Expand All @@ -51,30 +50,26 @@ pub struct NetworkedEntities {
pub translations: Vec<[f32; 3]>,
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct NetworkFrame {
pub tick: u32,
pub entities: NetworkedEntities,
}

impl ClientChannel {
pub fn id(&self) -> u8 {
match self {
Self::Input => 0,
Self::Command => 1,
impl From<ClientChannel> for u8 {
fn from(channel_id: ClientChannel) -> Self {
match channel_id {
ClientChannel::Command => 0,
ClientChannel::Input => 1,
}
}
}

impl ClientChannel {
pub fn channels_config() -> Vec<ChannelConfig> {
vec![
ReliableChannelConfig {
channel_id: Self::Input.id(),
channel_id: Self::Input.into(),
message_resend_time: Duration::ZERO,
..Default::default()
}
.into(),
ReliableChannelConfig {
channel_id: Self::Command.id(),
channel_id: Self::Command.into(),
message_resend_time: Duration::ZERO,
..Default::default()
}
Expand All @@ -83,23 +78,26 @@ impl ClientChannel {
}
}

impl ServerChannel {
pub fn id(&self) -> u8 {
match self {
Self::NetworkFrame => 0,
Self::ServerMessages => 1,
impl From<ServerChannel> for u8 {
fn from(channel_id: ServerChannel) -> Self {
match channel_id {
ServerChannel::NetworkedEntities => 0,
ServerChannel::ServerMessages => 1,
}
}
}

impl ServerChannel {
pub fn channels_config() -> Vec<ChannelConfig> {
vec![
UnreliableChannelConfig {
channel_id: Self::NetworkFrame.id(),
channel_id: Self::NetworkedEntities.into(),
sequenced: true, // We don't care about old positions
..Default::default()
}
.into(),
ReliableChannelConfig {
channel_id: Self::ServerMessages.id(),
channel_id: Self::ServerMessages.into(),
message_resend_time: Duration::from_millis(200),
..Default::default()
}
Expand Down
2 changes: 1 addition & 1 deletion rechannel/src/channel/unreliable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ mod tests {

// Send first message
let first_message = Bytes::from(vec![0]);
send_channel.send_message(first_message.clone(), current_time);
send_channel.send_message(first_message, current_time);
let first_channel_data = send_channel.get_messages_to_send(u64::MAX, sequence, current_time).unwrap();
assert_eq!(first_channel_data.messages.len(), 1);

Expand Down
2 changes: 1 addition & 1 deletion renet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod error;
mod network_info;
mod server;

pub use rechannel::channel::{ChunkChannelConfig, ChannelConfig, DefaultChannel, ReliableChannelConfig, UnreliableChannelConfig};
pub use rechannel::channel::{ChannelConfig, ChunkChannelConfig, DefaultChannel, ReliableChannelConfig, UnreliableChannelConfig};
pub use rechannel::error::{ChannelError, DisconnectionReason, RechannelError};

pub use renetcode::{generate_random_bytes, ConnectToken, NetcodeError};
Expand Down

0 comments on commit 1edd0f9

Please sign in to comment.