Open seivan opened 3 months ago
Any progress on this? Or maybe some insight on how to implement it in client code? :)
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.
How do you ensure state corrections arrive at each client in time? What if a correction packet gets dropped?
When applying state corrections, why do all the work of rolling back and resimulating if predicted wrong? Immediately, this leads to a different type of networking.
In a hypothetical scenario with three clients, client A received two state corrections from B and C. Which one do you apply and which do you ignore? How to insure that all clients make the same choice?
Lastly, enabling state corrections also opens the door for cheating (a luxury problem).
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! :)
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.
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.
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.
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.
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.
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