Skip to content

Initialize channels in App::finish instead of Startup #488

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Rename `replication_registry::despawn_recursive` into `replication_registry::despawn`.
- `ReplicationRule` now stores `Vec<ComponentRule>` instead of `Vec<(ComponentId, FnsId)>`
- `RuleFns` now available from prelude.
- Initialize channels in `App::finish` instead of `Startup`. It's called automatically on `App::run`, but in tests you need to call `App::finish` manually.
- Rules created with the same priority now evaluated in their creation order.
- Component removals and insertions for an entity are now buffered and applied as bundles to avoid triggering observers without all components being inserted or removed. This also significantly improves performance by avoiding extra archetype moves and lookups.
- The `Replicated` component is no longer automatically inserted into non-replicated entities spawned from replicated components.
Expand Down
6 changes: 4 additions & 2 deletions bevy_replicon_example_backend/tests/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ fn connect_disconnect() {
..Default::default()
}),
RepliconExampleBackendPlugins,
));
))
.finish();
}

setup(&mut server_app, &mut client_app).unwrap();
Expand Down Expand Up @@ -62,7 +63,8 @@ fn replication() {
..Default::default()
}),
RepliconExampleBackendPlugins,
));
))
.finish();
}

setup(&mut server_app, &mut client_app).unwrap();
Expand Down
11 changes: 6 additions & 5 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ impl Plugin for ClientPlugin {
PostUpdate,
(ClientSet::Send, ClientSet::SendPackets).chain(),
)
.add_systems(Startup, setup_channels)
.add_systems(
PreUpdate,
receive_replication
Expand All @@ -78,11 +77,13 @@ impl Plugin for ClientPlugin {
if **app.world().resource::<TrackMutateMessages>() {
app.init_resource::<ServerMutateTicks>();
}
}
}

fn setup_channels(mut client: ResMut<RepliconClient>, channels: Res<RepliconChannels>) {
client.setup_server_channels(channels.server_channels().len());
app.world_mut()
.resource_scope(|world, mut client: Mut<RepliconClient>| {
let channels = world.resource::<RepliconChannels>();
client.setup_server_channels(channels.server_channels().len());
});
}
}

/// Receives and applies replication messages from the server.
Expand Down
11 changes: 7 additions & 4 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ impl Plugin for ServerPlugin {
.add_observer(handle_connects)
.add_observer(handle_disconnects)
.add_observer(buffer_despawns)
.add_systems(Startup, setup_channels)
.add_systems(
PreUpdate,
(
Expand Down Expand Up @@ -175,10 +174,14 @@ impl Plugin for ServerPlugin {
app.register_required_components::<ConnectedClient, ReplicatedClient>();
}
}
}

fn setup_channels(mut server: ResMut<RepliconServer>, channels: Res<RepliconChannels>) {
server.setup_client_channels(channels.client_channels().len());
fn finish(&self, app: &mut App) {
app.world_mut()
.resource_scope(|world, mut server: Mut<RepliconServer>| {
let channels = world.resource::<RepliconChannels>();
server.setup_client_channels(channels.client_channels().len());
});
}
}

/// Increments current server tick which causes the server to replicate this frame.
Expand Down
3 changes: 3 additions & 0 deletions src/shared/backend/replicon_channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use log::debug;

/// A resource with all channels used by Replicon.
///
/// Initialized in [`ClientPlugin::finish`](crate::client::ClientPlugin) and
/// [`ServerPlugin::finish`](crate::server::ServerPlugin).
///
/// Channel IDs are represented by [`usize`], but backends may limit the number of channels.
///
/// The first two channels are used for replication. For more details, see [`ReplicationChannel`].
Expand Down
3 changes: 2 additions & 1 deletion src/test_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ for app in [&mut server_app, &mut client_app] {
tick_policy: TickPolicy::EveryFrame, // To tick each app update.
..Default::default()
}),
));
))
.finish(); // Don't forget to call `finish`.
}

