-
Notifications
You must be signed in to change notification settings - Fork 269
Add prediction guide #580
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add prediction guide #580
Conversation
|
Very cool job! |
VerinSenpai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial review. Just some minor wording and grammar nitpicks. Its beautiful 🥺
|
Occurs to me that I reviewed this like a 500 word english essay that's due in 3 weeks. 😅 |
SlamBamActionman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Baller guide. You're the GOAT.
| ``` | ||
| Don't forget the client-side system, even if it's empty. Otherwise the client won't be able to instanciate the system class and it will remain unpredicted. | ||
|
|
||
| Avoid shared abstract components. Some ancient code is still doing this, but nowadays we just instead put the entire component into `Content.Shared`, even if some datafields are only used on the server or client. This is minimally worse for performance, but makes the code much more readable, simplifies any API methods and makes it easier to use `TryComp` and `Resolve`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good place to re-mention netSync and serverOnly here!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait is serverOnly even mentioned? I think the only thing related to server-only datafields is when you imply not adding AutoNetworkedField to fields that shouldn't be networked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest I never used serverOnly so far, so no clue. Usually most components just keep the datafield on the client, even if it's only used on the server. Probably because it's just a microoptimization.
Tayrtahn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great! Thanks for writing all of this up!
Clarified how prediction works
|
Ok, I have rewritten some explanations and I hope they should be more clear now. |
ArtisticRoomba
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
T'was a very good read before bed.
|
|
||
| To reduce the network load the server usually does not send the full game state, but only the changes between each game tick (unless the client is freshly connecting or has major lag spikes). | ||
|
|
||
| Keep in mind that each client can only predict their own inputs and their results, as those of other players will still need to be networked to you first. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A good example that can semi lead into mispredicts: take an instance where you and another player try to grab a tool at nearly the same time. You'll appear to pick up the tool, but suddenly the tool is gone from your hand and is in their hand instead. In this instance the client assumed that you grabbed the tool, but the server decided that the other player had grabbed the tool first. You might have experienced this before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I already got a similar example above, where you interact with something but someone else killed you before your client knows about it.
|
|
||
| #### IRobustCloneable | ||
|
|
||
| Prediction repeatedly resets any dirtied datafield back to a previous game state and resimulates the player input. However, if your datafield is a [reference type](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types) it will only reset the reference to that datafield, not the datafield's current value. This can lead to [mispredicts](https://github.com/space-wizards/space-station-14/pull/34838) and even [major graphical glitches](https://github.com/space-wizards/space-station-14/issues/38512) if not handled correctly. To fix this make sure to implement the `IRobustCloneable` interface when using autonetworking with any custom reference type you are networking and the source generator will make sure to create a deep copy of the datafield for each game state. A code example for this is the [`Solution`](https://github.com/space-wizards/space-station-14/blob/master/Content.Shared/Chemistry/Components/Solution.cs) class used in the [`SolutionComponent`](https://github.com/space-wizards/space-station-14/blob/master/Content.Shared/Chemistry/Components/SolutionComponent.cs). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If IRobustClonable is only necessary for reference types then that means that we shouldn't put them on structs like HeatContainers? If so then it probably should be a warn-as-error type thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Structs may still contain pointers that would then have the same problem because those pointers would be copied by value.
HeatContainers would be fine without I guess, but it does not hurt to implement the interface in case someone expands them in the future.
|
|
||
| #### Only use NetworkedComponentAttribute for shared components | ||
| Adding `[NetworkedComponent]` to a purely server- or client-side component (i.e. not in `Content.Shared`) does not make any sense since those cannot be networked in the first place. | ||
| However at the time of writing RobustToolbox is not preventing you from doing so and instead of creating a warning or error it will just break silently. The sympoms include random other components no longer being networked to the client, which will cause a huge range of bugs, for example mispredicts and UIs not being populated. So this is something you should keep an eye on during reviews or when writing new code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Symptoms*
Also Jesus Christ.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, someone on the dev bus spent several days trying to figure out why their fork suddenly was bugging out everywhere. Turns out a completely unrelated PR had a single NetworkedComponent on a server side component.
This really needs an analyzer.
ArtisticRoomba
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah.
Adds a guide to prediction, along with a few code examples and gifs showcasing the results.
I tried writing down everything that needs to be known, let me know if anything is wrong or unclear.
Draft until I had a few contributors and maintainers proofreading this and give feedback.
Especially the section on ApplyingState seems like it could be explained a little better, but it's a complicated topic.
ToDo in a future PR: Update the
Basic Networking and youdoc to include sections on field deltas,NetSerializableAttributeand howEntityUidsare converted intoNetEntitiesby the source generator.