Release 0.21.0
Lightyear 0.21.0
Multiple crates
This is a massive release that is basically a full rewrite of the crate. In particular, the crate has been split into multiple subcrates, for the following reasons:
- faster compile times
- more modularity by splitting up small pieces into different crates
- encourages a better separation of concerns
This was definitely challenging but I think it's for the better.
Similarly to bevy, you will have lightyear_* subcrates and a main lightyear crate which imports every subcrate.
It is possible to use the subcrates directly if you want, as the main crate just imports the relevant plugins from the subcrates.
From Resources to Entities
Instead of managing the networking behaviour via a set of Resources (ClientConfig, ClientConnectionManager, etc.), we now switch to a model where you have one entity per network connection between the local peer and the remote peer. (this approach was pioneered by
aeronet)
-
at the transport layer (how to send/remove bytes):
- you can add one of the IO components (UdpIO, WebTransportIO, etc.) to specify how you will send or receive bytes from the remote peer
- the IO-agnostic
Linkcomponent is used to abstract away from the actual io - you can access metadata about the io link using the
LocalAddrandPeerAddrcomponents - the state of the link can be accessed via various marker components (
Linked,Unlinked) - the
Transportcomponent can be added to specify various channels that provide different reliability and ordering guarantees - the
MessageSender<M>andMessageReceiver<M>components can be added to add the ability to send and receive structs instead of raw bytes. TheMessageManageris responsible for handling the serialization and the entity mapping
-
at the connection layer (how to establish a persistent connection on top of the raw io):
- you can add the
ClientorServercomponent to specify the role of the entity. In particular, theServercomponent will listen for incoming connections and spawn newClientOfentities for each connected client - the state of the connection can be accessed via various marker components (
Connected,Disconnected,Started,Stopped) - the
NetcodeClientorNetcodeServercomponents can be added to use netcode as the layer providing authentication + persistent IDs on top of the raw IO
- you can add the
-
at the syncing layer (how to make sure that the local and remote peers are in sync)
- there is now a new
Timelinecomponent that is used to represent the various networking timelines:- the
LocalTimelinesimply increments the tick whenever the FixedUpdate schedule runs - the
RemoteTimelineis the local peer's best estimate of the remote peer's timeline; computed from the received packets. This is used to make sure that all the timelines remain in sync with the remote peer - the
InterpolationTimelineis in the past compared to the Remote, and is used to define how to interpolate between the received remote packets - the
InputTimelineis in the future to the Remote, and is used to define when ticks should be buffered
- the
- there is now a new
-
at the input layer (how do the clients send inputs to the server)
- the ActionState component defines the current state of the inputs at the current tick. It is guaranteed to be the same between client and server for a given tick
- the InputBuffer component can be used to access the received inputs that were locally buffered
- lightyear now has a shared generic inputs plugin that makes sure input-handling is correct with rollback, input_delay, rebroadcasting to other clients, etc. There are 3 implementations: native, leafwing, and bevy-enhanced-input
-
at the replication layer (how to replicate the state of the World to the remote)
- you can add the
ReplicationSenderandReplicationReceivercomponents to specify if you want the peer to be part of replication - the
PredictionManagerandInterpolationManagermark a link entity as having prediction/interpolation enabled
- you can add the
The bevy ECS provides a lot of flexibility: you can add or remove these components from a subset of the peers to change their networking configuration. Usually if you make changes, they will be applied on the next connection attempt.
This change was mostly made possibly with the recent ECS innovations: observers and relationships.
Moving away from Client-Server
Lightyear was strongly tied to the concepts of client and server. You had to use some specialized client or server resources (ClientManager and ServerManager) and those would have very similar code that varied in subtle ways. For example the replication code was essentially duplicated between them, apart from some server-specific code.
With the new component-based approach, the code has become fairly agnostic to the roles of client and servers.
For example there is now a unique replication system that works on any entity that has a ReplicationSender component, so each local peer can replicate to a remote peer in the exact same way!
I think this is super exciting as this opens the door to handling P2P topology with code that is very similar to client-server topologies!
Total parity?
This refactor of the crate doesn't achieve total parity with the previous version. Some of the functionality that hasn't been ported is:
- Resource replication: I believe bevy is moving towards resource-as-entities, where resources are simply components stored on an entity. I will just be waiting for this to be merged before re-adding resource replication
- input broadcasting: we previously had convenience functions so that a client could send a message to another client (the message would be sent to the server, who would broadcast it to the correct client). This hasn't been re-added yet
- authority: the handling of authority is still somewhat in flux, I have made steps towards it but it hasn't been properly tested, and the
distributed_authorityexample is still outdated.
Extras
-
Instead of maintaining my own steam, webtransport, websocket io layers, I now defer to the excellent aeronet crate!
-
Special thanks to @hukasu for helping me improve the compile time of lightyear!
Next steps
With the increased flexibility and modularity, I would like to tackle:
- handling networking modes where only inputs are replicated, such as deterministic lockstep! I believe this should now be very much within reach, as it mostly involves adding a
LockstepTimelineto define how the local and remote peers stay in sync - handling P2P topologies
What's Changed
- Bevy main refactor by @cBournhonesque in #989
- Update criterion requirement from 0.5 to 0.6 by @dependabot in #1013
- Fixed Client and server Working in Launcher Example by @JosephLassuy in #1014
- Allow replicating immutable components by @cBournhonesque in #1015
- Release 0.21 rc1 by @cBournhonesque in #1017
- Separate Connected from LocalId/RemoteId by @cBournhonesque in #1018
- Add steam using aeronet by @cBournhonesque in #1019
- Add rollback tolerance to avian examples by @cBournhonesque in #1020
- Fix lobby example (without HostServer) and add protocolhash by @cBournhonesque in #1021
- fix(prediction): add history-buffer for pre-existing components when … by @cBournhonesque in #1022
- Add HostServer by @cBournhonesque in #1023
- chore(example): enable host-client mode on simple box by @cBournhonesque in #1024
- chore(replication): add simple test to check that replicate can be re… by @cBournhonesque in #1026
- fix(host-server): fix overlapping ui nodes breaking disconnect button by @komodo472 in #1030
- fix(host): fix host-server disconnect by @komodo472 in #1031
- chore(host-server): enable host-server for all examples by @cBournhonesque in #1029
- Add #[reflect(MapEntities)] to RelationshipSync by @BigBadE in #1033
- Adds #[reflect(Component)] to Replicate. by @BigBadE in #1038
- feat(BEI): support BEI inputs by @cBournhonesque in #1039
- bug(inputs): fix inputs by @cBournhonesque in #1040
- Make workspace crates depend on individual bevy crates by @hukasu in #1043
- fix(bug): fix bug on fps example with missing PlayerMarker component by @cBournhonesque in #1047
- Updates notes for SinceLastSend and DeltaCompression by @cBournhonesque in #1048
- Alternative replication system + fix delta-compression by @cBournhonesque in #1049
- chore(tests): add tests for delta-compression by @cBournhonesque in #1051
- chore(docs) by @cBournhonesque in #1054
- chore(release): release 0.21 rc 2 by @cBournhonesque in #1055
- chore(book): fix book ci by @cBournhonesque in #1057
- Separate avian into 2 crates + fix delta-compression example by @cBournhonesque in #1058
- Update pprof requirement from 0.14.0 to 0.15.0 by @dependabot in #1016
- Update steamworks requirement from 0.11 to 0.12 by @dependabot in #1053
- Fix lobby example to allow host-clients by @cBournhonesque in #1060
- Enable steam on simple_box example + fix wasm by @cBournhonesque in #1061
- Release 0.21.0-rc.3 by @cBournhonesque in #1062
- chore(docs): enable all-features when building docs by @cBournhonesque in #1064
- Release 0.21.0 by @cBournhonesque in #1065
New Contributors
- @JosephLassuy made their first contribution in #1014
- @komodo472 made their first contribution in #1030
- @BigBadE made their first contribution in #1033
- @hukasu made their first contribution in #1043
Full Changelog: 0.20.2...0.21.0