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
11 changes: 8 additions & 3 deletions Generals/Code/GameEngine/Source/Common/Recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1149,16 +1149,21 @@ Bool RecorderClass::playbackFile(AsciiString filename)
}
#endif

Bool isMultiplayer = m_gameInfo.getSlot(header.localPlayerIndex)->getIP() != 0;
m_crcInfo = CRCInfo(header.localPlayerIndex, isMultiplayer);
REPLAY_CRC_INTERVAL = m_gameInfo.getCRCInterval();
DEBUG_LOG(("Player index is %d, replay CRC interval is %d", m_crcInfo.getLocalPlayer(), REPLAY_CRC_INTERVAL));

Int difficulty = 0;
m_file->read(&difficulty, sizeof(difficulty));

m_file->read(&m_originalGameMode, sizeof(m_originalGameMode));

// TheSuperHackers @bugfix bobtista 30/08/2026 A replay header is allowed to carry a local player
// index of -1 and getSlot returns NULL for it, so reading the slot to tell a network game from a
// local one dereferenced NULL. The recorded game mode answers the same question directly, so the
// crc queue is now primed from the mode and the local slot is no longer read here.
const Bool isMultiplayer = m_originalGameMode == GAME_LAN || m_originalGameMode == GAME_INTERNET;
m_crcInfo = CRCInfo(header.localPlayerIndex, isMultiplayer);
DEBUG_LOG(("Player index is %d, replay CRC interval is %d", m_crcInfo.getLocalPlayer(), REPLAY_CRC_INTERVAL));

Int rankPoints = 0;
m_file->read(&rankPoints, sizeof(rankPoints));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1315,7 +1315,11 @@ void GameLogic::tryStartNewGame( Bool loadingSaveGame )
d.setInt(TheKey_multiplayerStartIndex, slot->getStartPos());
// d.setBool(TheKey_multiplayerIsLocal, slot->isLocalPlayer());
// d.setBool(TheKey_multiplayerIsLocal, slot->getIP() == game->getLocalIP());
d.setBool(TheKey_multiplayerIsLocal, slot->isHuman() && (slot->getName().compare(TheGameInfo->getSlot(TheGameInfo->getLocalSlotNum())->getName().str()) == 0));
// TheSuperHackers @bugfix bobtista 30/08/2026 A replay recorded without a local player has no
// local slot number and getSlot returns NULL for it, so no slot can be the local one.
const Int localSlotNum = TheGameInfo->getLocalSlotNum();
const GameSlot *localGameSlot = localSlotNum >= 0 ? TheGameInfo->getSlot(localSlotNum) : nullptr;
d.setBool(TheKey_multiplayerIsLocal, slot->isHuman() && localGameSlot != nullptr && (slot->getName().compare(localGameSlot->getName().str()) == 0));

/*
if (slot->getIP() == game->getLocalIP())
Expand Down
11 changes: 8 additions & 3 deletions GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1152,16 +1152,21 @@ Bool RecorderClass::playbackFile(AsciiString filename)
}
#endif

Bool isMultiplayer = m_gameInfo.getSlot(header.localPlayerIndex)->getIP() != 0;
m_crcInfo = CRCInfo(header.localPlayerIndex, isMultiplayer);
REPLAY_CRC_INTERVAL = m_gameInfo.getCRCInterval();
DEBUG_LOG(("Player index is %d, replay CRC interval is %d", m_crcInfo.getLocalPlayer(), REPLAY_CRC_INTERVAL));

Int difficulty = 0;
m_file->read(&difficulty, sizeof(difficulty));

m_file->read(&m_originalGameMode, sizeof(m_originalGameMode));

// TheSuperHackers @bugfix bobtista 30/08/2026 A replay header is allowed to carry a local player
// index of -1 and getSlot returns NULL for it, so reading the slot to tell a network game from a
// local one dereferenced NULL. The recorded game mode answers the same question directly, so the
// crc queue is now primed from the mode and the local slot is no longer read here.
const Bool isMultiplayer = m_originalGameMode == GAME_LAN || m_originalGameMode == GAME_INTERNET;
m_crcInfo = CRCInfo(header.localPlayerIndex, isMultiplayer);
DEBUG_LOG(("Player index is %d, replay CRC interval is %d", m_crcInfo.getLocalPlayer(), REPLAY_CRC_INTERVAL));

Int rankPoints = 0;
m_file->read(&rankPoints, sizeof(rankPoints));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1476,7 +1476,11 @@ void GameLogic::tryStartNewGame( Bool loadingSaveGame )
d.setInt(TheKey_multiplayerStartIndex, slot->getStartPos());
// d.setBool(TheKey_multiplayerIsLocal, slot->isLocalPlayer());
// d.setBool(TheKey_multiplayerIsLocal, slot->getIP() == game->getLocalIP());
d.setBool(TheKey_multiplayerIsLocal, slot->isHuman() && (slot->getName().compare(TheGameInfo->getSlot(TheGameInfo->getLocalSlotNum())->getName().str()) == 0));
// TheSuperHackers @bugfix bobtista 30/08/2026 A replay recorded without a local player has no
// local slot number and getSlot returns NULL for it, so no slot can be the local one.
const Int localSlotNum = TheGameInfo->getLocalSlotNum();
const GameSlot *localGameSlot = localSlotNum >= 0 ? TheGameInfo->getSlot(localSlotNum) : nullptr;
d.setBool(TheKey_multiplayerIsLocal, slot->isHuman() && localGameSlot != nullptr && (slot->getName().compare(localGameSlot->getName().str()) == 0));

/*
if (slot->getIP() == game->getLocalIP())
Expand Down
Loading