// Simulate connection between two apps:
Expand Down
48 changes: 10 additions & 38 deletions tests/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ fn client_to_server() {
let mut server_app = App::new();
let mut client_app = App::new();
for app in [&mut server_app, &mut client_app] {
app.add_plugins((MinimalPlugins, RepliconPlugins));
app.update();
app.add_plugins((MinimalPlugins, RepliconPlugins)).finish();
}

const MESSAGES: &[&[u8]] = &[&[0], &[1]];
Expand Down Expand Up @@ -44,8 +43,7 @@ fn server_to_client() {
let mut server_app = App::new();
let mut client_app = App::new();
for app in [&mut server_app, &mut client_app] {
app.add_plugins((MinimalPlugins, RepliconPlugins));
app.update();
app.add_plugins((MinimalPlugins, RepliconPlugins)).finish();
}

const MESSAGES: &[&[u8]] = &[&[0], &[1]];
Expand All @@ -71,13 +69,7 @@ fn connect_disconnect() {
let mut server_app = App::new();
let mut client_app = App::new();
for app in [&mut server_app, &mut client_app] {
app.add_plugins((
MinimalPlugins,
RepliconPlugins.set(ServerPlugin {
tick_policy: TickPolicy::EveryFrame,
..Default::default()
}),
));
app.add_plugins((MinimalPlugins, RepliconPlugins)).finish();
}

server_app.connect_client(&mut client_app);
Expand All @@ -102,15 +94,7 @@ fn connect_disconnect() {
#[test]
fn client_cleanup_on_disconnect() {
let mut app = App::new();
app.add_plugins((
MinimalPlugins,
RepliconPlugins.set(ServerPlugin {
tick_policy: TickPolicy::EveryFrame,
..Default::default()
}),
));

app.update();
app.add_plugins((MinimalPlugins, RepliconPlugins)).finish();

let mut client = app.world_mut().resource_mut::<RepliconClient>();
client.set_status(RepliconClientStatus::Connected);
Expand All @@ -129,15 +113,7 @@ fn client_cleanup_on_disconnect() {
#[test]
fn server_cleanup_on_stop() {
let mut app = App::new();
app.add_plugins((
MinimalPlugins,
RepliconPlugins.set(ServerPlugin {
tick_policy: TickPolicy::EveryFrame,
..Default::default()
}),
));

app.update();
app.add_plugins((MinimalPlugins, RepliconPlugins)).finish();

let mut server = app.world_mut().resource_mut::<RepliconServer>();
server.set_running(true);
Expand All @@ -158,13 +134,7 @@ fn server_cleanup_on_stop() {
#[test]
fn client_disconnected() {
let mut app = App::new();
app.add_plugins((
MinimalPlugins,
RepliconPlugins.set(ServerPlugin {
tick_policy: TickPolicy::EveryFrame,
..Default::default()
}),
));
app.add_plugins((MinimalPlugins, RepliconPlugins)).finish();

app.update();

Expand All @@ -188,7 +158,8 @@ fn server_inactive() {
tick_policy: TickPolicy::EveryFrame,
..Default::default()
}),
));
))
.finish();

app.update();

Expand Down Expand Up @@ -217,7 +188,8 @@ fn deferred_replication() {
replicate_after_connect: false,
..Default::default()
}),
));
))
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down
12 changes: 8 additions & 4 deletions tests/despawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ fn single() {
tick_policy: TickPolicy::EveryFrame,
..Default::default()
}),
));
))
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -52,7 +53,8 @@ fn with_hierarchy() {
tick_policy: TickPolicy::EveryFrame,
..Default::default()
}),
));
))
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -98,7 +100,8 @@ fn after_spawn() {
..Default::default()
}),
))
.replicate::<TestComponent>();
.replicate::<TestComponent>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -129,7 +132,8 @@ fn hidden() {
visibility_policy: VisibilityPolicy::Whitelist, // Hide all spawned entities by default.
..Default::default()
}),
));
))
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down
42 changes: 28 additions & 14 deletions tests/insertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ fn table_storage() {
..Default::default()
}),
))
.replicate::<TableComponent>();
.replicate::<TableComponent>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -64,7 +65,8 @@ fn sparse_set_storage() {
..Default::default()
}),
))
.replicate::<SparseSetComponent>();
.replicate::<SparseSetComponent>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -101,7 +103,8 @@ fn immutable() {
..Default::default()
}),
))
.replicate::<ImmutableComponent>();
.replicate::<ImmutableComponent>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -151,7 +154,8 @@ fn mapped_existing_entity() {
..Default::default()
}),
))
.replicate::<MappedComponent>();
.replicate::<MappedComponent>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -200,7 +204,8 @@ fn mapped_new_entity() {
..Default::default()
}),
))
.replicate::<MappedComponent>();
.replicate::<MappedComponent>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -246,7 +251,8 @@ fn multiple_components() {
}),
))
.replicate::<ComponentA>()
.replicate::<ComponentB>();
.replicate::<ComponentB>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -291,7 +297,8 @@ fn command_fns() {
}),
))
.replicate::<OriginalComponent>()
.set_command_fns(replace, command_fns::default_remove::<ReplacedComponent>);
.set_command_fns(replace, command_fns::default_remove::<ReplacedComponent>)
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -335,7 +342,8 @@ fn marker() {
.set_marker_fns::<ReplaceMarker, _>(
replace,
command_fns::default_remove::<ReplacedComponent>,
);
)
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -382,7 +390,8 @@ fn group() {
..Default::default()
}),
))
.replicate_bundle::<(ComponentA, ComponentB)>();
.replicate_bundle::<(ComponentA, ComponentB)>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -418,7 +427,8 @@ fn not_replicated() {
tick_policy: TickPolicy::EveryFrame,
..Default::default()
}),
));
))
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -455,7 +465,8 @@ fn after_removal() {
..Default::default()
}),
))
.replicate::<TestComponent>();
.replicate::<TestComponent>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -507,7 +518,8 @@ fn before_started_replication() {
..Default::default()
}),
))
.replicate::<TestComponent>();
.replicate::<TestComponent>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -553,7 +565,8 @@ fn after_started_replication() {
..Default::default()
}),
))
.replicate::<TestComponent>();
.replicate::<TestComponent>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down Expand Up @@ -592,7 +605,8 @@ fn confirm_history() {
..Default::default()
}),
))
.replicate::<TestComponent>();
.replicate::<TestComponent>()
.finish();
}

server_app.connect_client(&mut client_app);
Expand Down
Loading