lucaspoffo / renet

Server/Client network library for multiplayer games with authentication and connection management made with Rust
Apache License 2.0
662 stars 67 forks source link

Add Transport layer based on memory channels #117

Open OleStrohm opened 11 months ago

OleStrohm commented 11 months ago

Overview

This pull request implements a transport layer based on the stdlib mpsc channel. This allows the renet server and clients to communicate efficiently within a single program. This is especially useful for testing networking code, where you want to be able to guarantee that messages arrive immediately, without having to go through the OS network layer. This should also hopefully allow benchmarks to be more consistent.

It also allows more efficient emulation of a locally hosted server that actually runs within the same binary.

Notes

As this can only be used within the same program, I decided to only expose a way to create new clients from an already existing server. I think this method simplifies the API significantly, and doesn't diminish the ergonomics in the scenarios I am able of thinking of.

I'm not very happy with the current state of the Connection struct, so any advice on that would be very welcome. The problem arises from Sender/Receiver being !Sync, but bevy resources need to be Sync. Bevy therefore provides a SyncCell which can turn Send types into Sync types by only allowing access through a &mut SyncCell<T>. However if this is used outside bevy, then SyncCell is not available. Thus in the current implementation the Transports are !Sync when used standalone. The only good solution I can think of to remedy this would be to copy a barebones version of Bevy's SyncCell and use that. This isn't a great solution, but this struct isn't public outside of renet_channel, so it might be okay.

I also wasn't sure what to do about the example, since this layer only runs within the same process you can't make a proper echo example, so I just added a whole bunch of tests.

OleStrohm commented 11 months ago

I added a method to create a client with a specific client id in case people want to test reconnection strategies that rely on the client id.

UkoeHB commented 5 months ago

@OleStrohm I implemented memory channels as a netcode socket option in renet2. The channel part was re-implemented from scratch (not that many lines), but I did use your test suite from this PR.

Here's the exact commit.