gschup / bevy_ggrs

Bevy plugin for the GGRS P2P rollback networking library.
Other
294 stars 41 forks source link

Support synchronizing parts of world state, since Rust isn't deterministic. #110

Open seivan opened 3 months ago

seivan commented 3 months ago

Is your feature request related to a problem? Please describe. Rust isn't deterministic across platforms, and neither are most of rust game dev libs.

Describe the solution you'd like Make ggrs support world state syncing for select component with its rollbacks from host.

Describe alternatives you've considered Using straight up UDP for syncing host and clients. But it's a shame, because ggrs has the right idea of using inputs + prediction. The only thing is missing is an out of the box solution for syncing states since there is no determinism guarantee.

Additional context Something that supports the ideas here https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization

Shelim commented 1 month ago

Any progress on this? Or maybe some insight on how to implement it in client code? :)

gschup commented 1 month ago

Thanks for asking! Always happy to receive ideas and comments! Please let me elaborate why I am not a fan of this idea.

While I understand why this is a popular request, this goes against the main idea of what GGPO and therefore GGRS aims to achieve.

Implementing the message would not be extremely complex. It would require adding a new message type to GGRS that is then pushed to the client as an Event. Then the user has to adjust the state given the information in that event. Making that happen in bevy might be trickier, but let's leave that for the future.

What is tricky here are the choices made along the way.

My idea here is that GGRS is not a general purpose networking solution. If your game is not deterministic, you should probably use a different networking crate. Keeping this strong assumption leaves the crate lean-"ish" with a clear use case.

What do you think about this? Let me know! :)

Shelim commented 1 month ago

I am actually investigating network crates for upcoming Bevy Jam - had my share of network game code, but outside of Rust stack. The problem I see is with float's, there can be always slight mis-calculations and drifting and those values can add-up quickly and explode the system. I wonder what kind of prevention / handle mechanism of such situations can GGRS provide. :)

Right now my idea is to designate one player (first one?) the owner of the game, and the rest players will send him periodically checksums of partial game state. In case of detected desync, the owner will send correction every few frames (these should be interpolated on clients from current state when received) until the matching checksum is send back from that player. If the owner disconnects, the next player will assume its role.

My idea is to send correction as some kind of "special Input", so they will participate in rollbacking and advancing.

seivan commented 1 month ago

I mean is it even possible to be deterministic with rust? And if so is it cross platform? Are any of the physics engines like Rapier or the new one (forgot the name) guaranteeing determinism of any shape? It all feels very hand wavy at this point.

gschup commented 1 month ago

No, neither floats nor libraries like bevy or rapier guarantee determinism for all their features. A common technique used in the fighting game development scene is to use fixed-point math instead of float computations. Using GGPO or any other rollback library usually requires either writing a lot of functionality yourself to meet the determinism-requirements or wrappers and workarounds to use other libraries.

This is the biggest hurdle in using rollback libraries like this.

Shelim commented 1 month ago

Actually Rapier has article regarding achieving determinism: https://rapier.rs/docs/user_guides/rust/determinism/

They also claim that:

The target platforms must strictly comply to the IEEE 754-2008 floating-points standard. This ensures that floating-point computations behave the same on all platforms. This include most modern mainstream processors as well as WASM targets.

johanhelsing commented 1 month ago

When I've been trying to use ggrs with a regular physics engine, the problem hasn't been floats, but reliance on added/changed queries and cached state that doesn't handle rolling back, and nondeterministic iteration order in queries.

I'm rolling my own physics for that reason, but i don't avoid floats.

If you're using vec3 etc, make sure you enable the libm feature of glam to disable simd instructions, though.