Skip to content
Open
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
36 changes: 27 additions & 9 deletions Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2383,6 +2383,9 @@
Player *msgPlayer = getMessagePlayer(msg);
if (TheNetwork)
{
if (TheNetwork->sawCRCMismatch())
return false;

Int slotIndex = -1;
for (Int i=0; i<MAX_SLOTS; ++i)
{
Expand All @@ -2401,26 +2404,41 @@
#if defined(RTS_DEBUG)
// don't even put this in release, cause someone might hack it.
if (!TheDebugIgnoreSyncErrors)
{
#endif
m_shouldValidateCRCs = TRUE;
#if defined(RTS_DEBUG)
}
#endif
m_validationModeCRC = CRCMODE_NETWORK;

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6-debug+t+e

'CRCMODE_NETWORK' : undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6-debug+t+e

'm_validationModeCRC' : undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6-profile+t+e

'CRCMODE_NETWORK' : undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6-profile+t+e

'm_validationModeCRC' : undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6+t+e

'CRCMODE_NETWORK' : undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6+t+e

'm_validationModeCRC' : undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-debug+t+e

'CRCMODE_NETWORK': undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-debug+t+e

'm_validationModeCRC': undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32+t+e

'CRCMODE_NETWORK': undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32+t+e

'm_validationModeCRC': undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-profile+t+e

'CRCMODE_NETWORK': undeclared identifier

Check failure on line 2408 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-profile+t+e

'm_validationModeCRC': undeclared identifier
}

UnsignedInt newCRC = msg->getArgument(0)->integer;
const UnsignedInt newCRC = msg->getArgument(0)->integer;
//DEBUG_LOG(("Received CRC of %8.8X from %ls on frame %d", newCRC,
//msgPlayer->getPlayerDisplayName().str(), m_frame));

m_cachedCRCs[msgPlayer->getPlayerIndex()] = newCRC;
}
else if (TheRecorder && TheRecorder->isPlaybackMode())
{
UnsignedInt newCRC = msg->getArgument(0)->integer;
//DEBUG_LOG(("Saw CRC of %X from player %d. Our CRC is %X. Arg count is %d",
#if RETAIL_COMPATIBLE_CRC
DEBUG_ASSERTCRASH(msg->getArgument(1)->boolean == msgPlayer->isLocalPlayer(),
("CRC message origin is unexpected; playback message argument doesn't match message player index"));
Comment thread
Caball009 marked this conversation as resolved.
#endif

if (TheRecorder->sawCRCMismatch())
return false;

const UnsignedInt newCRC = msg->getArgument(0)->integer;
//DEBUG_LOG(("Saw CRC of %X from player %d. Our CRC is %X. Arg count is %d",
//newCRC, msgPlayer->getPlayerIndex(), getCRC(), msg->getArgumentCount()));

TheRecorder->handleCRCMessage(newCRC, msgPlayer->getPlayerIndex(), (msg->getArgument(1)->boolean));
if (msgPlayer->isLocalPlayer())
{
// TheSuperHackers @info The replay observer / playback player is the local player during playback mode.
TheRecorder->handlePlaybackCRCMessage(newCRC);

Check failure on line 2434 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6-debug+t+e

'handlePlaybackCRCMessage' : is not a member of 'RecorderClass'

Check failure on line 2434 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6-profile+t+e

'handlePlaybackCRCMessage' : is not a member of 'RecorderClass'

Check failure on line 2434 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6+t+e

'handlePlaybackCRCMessage' : is not a member of 'RecorderClass'

Check failure on line 2434 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-debug+t+e

'handlePlaybackCRCMessage': is not a member of 'RecorderClass'

Check failure on line 2434 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32+t+e

'handlePlaybackCRCMessage': is not a member of 'RecorderClass'

Check failure on line 2434 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-profile+t+e

'handlePlaybackCRCMessage': is not a member of 'RecorderClass'
}
else
{
TheRecorder->handlePlayerCRCMessage(msgPlayer->getPlayerIndex(), newCRC);

Check failure on line 2438 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6-debug+t+e

'handlePlayerCRCMessage' : is not a member of 'RecorderClass'

Check failure on line 2438 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6-profile+t+e

'handlePlayerCRCMessage' : is not a member of 'RecorderClass'

Check failure on line 2438 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6+t+e

'handlePlayerCRCMessage' : is not a member of 'RecorderClass'

Check failure on line 2438 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-debug+t+e

'handlePlayerCRCMessage': is not a member of 'RecorderClass'

Check failure on line 2438 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32+t+e

'handlePlayerCRCMessage': is not a member of 'RecorderClass'

Check failure on line 2438 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-profile+t+e

'handlePlayerCRCMessage': is not a member of 'RecorderClass'

m_validationModeCRC = CRCMODE_REPLAY;

Check failure on line 2440 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6-debug+t+e

'CRCMODE_REPLAY' : undeclared identifier

Check failure on line 2440 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6-profile+t+e

'CRCMODE_REPLAY' : undeclared identifier

Check failure on line 2440 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / vc6+t+e

'CRCMODE_REPLAY' : undeclared identifier

Check failure on line 2440 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-debug+t+e

'CRCMODE_REPLAY': undeclared identifier

Check failure on line 2440 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-debug+t+e

'm_validationModeCRC': undeclared identifier

Check failure on line 2440 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32+t+e

'CRCMODE_REPLAY': undeclared identifier

Check failure on line 2440 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32+t+e

'm_validationModeCRC': undeclared identifier

Check failure on line 2440 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-profile+t+e

'CRCMODE_REPLAY': undeclared identifier

Check failure on line 2440 in Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp

View workflow job for this annotation

GitHub Actions / Build Generals / win32-profile+t+e

'm_validationModeCRC': undeclared identifier
}
}

