Skip to content
Merged
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
8 changes: 7 additions & 1 deletion Generals/Code/GameEngine/Include/Common/Recorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,13 @@ class RecorderClass : public SubsystemInterface {
void writeArgument(GameMessageArgumentDataType type, const GameMessageArgumentType arg);
void readArgument(GameMessageArgumentDataType type, GameMessage *msg);

void cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.
struct CullBadCommandsResult
{
CullBadCommandsResult() : hasClearGameDataMessage(false) {}
Bool hasClearGameDataMessage;
};

CullBadCommandsResult cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.

FILE *m_file;
AsciiString m_fileName;
Expand Down
25 changes: 21 additions & 4 deletions Generals/Code/GameEngine/Source/Common/Recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,17 @@ void RecorderClass::update() {
* Do the update for the next frame of this playback.
*/
void RecorderClass::updatePlayback() {
cullBadCommands(); // Remove any bad commands that have been inserted by the local user that shouldn't be
// executed during playback.
// Remove any bad commands that have been inserted by the local user that shouldn't be
// executed during playback.
CullBadCommandsResult result = cullBadCommands();

if (result.hasClearGameDataMessage) {
// TheSuperHackers @bugfix Stop appending more commands if the replay playback is about to end.
// Previously this would be able to append more commands, which could have unintended consequences,
// such as crashing the game when a MSG_PLACE_BEACON is appended after MSG_CLEAR_GAME_DATA.
// MSG_CLEAR_GAME_DATA is supposed to be processed later this frame, which will then stop this playback.
return;
}

if (m_nextFrame == -1) {
// This is reached if there are no more commands to be executed.
Expand Down Expand Up @@ -1501,9 +1510,11 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
/**
* This needs to be called for every frame during playback. Basically it prevents the user from inserting.
*/
void RecorderClass::cullBadCommands() {
RecorderClass::CullBadCommandsResult RecorderClass::cullBadCommands() {
CullBadCommandsResult result;

if (m_doingAnalysis)
return;
return result;

GameMessage *msg = TheCommandList->getFirstMessage();
GameMessage *next = NULL;
Expand All @@ -1516,9 +1527,15 @@ void RecorderClass::cullBadCommands() {

deleteInstance(msg);
}
else if (msg->getType() == GameMessage::MSG_CLEAR_GAME_DATA)
{
result.hasClearGameDataMessage = true;
}

msg = next;
}

return result;
}

/**
Expand Down
8 changes: 7 additions & 1 deletion GeneralsMD/Code/GameEngine/Include/Common/Recorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,13 @@ class RecorderClass : public SubsystemInterface {
void writeArgument(GameMessageArgumentDataType type, const GameMessageArgumentType arg);
void readArgument(GameMessageArgumentDataType type, GameMessage *msg);

void cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.
struct CullBadCommandsResult
{
CullBadCommandsResult() : hasClearGameDataMessage(false) {}
Bool hasClearGameDataMessage;
};

CullBadCommandsResult cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.

FILE *m_file;
AsciiString m_fileName;
Expand Down
25 changes: 21 additions & 4 deletions GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,17 @@ void RecorderClass::update() {
* Do the update for the next frame of this playback.
*/
void RecorderClass::updatePlayback() {
cullBadCommands(); // Remove any bad commands that have been inserted by the local user that shouldn't be
// executed during playback.
// Remove any bad commands that have been inserted by the local user that shouldn't be
// executed during playback.
CullBadCommandsResult result = cullBadCommands();

if (result.hasClearGameDataMessage) {
// TheSuperHackers @bugfix Stop appending more commands if the replay playback is about to end.
// Previously this would be able to append more commands, which could have unintended consequences,
// such as crashing the game when a MSG_PLACE_BEACON is appended after MSG_CLEAR_GAME_DATA.
// MSG_CLEAR_GAME_DATA is supposed to be processed later this frame, which will then stop this playback.
return;
}

if (m_nextFrame == -1) {
// This is reached if there are no more commands to be executed.
Expand Down Expand Up @@ -1504,9 +1513,11 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
/**
* This needs to be called for every frame during playback. Basically it prevents the user from inserting.
*/
void RecorderClass::cullBadCommands() {
RecorderClass::CullBadCommandsResult RecorderClass::cullBadCommands() {
CullBadCommandsResult result;

if (m_doingAnalysis)
return;
return result;

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

deleteInstance(msg);
}
else if (msg->getType() == GameMessage::MSG_CLEAR_GAME_DATA)
{
result.hasClearGameDataMessage = true;
}

msg = next;
}

return result;
}

/**
Expand Down
Loading