You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/en/ss14-by-example/prediction-guide.md
+13-13Lines changed: 13 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -52,7 +52,7 @@ When setting breakpoints or printing to the console you will notice that the pre
52
52
## Prediction Code example
53
53
Let's look at a simple unpredicted example component and predict it.
54
54
55
-
```C#
55
+
```csharp
56
56
// In Content.Server/PredictionExample/PredictionExampleComponent.cs
57
57
58
58
usingRobust.Shared.Audio;
@@ -81,7 +81,7 @@ public sealed partial class PredictionExampleComponent : Component
81
81
}
82
82
```
83
83
84
-
```C#
84
+
```csharp
85
85
// In Content.Server/PredictionExample/PredictionExampleSystem.cs
86
86
87
87
usingContent.Shared.Examine;
@@ -165,7 +165,7 @@ If we look at this in-game we notice the verb, examination text, popup and sound
165
165
166
166
Now let's move the code to shared and network and predict it.
167
167
168
-
```C#
168
+
```csharp
169
169
// In Content.Shared/PredictionExample/PredictionExampleComponent.cs
170
170
171
171
using Robust.Shared.Audio;
@@ -194,7 +194,7 @@ public sealed partial class PredictionExampleComponent : Component
194
194
}
195
195
196
196
```
197
-
```C#
197
+
```csharp
198
198
// In Content.Shared/PredictionExample/PredictionExampleSystem.cs
199
199
200
200
usingContent.Shared.Examine;
@@ -274,7 +274,7 @@ The result is much more responsive without the delay for the popup, audio or UI
274
274
Shared code can only call other shared code, whereas server-side code can use both server-side and shared code. This means if you want to predict an EntitySystem you will need predict all its dependencies first so that you can use them in Shared, which often turns prediction PRs into much larger tasks than initially expected.
275
275
276
276
Some systems cannot be predicted, but you might still want to call some API methods that are only available on the server from Shared. To work around this you can add an empty virtual API method in the corresponding shared system and override it on the server. Here's an example from [`SharedExplosionSystem`](https://github.com/space-wizards/space-station-14/blob/master/Content.Shared/Explosion/EntitySystems/SharedExplosionSystem.cs):
277
-
```C#
277
+
```csharp
278
278
// In Content.Shared/Explosion/EntitySystems/SharedExplosionSystem.cs
279
279
// This method is empty and does nothing on the client.
@@ -341,7 +341,7 @@ B) The insertion of the entity into the container is not predicted (for example
341
341
This is done that way to allow a client to update UIs even if they did not predict the event, for example the storage window of your backpack, your hand indicator or the damage overlay, but it also may cause problems during subscriptions as any changes done inside them are already networked separately within the same game state, meaning they will be applied multiple times, causing mispredicts.
342
342
343
343
Let's look at an example from `GlueSystem`
344
-
```C#
344
+
```csharp
345
345
// GluedComponent will make an item temporarily unremovable if you pick it up.
A lot of old code is accumulating frametime inside update loops to decide when to next run it.
388
-
```C#
388
+
```csharp
389
389
/// <summary>
390
390
/// Unpredicted example.
391
391
/// </summary>
@@ -430,7 +430,7 @@ public sealed class UpdateLoopExampleSystem : EntitySystem
430
430
```
431
431
This is bad for prediction, as dirtying the accumulator datafield every single tick would be expensive due to the network load if we repeatedly have to send game state updates from the server. So instead of accumulating frame time we use a time stamp indicating when the next update is supposed to happen and compare that with the current server time.
432
432
433
-
```C#
433
+
```csharp
434
434
/// <summary>
435
435
/// Predicted example.
436
436
/// We need to network the component for this.
@@ -547,7 +547,7 @@ Here is an example of a mispredict happening when gibbing someone, so that you k
547
547
In the future Robust Toolbox will have methods for predicted randomness, but at the time of writing the [PR for RandomPredicted](https://github.com/space-wizards/RobustToolbox/pull/5849) has not been merged yet.
548
548
As a workaround you can use a new `System.Random` instance and set the seed to something the server and client agree on, for example a combination of an entity's `NetEntity` id and the current game tick (if you would only the game tick here then all randomness within the same game tick would yield the same result, so we need both).
@@ -601,7 +601,7 @@ Dirtying and networking is expensive. Avoid dirtying entities every single tick
601
601
602
602
When setting a datafield it is recommended to add a guard statement to check if the datafield has a new value before calling `Dirty` so that we only network it when actually necessary.
@@ -670,7 +670,7 @@ There is currently some weird behaviour with solution entities and PVS, which ma
670
670
671
671
This debug assert happens if a predicted update loops calls `SharedSolutionContainerSystem.ResolveSolution`, and the entity containing the solution entity leaves PVS range. This should not be happening since entities are paused when moved outside PVS range, meaning the update loop should no longer run on the client, but for some reason this still causes the debug assert and needs a workaround until this is fixed properly in a way that does not need this boilerplate code.
0 commit comments