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
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 @@ -367,6 +367,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_replayOnlyCheckLocalPlayer; ///< flag to check only the CRC messages from the player that 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
64 changes: 60 additions & 4 deletions GeneralsMD/Code/GameEngine/Include/Common/Recorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,61 @@ enum RecorderModeType CPP_11(: Int) {
RECORDERMODETYPE_NONE // this is a valid state to be in on the shell map, or in saved games
};

class CRCInfo;
// TheSuperHackers @info helmutbuhler 03/04/2025
// Some info about CRC:
// In each game, each peer periodically calculates a CRC from the local gamestate and sends that
// in a message to all peers (including itself) so that everyone can check that the crc is synchronous.
// In a network game, there is a delay between sending the CRC message and receiving it. This is
// necessary because if you were to wait each frame for all messages from all peers, things would go
// horribly slow.
// But this delay is not a problem for CRC checking because everyone receives the CRC in the same frame
// and every peer just makes sure all the received CRCs are equal.
// While playing replays, this is a problem however: The CRC messages in the replays appear on the frame
// they were received, which can be a few frames delayed if it was a network game. And if we were to
// compare those with the local gamestate, they wouldn't sync up.
// So, in order to fix this, we need to queue up our local CRCs,
// so that we can check it with the crc messages that come later.
// This class is basically that queue.
class CRCInfo
{
public:
struct MismatchData
{
MismatchData() :
mismatched(FALSE),
playerIndex(0),
queueSize(0),
playbackCRC(0),
playerCRC(0)
{}

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

CRCInfo();
void init(Bool isMultiplayer, Int localPlayerIndex);
void addPlaybackCRC(UnsignedInt val);
void addPlayerCRC(Int playerIndex, UnsignedInt val);
void setSawCRCMismatch();
Bool sawCRCMismatch() const;
Byte getLocalPlayerIndex() const;
MismatchData getMismatchData();

static Int getPlayerIndexOffset();

protected:
UnsignedInt getLargestPlayerQueueSize() const;

Bool m_skippedOne;
Bool m_sawCRCMismatch;
Byte m_localPlayerIndex;
std::list<UnsignedInt> m_playbackData;
std::list<UnsignedInt> m_playerData[MAX_SLOTS];
};

class RecorderClass : public SubsystemInterface {
public:
Expand Down Expand Up @@ -84,10 +138,12 @@ 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();

protected:
CRCInfo *m_crcInfo;
CRCInfo m_crcInfo;
public:

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

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 @@ -312,7 +319,7 @@ class GameLogic : public SubsystemInterface, public Snapshot
// CRC cache system -----------------------------------------------------------------------------
UnsignedInt m_CRC; ///< Cache of previous CRC value
std::map<Int, UnsignedInt> m_cachedCRCs; ///< CRCs we've seen this frame
Bool m_shouldValidateCRCs; ///< Should we validate CRCs this frame?
CRCValidationMode m_shouldValidateCRCs; ///< 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 parseReplayCRC(char* args[], int num)
{
TheWritableGlobalData->m_replayOnlyCheckLocalPlayer = TRUE;

return 1;
}

Int parseXRes(char *args[], int num)
{
if (num > 1)
Expand Down Expand Up @@ -1177,6 +1184,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 24/04/2026 Enable checking only the CRC messages from the player that recorded a replay.
{ "-replayLocalPlayerCRC", parseReplayCRC },

#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 @@ -1009,6 +1009,7 @@ GlobalData::GlobalData()
m_playSizzle = TRUE;
m_afterIntro = FALSE;
m_allowExitOutOfMovies = FALSE;
m_replayOnlyCheckLocalPlayer = FALSE;
m_loadScreenRender = FALSE;

m_keyboardDefaultScrollFactor = m_keyboardScrollFactor = 0.5f;
Expand Down
Loading
Loading