1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
use *;
use debug;
/// A resource with all channels used by Replicon.
///
/// Initialized in [`ClientPlugin::finish`](crate::client::ClientPlugin) and
/// [`ServerPlugin::finish`](crate::server::ServerPlugin).
///
/// The channels are divided into client and server channels.
/// On a client:
/// - [`Self::client_channels`] are used for sending.
/// - [`Self::server_channels`] are used for receiving.
///
/// On a server:
/// - [`Self::server_channels`] are used for sending.
/// - [`Self::client_channels`] are used for receiving.
///
/// If the backend does not distinguish between sending and receiving channels,
/// create channels for both client and server by chaining them.
///
/// Channel IDs are represented by [`usize`], but backends may limit the number of channels.
/// See [`ServerChannel`] and [`ClientChannel`] for channels that are always reserved.
/// Other channels are used for events, with one channel per event. For more details, see
/// [`RemoteMessageRegistry`](crate::shared::message::registry::RemoteMessageRegistry).
///
/// The backend needs to provide an API for creating its own channels. This can be done
/// by writing an extension trait for this struct. Created channels should have the defined
/// delivery guarantee or stronger.
/// Only stores the replication channel by default.
/// Constant ID of a channel for sending data from server to client.
///
/// These channels are always reserved, though additional channels may be required
/// for remote server events. Use [`RepliconChannels`] to retrieve all channels required for Replicon.
///
/// See also [`ClientChannel`].
///
/// # Replication channels
///
/// To synchronize the state, we send only changes using Bevy's change detection.
///
/// We can't use only a reliable channel because of how reliability is implemented. Messages are split into packets
/// based on the MTU and are considered received only if all their packets are received. If any packet is dropped,
/// it gets resent with the same data. However, on the client, we care only about the latest data. For example:
///
/// - Tick 1, position X - received.
/// - Tick 2, position Y - missed.
/// - Tick 3, position Z - received.
///
/// By tick 3, we no longer care about the missing position from tick 2, but it will still be resent.
///
/// We also can't use only an unreliable channel. We could implement a custom acknowledgment system on top of it
/// and resend the latest data if a message is lost. However, partial updates would break the game logic.
/// For example, if a component that references an entity is lost, we can't resend it with the new entity
/// because the client might not have received the entity yet.
///
/// This is why we use a dual-channel approach to send data.
///
/// For everything except mutations, we use a reliable channel. This data can't be outdated and is sent in
/// a single update message for each tick to ensure atomic updates.
///
/// For mutations, we use an unreliable channel. This data can be outdated, so we always send the latest values
/// since the last acknowledgment. We also include a minimum required tick - the tick on which the last update
/// message was sent. Messages will be buffered until an update message for this tick is received. Mutations
/// are split into packet-size messages to allow applying them partially without waiting for all parts of the message.
/// We guarantee that all mutations for a single entity arrive won't be split across messages, even if they are larger
/// than the packet size. You can also ensure that mutations for specific entities arrive in sync by using
/// [`SyncRelatedAppExt::sync_related_entities`](crate::server::related_entities::SyncRelatedAppExt::sync_related_entities).
///
/// Server events also have minimum required tick. For details, see the documentation on
/// [`ServerMessageAppExt::make_message_independent`](crate::shared::message::server_message::ServerMessageAppExt::make_message_independent).
///
/// See also [`RepliconChannels`], [`Channel`] and [corresponding section](crate#eventual-consistency)
/// from the quick start guide.
/// Constant ID of a channel for sending data from client to server.
///
/// These channels are always reserved, though additional channels may be required
/// for remote client events. Use [`RepliconChannels`] to retrieve all channels required for Replicon.
///
/// See also [`ServerChannel`].
/// Channel delivery guarantee.