Skip to content

Commit

Permalink
initial sync only on new sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
raffaeleragni committed Jun 23, 2024
1 parent 10eaf5d commit 439516a
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 16 deletions.
17 changes: 15 additions & 2 deletions src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bevy_renet::renet::{
};

use crate::{
lib_priv::{sync_material_enabled, sync_mesh_enabled, SyncTrackerRes},
lib_priv::{sync_material_enabled, sync_mesh_enabled, PromotionState, SyncTrackerRes},
proto::Message,
ClientState,
};
Expand Down Expand Up @@ -73,9 +73,22 @@ fn client_connecting(mut client_state: ResMut<NextState<ClientState>>) {
client_state.set(ClientState::Connecting);
}

fn client_connected(mut client_state: ResMut<NextState<ClientState>>, mut cmd: Commands) {
fn client_connected(
mut client_state: ResMut<NextState<ClientState>>,
mut cmd: Commands,
mut client: ResMut<RenetClient>,
promotion_state: Res<State<PromotionState>>,
) {
info!("Connected to server.");
client_state.set(ClientState::Connected);
if promotion_state.eq(&PromotionState::NeverPromoted) {
// this connection is a new session and requires the initial information
// from initial sync
client.send_message(
DefaultChannel::ReliableOrdered,
bincode::serialize(&Message::RequestInitialSync {}).unwrap(),
)
}
// remove any previous pending server since the instance is a client now
// this servers can be pending after a host promotion
cmd.remove_resource::<NetcodeServerTransport>();
Expand Down
12 changes: 11 additions & 1 deletion src/client/receiver.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
lib_priv::PromotedToServer,
lib_priv::{PromotedToServer, PromotionState},
logging::{log_message_received, Who},
networking::{assets::SyncAssetTransfer, create_client, create_server},
proto::SyncAssetType,
Expand All @@ -15,6 +15,7 @@ pub(crate) fn poll_for_messages(
mut sync_assets: ResMut<SyncAssetTransfer>,
mut client: ResMut<RenetClient>,
mut send_promoted_event: EventWriter<PromotedToServer>,
mut promotion_state: ResMut<NextState<PromotionState>>,
) {
while let Some(message) = client.receive_message(DefaultChannel::ReliableOrdered) {
let deser_message = bincode::deserialize(&message).unwrap();
Expand All @@ -26,10 +27,12 @@ pub(crate) fn poll_for_messages(
&mut sync_assets,
&mut commands,
&mut send_promoted_event,
&mut promotion_state,
);
}
}

#[allow(clippy::too_many_arguments)]
fn client_received_a_message(
msg: Message,
connection_parameters: &Res<SyncConnectionParameters>,
Expand All @@ -38,6 +41,7 @@ fn client_received_a_message(
sync_assets: &mut ResMut<SyncAssetTransfer>,
cmd: &mut Commands,
send_promoted_event: &mut EventWriter<PromotedToServer>,
promotion_state: &mut ResMut<NextState<PromotionState>>,
) {
log_message_received(Who::Client, &msg);
match msg {
Expand Down Expand Up @@ -120,6 +124,7 @@ fn client_received_a_message(
world.insert_resource(create_server(ip, port));
});
send_promoted_event.send(PromotedToServer {});
promotion_state.set(PromotionState::PromotedToServer);
}
Message::NewHost {
ip,
Expand All @@ -131,6 +136,11 @@ fn client_received_a_message(
client.disconnect();
cmd.remove_resource::<NetcodeClientTransport>();
cmd.insert_resource(create_client(ip, port));
// even if it was a client before, this connection is not a new session
// and won't need the initial_sync, so it's consider a client to client promotion
promotion_state.set(PromotionState::PromotedToClient);
}
// Nothing to do, only servers send initial sync
Message::RequestInitialSync => {}
}
}
9 changes: 9 additions & 0 deletions src/lib_priv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ pub(crate) struct PromotedToServer;
#[derive(Event)]
pub(crate) struct PromotedToClient;

#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, States)]
pub(crate) enum PromotionState {
#[default]
NeverPromoted,
PromotedToServer,
PromotedToClient,
}

#[derive(Resource, Default)]
pub(crate) struct SyncTrackerRes {
/// Mapping of entity ids between server and clients. key: server, value: client
Expand Down Expand Up @@ -237,6 +245,7 @@ impl Plugin for SyncPlugin {
app.add_plugins(BundleFixPlugin);
app.add_plugins(ServerSyncPlugin);
app.add_plugins(ClientSyncPlugin);
app.init_state::<PromotionState>();
app.init_state::<ServerState>();
app.init_state::<ClientState>();
app.add_event::<PromotedToServer>();
Expand Down
1 change: 1 addition & 0 deletions src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,6 @@ pub(crate) fn log_message_received(from: Who, message: &Message) {
} => debug!(
"{:?} received NewHost {{ ip: {} }} {{ port: {} }} {{ web_port: {} }} {{ max_transfer: {} }}",
from, ip, port, web_port, max_transfer),
Message::RequestInitialSync => debug!("Reveived a request for initial sync")
}
}
1 change: 1 addition & 0 deletions src/proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub(crate) enum Message {
web_port: u16,
max_transfer: usize,
},
RequestInitialSync,
}

#[derive(Event)]
Expand Down
1 change: 0 additions & 1 deletion src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ fn client_connected(mut cmd: Commands, mut server_events: EventReader<ServerEven
ServerEvent::ClientConnected { client_id } => {
let client_id = *client_id;
info!("Client connected with client id: {}", client_id);
cmd.add(move |world: &mut World| send_initial_sync(client_id, world));
// remove any previous pending client since the instance is a server now
// this clients can be pending after a host promotion
cmd.remove_resource::<NetcodeClientTransport>();
Expand Down
18 changes: 16 additions & 2 deletions src/server/receiver.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bevy_renet::renet::ClientId;

use crate::{
lib_priv::PromotedToClient,
lib_priv::{PromotedToClient, PromotionState},
logging::{log_message_received, Who},
networking::{assets::SyncAssetTransfer, create_client},
proto::SyncAssetType,
Expand All @@ -16,6 +16,8 @@ pub(crate) fn poll_for_messages(
mut track: ResMut<SyncTrackerRes>,
mut sync_assets: ResMut<SyncAssetTransfer>,
mut send_promoted_event: EventWriter<PromotedToClient>,
promotion_state: Res<State<PromotionState>>,
mut next_promotion_state: ResMut<NextState<PromotionState>>,
) {
for client_id in server.clients_id().into_iter() {
while let Some(message) = server.receive_message(client_id, DefaultChannel::ReliableOrdered)
Expand All @@ -29,11 +31,14 @@ pub(crate) fn poll_for_messages(
&mut sync_assets,
&mut commands,
&mut send_promoted_event,
&promotion_state,
&mut next_promotion_state,
);
}
}
}

#[allow(clippy::too_many_arguments)]
fn server_received_a_message(
client_id: ClientId,
msg: Message,
Expand All @@ -42,6 +47,8 @@ fn server_received_a_message(
sync_assets: &mut ResMut<SyncAssetTransfer>,
cmd: &mut Commands,
send_promoted_event: &mut EventWriter<PromotedToClient>,
promotion_state: &Res<State<PromotionState>>,
next_promotion_state: &mut ResMut<NextState<PromotionState>>,
) {
log_message_received(Who::Server, &msg);
match msg {
Expand Down Expand Up @@ -145,7 +152,7 @@ fn server_received_a_message(
);
})
}
// server is already host
// server is already host, no operation to do
Message::PromoteToHost => (),
Message::NewHost {
ip,
Expand All @@ -171,6 +178,13 @@ fn server_received_a_message(
world.insert_resource(create_client(ip, port));
});
send_promoted_event.send(PromotedToClient {});
next_promotion_state.set(PromotionState::PromotedToClient);
}
Message::RequestInitialSync => {
if promotion_state.eq(&PromotionState::NeverPromoted) {
debug!("Sending initial sync to client id: {}", client_id);
cmd.add(move |world: &mut World| send_initial_sync(client_id, world));
}
}
}
}
Expand Down
3 changes: 0 additions & 3 deletions tests/host_promotion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ mod setup;

