bugfix(network): Reset network command id to keep commands in chronological order#2736
bugfix(network): Reset network command id to keep commands in chronological order#2736Caball009 wants to merge 3 commits into
Conversation
This reverts commit 52d5e82.
ee6bcd8 to
1f31061
Compare
|
| Filename | Overview |
|---|---|
| Core/GameEngine/Source/GameNetwork/NetworkUtil.cpp | Moves commandID to file scope, adds ResetCommandID(), and changes GenerateNextCommandID() to post-increment semantics; straightforward and correct. |
| Core/GameEngine/Source/GameNetwork/Network.cpp | Adds m_lastFrameResetCommandID member and periodic reset logic in update(); the throttle condition and initialization in both constructor and init() are consistent and correct. |
| Core/GameEngine/Include/GameNetwork/networkutil.h | Adds ResetCommandID() declaration; already uses #pragma once; no issues. |
| Core/GameEngine/Source/GameNetwork/NetCommandList.cpp | Adds an informational comment explaining the overflow limitation of the sort; no logic changes. |
Sequence Diagram
sequenceDiagram
participant GL as GameLogic
participant Net as Network::update()
participant CID as commandID (static)
participant CM as ConnectionManager
Note over Net,CID: Every MAX_FRAMES_AHEAD frames (when executing ahead)
Net->>CID: "ResetCommandID() → commandID = 0"
GL->>CM: Game commands queued on TheCommandList
Net->>CM: GetCommandsFromCommandList()
CM->>CID: GenerateNextCommandID() → 0, 1, 2 …
CM-->>Net: Commands tagged with fresh IDs
Net->>CM: liteupdate() / FRAMEINFO / RUNAHEAD msgs
CM->>CID: GenerateNextCommandID() → continues monotonically
Net->>Net: AllCommandsReady(frame)?
Net->>GL: RelayCommandsToCommandList(frame)
Note over GL: Commands sorted by (type, playerID, commandID) — all IDs monotone within one frame
Reviews (4): Last reviewed commit: "Added code to reset command id." | Re-trigger Greptile
1f31061 to
ebf1fa2
Compare
ebf1fa2 to
a7ff356
Compare
|
Resetting the command id just delays the potential mismatch, right? Wouldn't it be better to sort the command ids properly, even if that rarely causes mismatches with retail clients? |
It's reset every N frames, so it's not just delayed. |
a7ff356 to
3ae2622
Compare
xezon
left a comment
There was a problem hiding this comment.
The id needs to be unique per execution frame.
Can we just reset it to 0 or 1 at the beginning of every new frame? Or does that cause issues? What is the reason for it to reset every 128 frames now?
| static UnsignedShort commandID = 64000; | ||
| ++commandID; | ||
| return commandID; | ||
| static UnsignedShort commandID = 0; |
| static UnsignedShort commandID = 64000; | ||
| ++commandID; | ||
| return commandID; | ||
| static UnsignedShort commandID = 0; |
There was a problem hiding this comment.
Is it ok to start it at 0 when retail clients still start at 64000 ? I suspect this means every client can make up his own Id numbers as he pleases ?
Any clue why the original author picked 64000 as a start for it ?
| #endif | ||
|
|
||
| const UnsignedInt frame = TheGameLogic->getFrame(); | ||
| if (m_localStatus == NETLOCALSTATUS_INGAME) { |
|
|
||
| const UnsignedInt frame = TheGameLogic->getFrame(); | ||
| if (m_localStatus == NETLOCALSTATUS_INGAME) { | ||
| if (frame + m_runAhead > m_lastExecutionFrame) { |
There was a problem hiding this comment.
I do not understand this condition. Can you explain it?
Synchronized network commands are given a unique id so that they can be sorted chronologically. The id needs to be unique per execution frame. It's a uint16 value so it'll overflow quite fast, especially because it's never reset and the starting value is 64000 by default.
When the network runahead decreases it's expected that multiple frames are executed right after each other. I noticed an issue with the overflow when I set the CRC interval to once per frame. When the overflow happened for a client combined with a decrease of the runahead, the order of the CRC messages was no longer guaranteed to be in chronological order for that execution frame. That would cause a mismatch if the overflow didn't happen for all clients at the same time.
With a starting value of 64000 and a CRC message every frame the first overflow happens after ~25 seconds. You can see it mismatch here because of the overflow (this was with a special test build);
https://www.youtube.com/live/V_l-q9Y-DmA?t=621s
https://www.youtube.com/live/V_l-q9Y-DmA?t=9499s
I've added some test code in the first commit. If that's used without this fix, it becomes very apparent that the messages are not in the right order when the command id overflows. On top of that, it's very likely that the disconnect bug (disconnect screen with everyone at ~59XXX msec) occurs frequently.
I intend to do a follow up PR to make the
static commandIDvariable a part of theNetCommandMsgclass.