@@ -53,7 +53,61 @@ enum RecorderModeType CPP_11(: Int) {
5353 RECORDERMODETYPE_NONE // this is a valid state to be in on the shell map, or in saved games
5454};
5555
56- class CRCInfo ;
56+ // TheSuperHackers @info helmutbuhler 03/04/2025
57+ // Some info about CRC:
58+ // In each game, each peer periodically calculates a CRC from the local gamestate and sends that
59+ // in a message to all peers (including itself) so that everyone can check that the crc is synchronous.
60+ // In a network game, there is a delay between sending the CRC message and receiving it. This is
61+ // necessary because if you were to wait each frame for all messages from all peers, things would go
62+ // horribly slow.
63+ // But this delay is not a problem for CRC checking because everyone receives the CRC in the same frame
64+ // and every peer just makes sure all the received CRCs are equal.
65+ // While playing replays, this is a problem however: The CRC messages in the replays appear on the frame
66+ // they were received, which can be a few frames delayed if it was a network game. And if we were to
67+ // compare those with the local gamestate, they wouldn't sync up.
68+ // So, in order to fix this, we need to queue up our local CRCs,
69+ // so that we can check it with the crc messages that come later.
70+ // This class is basically that queue.
71+ class CRCInfo
72+ {
73+ public:
74+ struct MismatchData
75+ {
76+ MismatchData () :
77+ mismatched (FALSE ),
78+ playerIndex (0 ),
79+ queueSize (0 ),
80+ playbackCRC (0 ),
81+ playerCRC (0 )
82+ {}
83+
84+ Bool mismatched;
85+ Byte playerIndex;
86+ UnsignedShort queueSize;
87+ UnsignedInt playbackCRC;
88+ UnsignedInt playerCRC;
89+ };
90+
91+ CRCInfo ();
92+ void init (Bool isMultiplayer, Int localPlayerIndex);
93+ void addPlaybackCRC (UnsignedInt val);
94+ void addPlayerCRC (Int playerIndex, UnsignedInt val);
95+ void setSawCRCMismatch ();
96+ Bool sawCRCMismatch () const ;
97+ Byte getLocalPlayerIndex () const ;
98+ MismatchData getMismatchData ();
99+
100+ static Int getPlayerIndexOffset ();
101+
102+ protected:
103+ UnsignedInt getLargestPlayerQueueSize () const ;
104+
105+ Bool m_skippedOne;
106+ Bool m_sawCRCMismatch;
107+ Byte m_localPlayerIndex;
108+ std::list<UnsignedInt> m_playbackData;
109+ std::list<UnsignedInt> m_playerData[MAX_SLOTS];
110+ };
57111
58112class RecorderClass : public SubsystemInterface {
59113public:
@@ -84,10 +138,12 @@ class RecorderClass : public SubsystemInterface {
84138#endif
85139 Bool isPlaybackInProgress () const ;
86140
87- public:
88- void handleCRCMessage (UnsignedInt newCRC, Int playerIndex, Bool fromPlayback);
141+ void handlePlaybackCRCMessage (UnsignedInt newCRC);
142+ void handlePlayerCRCMessage (Int playerIndex, UnsignedInt newCRC);
143+ void checkForMismatch ();
144+
89145protected:
90- CRCInfo * m_crcInfo;
146+ CRCInfo m_crcInfo;
91147public:
92148
93149 // read in info relating to a replay, conditionally setting up m_file for playback
0 commit comments