#[test]
#[serial]
#[ignore = "host promotion is not complete"]
fn test_host_promotion_with_one_client() {
TestRun::default().run(
2,
Expand All @@ -35,8 +34,6 @@ fn test_host_promotion_with_one_client() {
.value = 7;
},
|env, _, _| {
// todo fix: make the entity id server<>client more agnostic and compatible towards
// host switch
let comp = get_first_entity_component::<MySynched>(&mut env.clients[0]).unwrap();
assert_eq!(comp.value, 7);
let comp = get_first_entity_component::<MySynched>(&mut env.clients[1]).unwrap();
Expand Down
9 changes: 2 additions & 7 deletions tests/setup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@ use std::{
};

use bevy::{
pbr::PbrPlugin,
prelude::*,
reflect::{DynamicTypePath, FromReflect, GetTypeRegistration, Reflect},
render::{mesh::Indices, render_asset::RenderAssetUsages, render_resource::PrimitiveTopology},
transform::TransformBundle,
utils::Uuid,
MinimalPlugins,
log::{Level, LogPlugin}, pbr::PbrPlugin, prelude::*, reflect::{DynamicTypePath, FromReflect, GetTypeRegistration, Reflect}, render::{mesh::Indices, render_asset::RenderAssetUsages, render_resource::PrimitiveTopology}, transform::TransformBundle, utils::Uuid, MinimalPlugins
};
use bevy_renet::renet::RenetClient;
use bevy_sync::{ClientPlugin, ServerPlugin, SyncComponent, SyncPlugin};
Expand Down Expand Up @@ -158,6 +152,7 @@ fn add_plugins(app: &mut App) {
app.init_asset::<Mesh>();
app.init_asset::<Image>();
app.add_plugins(PbrPlugin::default());
app.add_plugins(LogPlugin{level:Level::DEBUG,..default()});

app.add_plugins(SyncPlugin);
}
Expand Down

0 comments on commit 439516a

Please sign in to comment.