Skip to content

Commit de85be4

Browse files
authored
[GEN][ZH] Fix crash when exiting Replay playback while a player places a beacon (#971)
1 parent 5121f07 commit de85be4

File tree

4 files changed

+56
-10
lines changed

4 files changed

+56
-10
lines changed

Generals/Code/GameEngine/Include/Common/Recorder.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,13 @@ class RecorderClass : public SubsystemInterface {
137137
void writeArgument(GameMessageArgumentDataType type, const GameMessageArgumentType arg);
138138
void readArgument(GameMessageArgumentDataType type, GameMessage *msg);
139139

140-
void cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.
140+
struct CullBadCommandsResult
141+
{
142+
CullBadCommandsResult() : hasClearGameDataMessage(false) {}
143+
Bool hasClearGameDataMessage;
144+
};
145+
146+
CullBadCommandsResult cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.
141147

142148
FILE *m_file;
143149
AsciiString m_fileName;

Generals/Code/GameEngine/Source/Common/Recorder.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,17 @@ void RecorderClass::update() {
439439
* Do the update for the next frame of this playback.
440440
*/
441441
void RecorderClass::updatePlayback() {
442-
cullBadCommands(); // Remove any bad commands that have been inserted by the local user that shouldn't be
443-
// executed during playback.
442+
// Remove any bad commands that have been inserted by the local user that shouldn't be
443+
// executed during playback.
444+
CullBadCommandsResult result = cullBadCommands();
445+
446+
if (result.hasClearGameDataMessage) {
447+
// TheSuperHackers @bugfix Stop appending more commands if the replay playback is about to end.
448+
// Previously this would be able to append more commands, which could have unintended consequences,
449+
// such as crashing the game when a MSG_PLACE_BEACON is appended after MSG_CLEAR_GAME_DATA.
450+
// MSG_CLEAR_GAME_DATA is supposed to be processed later this frame, which will then stop this playback.
451+
return;
452+
}
444453

445454
if (m_nextFrame == -1) {
446455
// This is reached if there are no more commands to be executed.
@@ -1504,9 +1513,11 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
15041513
/**
15051514
* This needs to be called for every frame during playback. Basically it prevents the user from inserting.
15061515
*/
1507-
void RecorderClass::cullBadCommands() {
1516+
RecorderClass::CullBadCommandsResult RecorderClass::cullBadCommands() {
1517+
CullBadCommandsResult result;
1518+
15081519
if (m_doingAnalysis)
1509-
return;
1520+
return result;
15101521

15111522
GameMessage *msg = TheCommandList->getFirstMessage();
15121523
GameMessage *next = NULL;
@@ -1519,9 +1530,15 @@ void RecorderClass::cullBadCommands() {
15191530

15201531
deleteInstance(msg);
15211532
}
1533+
else if (msg->getType() == GameMessage::MSG_CLEAR_GAME_DATA)
1534+
{
1535+
result.hasClearGameDataMessage = true;
1536+
}
15221537

15231538
msg = next;
15241539
}
1540+
1541+
return result;
15251542
}
15261543

15271544
/**

GeneralsMD/Code/GameEngine/Include/Common/Recorder.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,13 @@ class RecorderClass : public SubsystemInterface {
137137
void writeArgument(GameMessageArgumentDataType type, const GameMessageArgumentType arg);
138138
void readArgument(GameMessageArgumentDataType type, GameMessage *msg);
139139

140-
void cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.
140+
struct CullBadCommandsResult
141+
{
142+
CullBadCommandsResult() : hasClearGameDataMessage(false) {}
143+
Bool hasClearGameDataMessage;
144+
};
145+
146+
CullBadCommandsResult cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.
141147

142148
FILE *m_file;
143149
AsciiString m_fileName;

GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,17 @@ void RecorderClass::update() {
439439
* Do the update for the next frame of this playback.
440440
*/
441441
void RecorderClass::updatePlayback() {
442-
cullBadCommands(); // Remove any bad commands that have been inserted by the local user that shouldn't be
443-
// executed during playback.
442+
// Remove any bad commands that have been inserted by the local user that shouldn't be
443+
// executed during playback.
444+
CullBadCommandsResult result = cullBadCommands();
445+
446+
if (result.hasClearGameDataMessage) {
447+
// TheSuperHackers @bugfix Stop appending more commands if the replay playback is about to end.
448+
// Previously this would be able to append more commands, which could have unintended consequences,
449+
// such as crashing the game when a MSG_PLACE_BEACON is appended after MSG_CLEAR_GAME_DATA.
450+
// MSG_CLEAR_GAME_DATA is supposed to be processed later this frame, which will then stop this playback.
451+
return;
452+
}
444453

445454
if (m_nextFrame == -1) {
446455
// This is reached if there are no more commands to be executed.
@@ -1507,9 +1516,11 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
15071516
/**
15081517
* This needs to be called for every frame during playback. Basically it prevents the user from inserting.
15091518
*/
1510-
void RecorderClass::cullBadCommands() {
1519+
RecorderClass::CullBadCommandsResult RecorderClass::cullBadCommands() {
1520+
CullBadCommandsResult result;
1521+
15111522
if (m_doingAnalysis)
1512-
return;
1523+
return result;
15131524

15141525
GameMessage *msg = TheCommandList->getFirstMessage();
15151526
GameMessage *next = NULL;
@@ -1522,9 +1533,15 @@ void RecorderClass::cullBadCommands() {
15221533

15231534
deleteInstance(msg);
15241535
}
1536+
else if (msg->getType() == GameMessage::MSG_CLEAR_GAME_DATA)
1537+
{
1538+
result.hasClearGameDataMessage = true;
1539+
}
15251540

15261541
msg = next;
15271542
}
1543+
1544+
return result;
15281545
}
15291546

15301547
/**

0 commit comments

Comments
 (0)