return true;
Expand Down
2 changes: 2 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ class GlobalData : public SubsystemInterface
Bool m_afterIntro; ///< we need to tell the game our intro is done
Bool m_allowExitOutOfMovies; ///< flag to allow exit out of movies only after the Intro has played

Bool m_replayLocalPlayerCRC; ///< flag to validate CRC messages only from the player who recorded a replay

Bool m_loadScreenRender; ///< flag to disallow rendering of almost everything during a loadscreen

Real m_keyboardScrollFactor; ///< Factor applied to game scrolling speed via keyboard scrolling
Expand Down
2 changes: 1 addition & 1 deletion GeneralsMD/Code/GameEngine/Include/Common/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class Player : public Snapshot

void deletePlayerAI();

UnicodeString getPlayerDisplayName() { return m_playerDisplayName; }
UnicodeString getPlayerDisplayName() const { return m_playerDisplayName; }
NameKeyType getPlayerNameKey() const { return m_playerNameKey; }

AsciiString getSide() const { return m_side; }
Expand Down
60 changes: 48 additions & 12 deletions GeneralsMD/Code/GameEngine/Include/Common/Recorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,55 @@ class RecorderClass : public SubsystemInterface
class CRCInfo
{
public:
struct MismatchData
{
enum CPP_11(: Byte)
{
PLAYER_PLAYBACK = -1,
PLAYER_UNKNOWN = -2,
};

MismatchData() :
mismatched(false),
playerIndex(0),
queueSize(0),
playbackCRC(0),
playerCRC(0)
{}

MismatchData(Byte playerIndex, UnsignedShort queueSize, UnsignedInt playbackCRC, UnsignedInt playerCRC) :
mismatched(true),
playerIndex(playerIndex),
queueSize(queueSize),
playbackCRC(playbackCRC),
playerCRC(playerCRC)
{}

Bool mismatched;
Byte playerIndex;
UnsignedShort queueSize;
UnsignedInt playbackCRC;
UnsignedInt playerCRC;
};

CRCInfo();
CRCInfo(UnsignedInt localPlayer, Bool isMultiplayer);
void addCRC(UnsignedInt val);
UnsignedInt readCRC();
int GetQueueSize() const { return m_data.size(); }
UnsignedInt getLocalPlayer() const { return m_localPlayer; }
void setSawCRCMismatch() { m_sawCRCMismatch = TRUE; }
Bool sawCRCMismatch() const { return m_sawCRCMismatch; }
void init(Bool isMultiplayer, Int localPlayerIndex);
void pushPlaybackCRC(UnsignedInt val);
void pushPlayerCRC(Int playerIndex, UnsignedInt val);
void setSawCRCMismatch();
Bool sawCRCMismatch() const;
Byte getLocalPlayerIndex() const;
MismatchData generateMismatchData();

protected:
Bool m_sawCRCMismatch;
UnsignedInt getLargestQueueSize() const;
UnsignedInt popPlaybackCRC();

Bool m_skippedOne;
UnsignedInt m_localPlayer;
std::list<UnsignedInt> m_data;
Bool m_sawCRCMismatch;
Byte m_localPlayerIndex;
std::list<UnsignedInt> m_playbackData;
std::vector<UnsignedInt> m_playerData[MAX_PLAYER_COUNT];
};

