Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Core/GameEngine/Include/GameNetwork/networkutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
UnsignedInt AssembleIp(UnsignedByte a, UnsignedByte b, UnsignedByte c, UnsignedByte d);
UnsignedInt ResolveIP(AsciiString host);
UnsignedShort GenerateNextCommandID();
void ResetCommandID();
Bool DoesCommandRequireACommandID(NetCommandType type);
Bool CommandRequiresAck(NetCommandMsg *msg);
Bool CommandRequiresDirectSend(NetCommandMsg *msg);
Expand Down
4 changes: 4 additions & 0 deletions Core/GameEngine/Source/GameNetwork/NetCommandList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ void NetCommandList::reset() {
/**
* Insert sorts msg. Assumes that all the previous message inserts were done using this function.
* The message is sorted in based first on command type, then player id, and then command id.
*
* TheSuperHackers @info Caball009 20/05/2026 The command id may overflow and the sorting in this function
* does not check against that. Changing the sorting implementation to deal with overflows is not retail compatible,
* unlike resetting the command id.
*/
NetCommandRef * NetCommandList::addMessage(NetCommandMsg *cmdMsg) {
if (cmdMsg == nullptr) {
Expand Down
25 changes: 22 additions & 3 deletions Core/GameEngine/Source/GameNetwork/Network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "Common/Player.h"
#include "Common/PlayerList.h"
#include "GameNetwork/NetworkInterface.h"
#include "GameNetwork/networkutil.h"
#include "GameNetwork/udp.h"
#include "GameNetwork/Transport.h"
#include "strtok_r.h"
Expand Down Expand Up @@ -201,6 +202,7 @@ class Network : public NetworkInterface
Int m_frameRate;
Int m_lastExecutionFrame; ///< The highest frame number that a command could have been executed on.
Int m_lastFrameCompleted;
Int m_lastFrameResetCommandID; ///< The last frame the network command ID was reset
Bool m_didSelfSlug;
__int64 m_perfCountFreq; ///< The frequency of the performance counter.

Expand Down Expand Up @@ -273,6 +275,8 @@ Network::Network()
m_conMgr = nullptr;
m_messageWindow = nullptr;

m_lastFrameResetCommandID = 0;

#if defined(RTS_DEBUG)
m_networkOn = TRUE;
#endif
Expand Down Expand Up @@ -331,6 +335,7 @@ void Network::init()
m_frameRate = 30;
m_lastExecutionFrame = m_runAhead - 1; // subtract 1 since we're starting on frame 0
m_lastFrameCompleted = m_runAhead - 1; // subtract 1 since we're starting on frame 0
m_lastFrameResetCommandID = 0;
m_frameDataReady = FALSE;
m_isStalling = FALSE;
m_didSelfSlug = FALSE;
Expand All @@ -356,6 +361,7 @@ void Network::init()
DEBUG_LOG(("FRAME_DATA_LENGTH = %d", FRAME_DATA_LENGTH));
DEBUG_LOG(("FRAMES_TO_KEEP = %d", FRAMES_TO_KEEP));

ResetCommandID();

#if defined(RTS_DEBUG)
m_networkOn = TRUE;
Expand Down Expand Up @@ -697,6 +703,19 @@ void Network::update()
}
#endif

const UnsignedInt frame = TheGameLogic->getFrame();
if (m_localStatus == NETLOCALSTATUS_INGAME) {
if (frame + m_runAhead > m_lastExecutionFrame) {
if (frame >= m_lastFrameResetCommandID + MAX_FRAMES_AHEAD) {
// TheSuperHackers @bugfix Caball009 20/05/2026 Reset the network command id to prevent it from overflowing.
// This prevents commands from being sorted incorrectly, which can cause spurious mismatches at low CRC intervals
// and the disconnect screen from popping up.
m_lastFrameResetCommandID = frame;
ResetCommandID();
}
}
}

GetCommandsFromCommandList(); // Remove commands from TheCommandList and send them to the connection manager.
if (m_conMgr != nullptr) {
if (m_localStatus == NETLOCALSTATUS_INGAME) {
Expand All @@ -713,11 +732,11 @@ void Network::update()
endOfGameCheck();
}

if (AllCommandsReady(TheGameLogic->getFrame())) { // If all the commands are ready for the next frame...
if (AllCommandsReady(frame)) { // If all the commands are ready for the next frame...
m_conMgr->handleAllCommandsReady();
// DEBUG_LOG(("Network::update - frame %d is ready", TheGameLogic->getFrame()));
// DEBUG_LOG(("Network::update - frame %d is ready", frame));
if (timeForNewFrame()) { // This needs to come after any other pre-frame execution checks as this changes the timing variables.
RelayCommandsToCommandList(TheGameLogic->getFrame()); // Put the commands for the next frame on TheCommandList.
RelayCommandsToCommandList(frame); // Put the commands for the next frame on TheCommandList.
m_frameDataReady = TRUE; // Tell the GameEngine to run the commands for the new frame.
}
}
Expand Down
13 changes: 9 additions & 4 deletions Core/GameEngine/Source/GameNetwork/NetworkUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,15 @@ UnsignedInt ResolveIP(AsciiString host)
/**
* Returns the next network command ID.
*/
UnsignedShort GenerateNextCommandID() {
static UnsignedShort commandID = 64000;
++commandID;
return commandID;
static UnsignedShort commandID = 0;
UnsignedShort GenerateNextCommandID()
{
return ++commandID;
}

void ResetCommandID()
{
commandID = 0;
}

/**
Expand Down
Loading