Skip to content

Release 0.14.0

Compare
Choose a tag to compare
@cBournhonesque cBournhonesque released this 29 Apr 21:42
· 562 commits to main since this release

Release 0.14.0

Added

Refactored the Protocol

lightyear used to require a Protocol struct which contained 2 enums MessageProtocol and ComponentProtocol that held the list of messages that could be sent over the network.

Now you can split up a protocol into multiple pieces, each piece can be registered directly on the App:

app.add_message::<Message1>(ChannelDirection::Bidirectional);
app.add_plugins(InputPlugin::<Inputs>::default());
app.register_component::<PlayerPosition>(ChannelDirection::ServerToClient)
    .add_prediction::<PlayerPosition>(ComponentSyncMode::Full)
    .add_interpolation::<PlayerPosition>(ComponentSyncMode::Full)
    .add_linear_interpolation_fn::<PlayerPosition>();
app.add_channel::<Channel1>(ChannelSettings {
    mode: ChannelMode::OrderedReliable(ReliableSettings::default()),
    ..default()
});

This approach provides more flexibility, since the Protocol can now be defined in various separate plugins; it also removes a lot of procedural macro magic that was hard to maintain.
Currently the only requirement is that the protocol registration must happen after the ClientPlugin or the ServerPlugin have been added.

Network configuration is modifiable at runtime

Previously, your network configuration would be set in stone after adding the ClientPlugin and ServerPlugin.
Now, you can freely update the configuration (by updating the ClientConfig and ServerConfig resources) at any time, and the configuration change will take effect on the next connection attempt.

I also introduce the NetworkingState state to track the status of the client or server (Connecting, Connected, Disconnected).

This means that a machine can dynamically become a client or a server depending on the configuration!
Here is an example where clients can choose at runtime whether to host the game by acting as 'host-servers', or just join the game as clients.

Automatic Resource replication

You can now easily replicate resources!
There are 2 steps:

  1. Define the resource in your protocol: app.register_resource::<R>(ChannelDirection::ServerToClient);
  2. Use commands to start/stop the replication:
  • commands.replicate_resource::<R>(target) starts the replication
  • commands.pause_replicate_resource::<R>() pauses the replication (without removing the resource)

And every changes to your resource will now be replicated!

Updated

Automatic cleanup on client disconnection

When a client gets disconnected, we now automatically cleanup all entities and resources that had been spawned on the client via replication.
In the future I have plans to make this behavior more configurable (we might want some entities to remain even when disconnected), but I chose to enable this currently for simplicity.

Separating the prediction and interpolation mode

Previously, there was only one configuration shared between Prediction and Interpolation. But there are actually situations where one would want to only enable Prediction and not Interpolation, or vice-versa.
For example, you might need to turn on Prediction on a physics component like AngularVelocity, but not turn on Interpolation since AngularVelocity doesn't have any visual impact on the component.
You can now independently specify the prediction behavior and the interpolation behavior.

Breaking changes

  • The ClientPlugin is now directly created from the ClientConfig, same for ServerPlugin
  • You now have to define a shared protocol by registering the protocol on the App after the ClientPlugin and ServerPlugin have been registered.
  • You now update the connection status via Commands:
    • commands.connect_client()
    • commands.disconnect_client()
    • commands.start_server()
    • commands.stop_server()