public:
Expand Down Expand Up @@ -110,8 +145,9 @@ class RecorderClass : public SubsystemInterface
#endif
Bool isPlaybackInProgress() const;

public:
void handleCRCMessage(UnsignedInt newCRC, Int playerIndex, Bool fromPlayback);
void handlePlaybackCRCMessage(UnsignedInt newCRC);
void handlePlayerCRCMessage(Int playerIndex, UnsignedInt newCRC);
void checkForMismatch();

// read in info relating to a replay, conditionally setting up m_file for playback
struct ReplayHeader
Expand Down
11 changes: 10 additions & 1 deletion GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,17 @@ class GameLogic : public SubsystemInterface, public Snapshot

static void createOptimizedTree(const ThingTemplate *thingTemplate, Coord3D *pos, Real angle);

void checkForMismatch();

private:

enum CRCValidationMode CPP_11(: UnsignedByte)
{
CRCMODE_NONE,
CRCMODE_NETWORK,
CRCMODE_REPLAY,
};

/**
overrides to thing template buildable status. doesn't really belong here,
but has to go somewhere. (srj)
Expand All @@ -392,7 +401,7 @@ class GameLogic : public SubsystemInterface, public Snapshot
UnsignedInt m_CRC; ///< Cache of previous CRC value
typedef std::map<Int, UnsignedInt> CachedCRCMap;
CachedCRCMap m_cachedCRCs; ///< CRCs we've seen this frame
Bool m_shouldValidateCRCs; ///< Should we validate CRCs this frame?
CRCValidationMode m_validationModeCRC; ///< (How) should we validate CRCs this frame?
//-----------------------------------------------------------------------------------------------
//Bool m_loadingScene;
Bool m_loadingMap;
Expand Down
10 changes: 10 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,13 @@ Int parseJobs(char *args[], int num)
return 1;
}

Int parseReplayLocalPlayerCRC(char* args[], int num)
{
TheWritableGlobalData->m_replayLocalPlayerCRC = TRUE;

return 1;
}

Int parseXRes(char *args[], int num)
{
if (num > 1)
Expand Down Expand Up @@ -1166,6 +1173,9 @@ static CommandLineParam paramsForEngineInit[] =
// TheSuperHackers @feature xezon 03/08/2025 Force full viewport for 'Control Bar Pro' Addons like GenTool did it.
{ "-forcefullviewport", parseFullViewport },

// TheSuperHackers @feature Caball009 21/06/2026 Validate CRC messages only from the player who recorded a replay.
{ "-replayLocalPlayerCRC", parseReplayLocalPlayerCRC },

#if defined(RTS_DEBUG)
{ "-noaudio", parseNoAudio },
{ "-map", parseMapName },
Expand Down
1 change: 1 addition & 0 deletions GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,7 @@ GlobalData::GlobalData()
m_playSizzle = TRUE;
m_afterIntro = FALSE;
m_allowExitOutOfMovies = FALSE;
m_replayLocalPlayerCRC = FALSE;
m_loadScreenRender = FALSE;

m_keyboardDefaultScrollFactor = m_keyboardScrollFactor = 0.5f;
Expand Down
Loading
Loading