Skip to content

Commit f523f6b

Browse files
committed
Split ReplicationChannel into ServerChannel and ClientChannel
For clarity. While doing so, I noticed that we register an extra client channel. While the server requires two channels, the client only needs one.
1 parent b187ee1 commit f523f6b

File tree

11 files changed

+81
-47
lines changed

11 files changed

+81
-47
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2626
- 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.
2727
- The `Replicated` component is no longer automatically inserted into non-replicated entities spawned from replicated components.
2828
- Replace `ServerEntityMap::get_by_*` and `ServerEntityMap::remove_by_*` with an entry-based API. Use `ServerEntityMap::server_entry` or `ServerEntityMap::client_entry` instead.
29+
- Split `ReplicationChannel` into `ServerChannel` and `ClientChannel` for clarity.
30+
- Don't register an additional unreliable client channel for replication. While the server requires two channels, the client only needs one.
2931
- Print error instead of panic on mapping overwrite in `ServerEntityMap`.
3032

3133
### Removed

src/client.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use postcard::experimental::max_size::MaxSize;
1212
use crate::shared::{
1313
backend::{
1414
ClientState,
15-
replicon_channels::{ReplicationChannel, RepliconChannels},
15+
replicon_channels::{ClientChannel, RepliconChannels, ServerChannel},
1616
replicon_client::RepliconClient,
1717
},
1818
entity_serde, postcard_utils,
@@ -87,10 +87,10 @@ impl Plugin for ClientPlugin {
8787

8888
/// Receives and applies replication messages from the server.
8989
///
90-
/// Update messages are sent over the [`ReplicationChannel::Updates`] and are applied first to ensure valid state
90+
/// Update messages are sent over the [`ServerChannel::Updates`] and are applied first to ensure valid state
9191
/// for component mutations.
9292
///
93-
/// Mutate messages are sent over [`ReplicationChannel::Mutations`], which means they may appear
93+
/// Mutate messages are sent over [`ServerChannel::Mutations`], which means they may appear
9494
/// ahead-of or behind update messages from the same server tick. A mutation will only be applied if its
9595
/// update tick has already appeared in an update message, otherwise it will be buffered while waiting.
9696
/// Since component mutations can arrive in any order, they will only be applied if they correspond to a more
@@ -180,7 +180,7 @@ fn apply_replication(
180180
client: &mut RepliconClient,
181181
buffered_mutations: &mut BufferedMutations,
182182
) -> Result<()> {
183-
for mut message in client.receive(ReplicationChannel::Updates) {
183+
for mut message in client.receive(ServerChannel::Updates) {
184184
apply_update_message(world, params, &mut message)?;
185185
}
186186

@@ -191,14 +191,14 @@ fn apply_replication(
191191
// (unless user requested history via marker).
192192
let update_tick = *world.resource::<ServerUpdateTick>();
193193
let acks_size =
194-
MutateIndex::POSTCARD_MAX_SIZE * client.received_count(ReplicationChannel::Mutations);
194+
MutateIndex::POSTCARD_MAX_SIZE * client.received_count(ServerChannel::Mutations);
195195
if acks_size != 0 {
196196
let mut acks = Vec::with_capacity(acks_size);
197-
for message in client.receive(ReplicationChannel::Mutations) {
197+
for message in client.receive(ServerChannel::Mutations) {
198198
let mutate_index = buffer_mutate_message(params, buffered_mutations, message)?;
199199
postcard_utils::to_extend_mut(&mutate_index, &mut acks)?;
200200
}
201-
client.send(ReplicationChannel::Updates, acks);
201+
client.send(ClientChannel::MutationAcks, acks);
202202
}
203203

204204
apply_mutate_messages(world, params, buffered_mutations, update_tick)

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ It can be disabled by setting [`ServerPlugin::replicate_after_connect`] to `fals
102102
some components on connected clients are only present after replication starts.
103103
See the required components for [`ReplicatedClient`].
104104
105-
For implementation details see [`ReplicationChannel`](shared::backend::replicon_channels::ReplicationChannel).
105+
For implementation details see [`ServerChannel`](shared::backend::replicon_channels::ServerChannel).
106106
107107
### Tick rate
108108
@@ -589,7 +589,7 @@ You can control marker priority or enable processing of old values using [`AppMa
589589
### Ticks information
590590
591591
This requires an understanding of how replication works. See the documentation on
592-
[`ReplicationChannel`](shared::backend::replicon_channels::ReplicationChannel) and [this section](#eventual-consistency) for more details.
592+
[`ServerChannel`](shared::backend::replicon_channels::ServerChannel) and [this section](#eventual-consistency) for more details.
593593
594594
To get information about confirmed ticks for individual entities, we provide
595595
[`ConfirmHistory`](client::confirm_history::ConfirmHistory) along with the [`EntityReplicated`](client::confirm_history::ConfirmHistory)

src/server.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::shared::{
2525
backend::{
2626
ServerState,
2727
connected_client::ConnectedClient,
28-
replicon_channels::{ReplicationChannel, RepliconChannels},
28+
replicon_channels::{ClientChannel, RepliconChannels},
2929
replicon_server::RepliconServer,
3030
},
3131
event::server_event::BufferedServerEvents,
@@ -223,7 +223,7 @@ fn receive_acks(
223223
mut clients: Query<&mut ClientTicks>,
224224
mut entity_buffer: ResMut<EntityBuffer>,
225225
) {
226-
for (client_entity, mut message) in server.receive(ReplicationChannel::Updates) {
226+
for (client_entity, mut message) in server.receive(ClientChannel::MutationAcks) {
227227
while message.has_remaining() {
228228
match postcard_utils::from_buf(&mut message) {
229229
Ok(mutate_index) => {

src/server/replication_messages/mutations.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use postcard::experimental::{max_size::MaxSize, serialized_size};
55

66
use super::{change_ranges::ChangeRanges, serialized_data::SerializedData};
77
use crate::shared::{
8-
backend::{replicon_channels::ReplicationChannel, replicon_server::RepliconServer},
8+
backend::{replicon_channels::ServerChannel, replicon_server::RepliconServer},
99
postcard_utils,
1010
replication::{
1111
client_ticks::{ClientTicks, EntityBuffer},
@@ -147,7 +147,7 @@ impl Mutations {
147147
/// independently on the client.
148148
/// Message splits only happen per-entity to avoid weird behavior from partial entity mutations.
149149
///
150-
/// Sent over the [`ReplicationChannel::Mutations`] channel. If the message gets lost, we try to resend it manually,
150+
/// Sent over the [`ServerChannel::Mutations`] channel. If the message gets lost, we try to resend it manually,
151151
/// using the last up-to-date mutations to avoid re-sending old values.
152152
pub(crate) fn send(
153153
&mut self,
@@ -231,7 +231,7 @@ impl Mutations {
231231

232232
debug_assert_eq!(message.len(), message_size);
233233

234-
server.send(client_entity, ReplicationChannel::Mutations, message);
234+
server.send(client_entity, ServerChannel::Mutations, message);
235235
}
236236

237237
Ok(self.messages.len())

src/server/replication_messages/updates.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use postcard::experimental::serialized_size;
66
use super::{change_ranges::ChangeRanges, mutations::Mutations, serialized_data::SerializedData};
77
use crate::server::client_visibility::Visibility;
88
use crate::shared::{
9-
backend::{replicon_channels::ReplicationChannel, replicon_server::RepliconServer},
9+
backend::{replicon_channels::ServerChannel, replicon_server::RepliconServer},
1010
postcard_utils,
1111
replication::update_message_flags::UpdateMessageFlags,
1212
};
@@ -180,7 +180,7 @@ impl Updates {
180180
/// Contains tick, mappings, insertions, removals, and despawns that
181181
/// happened in this tick.
182182
///
183-
/// Sent over [`ReplicationChannel::Updates`] channel.
183+
/// Sent over [`ServerChannel::Updates`] channel.
184184
///
185185
/// Some data is optional, and their presence is encoded in the [`UpdateMessageFlags`] bitset.
186186
///
@@ -285,7 +285,7 @@ impl Updates {
285285

286286
debug_assert_eq!(message.len(), message_size);
287287

288-
server.send(client_entity, ReplicationChannel::Updates, message);
288+
server.send(client_entity, ServerChannel::Updates, message);
289289

290290
Ok(())
291291
}

src/shared/backend/connected_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub struct ConnectedClient {
3232
/// splitting into multiple packets.
3333
///
3434
/// Used to manually split mutations over packet-size messages to allow applying them partially.
35-
/// For more details on replication see [`ReplicationChannel`](super::replicon_channels::ReplicationChannel).
35+
/// For more details on replication see [`ServerChannel`](super::replicon_channels::ServerChannel).
3636
///
3737
/// <div class="warning">
3838
///

src/shared/backend/replicon_channels.rs

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ use log::debug;
77
/// [`ServerPlugin::finish`](crate::server::ServerPlugin).
88
///
99
/// Channel IDs are represented by [`usize`], but backends may limit the number of channels.
10-
///
11-
/// The first two channels are used for replication. For more details, see [`ReplicationChannel`].
10+
/// See [`ServerChannel`] and [`ClientChannel`] for channels that are always reserved.
1211
///
1312
/// Other channels are used for events, with one channel per event. For more details, see
1413
/// [`RemoteEventRegistry`](crate::shared::event::remote_event_registry::RemoteEventRegistry).
@@ -30,13 +29,10 @@ impl Default for RepliconChannels {
3029
fn default() -> Self {
3130
Self {
3231
server: vec![
33-
ReplicationChannel::Updates.into(),
34-
ReplicationChannel::Mutations.into(),
35-
],
36-
client: vec![
37-
ReplicationChannel::Updates.into(),
38-
ReplicationChannel::Mutations.into(),
32+
ServerChannel::Updates.into(),
33+
ServerChannel::Mutations.into(),
3934
],
35+
client: vec![ClientChannel::MutationAcks.into()],
4036
}
4137
}
4238
}
@@ -71,7 +67,14 @@ impl RepliconChannels {
7167
}
7268
}
7369

74-
/// ID of a server replication channel.
70+
/// Constant ID of a channel for sending data from server to client.
71+
///
72+
/// These channels are always reserved, though additional channels may be required
73+
/// for remote server events. Use [`RepliconChannels`] to retrieve all channels required for Replicon.
74+
///
75+
/// See also [`ClientChannel`].
76+
///
77+
/// # Replication channels
7578
///
7679
/// To synchronize the state, we send only changes using Bevy's change detection.
7780
///
@@ -108,28 +111,57 @@ impl RepliconChannels {
108111
///
109112
/// See also [`RepliconChannels`], [`Channel`] and [corresponding section](../index.html#eventual-consistency)
110113
/// from the quick start guide.
111-
pub enum ReplicationChannel {
114+
pub enum ServerChannel {
112115
/// For sending messages with entity mappings, inserts, removals and despawns.
113116
///
114117
/// This is an ordered reliable channel.
115118
Updates,
116119
/// For sending messages with component mutations.
117120
///
118121
/// This is an unreliable channel.
122+
///
123+
/// See also [`ClientChannel::MutationAcks`].
119124
Mutations,
120125
}
121126

122-
impl From<ReplicationChannel> for Channel {
123-
fn from(value: ReplicationChannel) -> Self {
127+
impl From<ServerChannel> for Channel {
128+
fn from(value: ServerChannel) -> Self {
129+
match value {
130+
ServerChannel::Updates => Channel::Ordered,
131+
ServerChannel::Mutations => Channel::Unreliable,
132+
}
133+
}
134+
}
135+
136+
impl From<ServerChannel> for usize {
137+
fn from(value: ServerChannel) -> Self {
138+
value as usize
139+
}
140+
}
141+
142+
/// Constant ID of a channel for sending data from client to server.
143+
///
144+
/// These channels are always reserved, though additional channels may be required
145+
/// for remote client events. Use [`RepliconChannels`] to retrieve all channels required for Replicon.
146+
///
147+
/// See also [`ServerChannel`].
148+
pub enum ClientChannel {
149+
/// For sending acks to acknowledge mutation messages received from [`ServerChannel::Mutations`].
150+
///
151+
/// This is an ordered reliable channel.
152+
MutationAcks,
153+
}
154+
155+
impl From<ClientChannel> for Channel {
156+
fn from(value: ClientChannel) -> Self {
124157
match value {
125-
ReplicationChannel::Updates => Channel::Ordered,
126-
ReplicationChannel::Mutations => Channel::Unreliable,
158+
ClientChannel::MutationAcks => Channel::Ordered,
127159
}
128160
}
129161
}
130162

131-
impl From<ReplicationChannel> for usize {
132-
fn from(value: ReplicationChannel) -> Self {
163+
impl From<ClientChannel> for usize {
164+
fn from(value: ClientChannel) -> Self {
133165
value as usize
134166
}
135167
}

src/shared/event/server_event.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ pub trait ServerEventAppExt {
148148
/// has not yet received.
149149
///
150150
/// For more details about replication see the documentation on
151-
/// [`ReplicationChannel`](crate::shared::backend::replicon_channels::ReplicationChannel).
151+
/// [`ServerChannel`](crate::shared::backend::replicon_channels::ServerChannel).
152152
///
153153
/// However, if you know your event doesn't rely on that, you can mark it
154154
/// as independent to always emit it immediately. For example, a chat

tests/client_event.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn channels() {
3030

3131
let event_registry = app.world().resource::<RemoteEventRegistry>();
3232
assert_eq!(event_registry.client_channel::<NonRemoteEvent>(), None);
33-
assert_eq!(event_registry.client_channel::<TestEvent>(), Some(2));
33+
assert_eq!(event_registry.client_channel::<TestEvent>(), Some(1));
3434
}
3535

3636
#[test]

tests/connection.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use bevy_replicon::{
44
server::server_tick::ServerTick,
55
shared::backend::{
66
connected_client::{ConnectedClient, NetworkId, NetworkIdMap},
7-
replicon_channels::ReplicationChannel,
7+
replicon_channels::{ClientChannel, ServerChannel},
88
},
99
test_app::ServerTestAppExt,
1010
};
@@ -21,7 +21,7 @@ fn client_to_server() {
2121
const MESSAGES: &[&[u8]] = &[&[0], &[1]];
2222
let mut client = client_app.world_mut().resource_mut::<RepliconClient>();
2323
for &message in MESSAGES {
24-
client.send(ReplicationChannel::Updates, message);
24+
client.send(ClientChannel::MutationAcks, message);
2525
}
2626

2727
let mut server = server_app.world_mut().resource_mut::<RepliconServer>();
@@ -30,7 +30,7 @@ fn client_to_server() {
3030
}
3131

3232
let messages: Vec<_> = server
33-
.receive(ReplicationChannel::Updates)
33+
.receive(ServerChannel::Updates)
3434
.map(|(_, message)| message)
3535
.collect();
3636
assert_eq!(messages, MESSAGES);
@@ -48,15 +48,15 @@ fn server_to_client() {
4848
const MESSAGES: &[&[u8]] = &[&[0], &[1]];
4949
let mut server = server_app.world_mut().resource_mut::<RepliconServer>();
5050
for &message in MESSAGES {
51-
server.send(Entity::PLACEHOLDER, ReplicationChannel::Updates, message);
51+
server.send(Entity::PLACEHOLDER, ServerChannel::Updates, message);
5252
}
5353

5454
let mut client = client_app.world_mut().resource_mut::<RepliconClient>();
5555
for (_, channel_id, message) in server.drain_sent() {
5656
client.insert_received(channel_id, message);
5757
}
5858

59-
let messages: Vec<_> = client.receive(ReplicationChannel::Updates).collect();
59+
let messages: Vec<_> = client.receive(ServerChannel::Updates).collect();
6060
assert_eq!(messages, MESSAGES);
6161
}
6262

@@ -102,8 +102,8 @@ fn client_cleanup_on_disconnect() {
102102
app.world_mut().run_schedule(StateTransition);
103103

104104
let mut client = app.world_mut().resource_mut::<RepliconClient>();
105-
client.send(ReplicationChannel::Updates, Vec::new());
106-
client.insert_received(ReplicationChannel::Updates, Vec::new());
105+
client.send(ServerChannel::Updates, Vec::new());
106+
client.insert_received(ServerChannel::Updates, Vec::new());
107107

108108
app.world_mut()
109109
.resource_mut::<NextState<ClientState>>()
@@ -113,7 +113,7 @@ fn client_cleanup_on_disconnect() {
113113

114114
let mut client = app.world_mut().resource_mut::<RepliconClient>();
115115
assert_eq!(client.drain_sent().count(), 0);
116-
assert_eq!(client.receive(ReplicationChannel::Updates).count(), 0);
116+
assert_eq!(client.receive(ServerChannel::Updates).count(), 0);
117117
}
118118

119119
#[test]
@@ -130,8 +130,8 @@ fn server_cleanup_on_stop() {
130130
app.world_mut().run_schedule(StateTransition);
131131

132132
let mut server = app.world_mut().resource_mut::<RepliconServer>();
133-
server.send(Entity::PLACEHOLDER, ReplicationChannel::Updates, Vec::new());
134-
server.insert_received(Entity::PLACEHOLDER, ReplicationChannel::Updates, Vec::new());
133+
server.send(Entity::PLACEHOLDER, ServerChannel::Updates, Vec::new());
134+
server.insert_received(Entity::PLACEHOLDER, ServerChannel::Updates, Vec::new());
135135

136136
app.world_mut()
137137
.resource_mut::<NextState<ServerState>>()
@@ -141,7 +141,7 @@ fn server_cleanup_on_stop() {
141141

142142
let mut server = app.world_mut().resource_mut::<RepliconServer>();
143143
assert_eq!(server.drain_sent().count(), 0);
144-
assert_eq!(server.receive(ReplicationChannel::Updates).count(), 0);
144+
assert_eq!(server.receive(ServerChannel::Updates).count(), 0);
145145
assert_eq!(app.world().resource::<ServerTick>().get(), 0);
146146
}
147147

0 commit comments

Comments
 (0)