diff --git a/Generals/Code/GameEngine/Include/Common/PlayerList.h b/Generals/Code/GameEngine/Include/Common/PlayerList.h index f2c2b3622f7..7b77b205c42 100644 --- a/Generals/Code/GameEngine/Include/Common/PlayerList.h +++ b/Generals/Code/GameEngine/Include/Common/PlayerList.h @@ -150,6 +150,8 @@ class PlayerList : public SubsystemInterface, */ PlayerMaskType getPlayersWithRelationship( Int srcPlayerIndex, UnsignedInt allowedRelationships ); + Int getSlotIndex(Int playerIndex) const; + protected: // snapshot methods @@ -158,10 +160,13 @@ class PlayerList : public SubsystemInterface, virtual void loadPostProcess() override; private: + void resolveSlotIndices(); + void setSlotIndex(Int playerIndex, Int slotIndex); Player *m_local; Int m_playerCount; Player *m_players[MAX_PLAYER_COUNT]; + Int m_slotIndices[MAX_PLAYER_COUNT]; }; diff --git a/Generals/Code/GameEngine/Source/Common/RTS/PlayerList.cpp b/Generals/Code/GameEngine/Source/Common/RTS/PlayerList.cpp index 3aa5b628db3..7881c948205 100644 --- a/Generals/Code/GameEngine/Source/Common/RTS/PlayerList.cpp +++ b/Generals/Code/GameEngine/Source/Common/RTS/PlayerList.cpp @@ -58,9 +58,9 @@ #include "GameLogic/Object.h" #endif #include "GameLogic/SidesList.h" +#include "GameNetwork/GameInfo.h" #include "GameNetwork/NetworkDefs.h" - //----------------------------------------------------------------------------- /*extern*/ PlayerList *ThePlayerList = nullptr; @@ -226,6 +226,7 @@ void PlayerList::newGame() p->setDefaultTeam(); } + resolveSlotIndices(); } //----------------------------------------------------------------------------- @@ -237,6 +238,8 @@ void PlayerList::init() for (int i = 1; i < MAX_PLAYER_COUNT; i++) m_players[i]->init(nullptr); + std::fill(m_slotIndices, m_slotIndices + ARRAY_SIZE(m_slotIndices), -1); + // call setLocalPlayer so that becomingLocalPlayer() gets called appropriately setLocalPlayer(m_players[0]); @@ -383,7 +386,6 @@ Player *PlayerList::getEachPlayerFromMask( PlayerMaskType& maskToAdjust ) return nullptr; // mask not found } - //------------------------------------------------------------------------------------------------- PlayerMaskType PlayerList::getPlayersWithRelationship( Int srcPlayerIndex, UnsignedInt allowedRelationships ) { @@ -479,6 +481,49 @@ void PlayerList::xfer( Xfer *xfer ) // ------------------------------------------------------------------------------------------------ void PlayerList::loadPostProcess() { + std::fill(m_slotIndices, m_slotIndices + ARRAY_SIZE(m_slotIndices), -1); +} +//----------------------------------------------------------------------------- +void PlayerList::setSlotIndex(Int playerIndex, Int slotIndex) +{ + if (playerIndex >= 0 && playerIndex < ARRAY_SIZE(m_slotIndices)) + { + m_slotIndices[playerIndex] = slotIndex; + } } +//----------------------------------------------------------------------------- +Int PlayerList::getSlotIndex(Int playerIndex) const +{ + if (playerIndex >= 0 && playerIndex < ARRAY_SIZE(m_slotIndices)) + { + return m_slotIndices[playerIndex]; + } + + return -1; +} + +//----------------------------------------------------------------------------- +void PlayerList::resolveSlotIndices() +{ + if (!TheGameInfo) + return; + + AsciiString playerName; + + for (Int i = 0; i < MAX_SLOTS; ++i) + { + const GameSlot* slot = TheGameInfo->getSlot(i); + if (!slot || !slot->isOccupied()) + continue; + + playerName.format("player%d", i); + + Player* player = findPlayerWithNameKey(TheNameKeyGenerator->nameToKey(playerName)); + if (player) + { + setSlotIndex(player->getPlayerIndex(), i); + } + } +} diff --git a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index 3ba325d078f..a8b98ea7bba 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -2345,7 +2345,8 @@ void GameLogic::processCommandList( CommandList *list ) { // TheSuperHackers @bugfix Caball009 14/06/2026 Check if player is still connected, // to avoid spurious mismatches at low CRC intervals, e.g. every frame. - if (!TheNetwork->isPlayerConnected(it->first)) + const Int slotIndex = ThePlayerList->getSlotIndex(it->first); + if (slotIndex >= 0 && !TheNetwork->isPlayerConnected(slotIndex)) continue; const UnsignedInt crc = it->second; diff --git a/GeneralsMD/Code/GameEngine/Include/Common/PlayerList.h b/GeneralsMD/Code/GameEngine/Include/Common/PlayerList.h index 8fcbe0a91d9..88051a96758 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/PlayerList.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/PlayerList.h @@ -150,6 +150,8 @@ class PlayerList : public SubsystemInterface, */ PlayerMaskType getPlayersWithRelationship( Int srcPlayerIndex, UnsignedInt allowedRelationships ); + Int getSlotIndex(Int playerIndex) const; + protected: // snapshot methods @@ -158,10 +160,13 @@ class PlayerList : public SubsystemInterface, virtual void loadPostProcess() override; private: + void resolveSlotIndices(); + void setSlotIndex(Int playerIndex, Int slotIndex); Player *m_local; Int m_playerCount; Player *m_players[MAX_PLAYER_COUNT]; + Int m_slotIndices[MAX_PLAYER_COUNT]; }; diff --git a/GeneralsMD/Code/GameEngine/Source/Common/RTS/PlayerList.cpp b/GeneralsMD/Code/GameEngine/Source/Common/RTS/PlayerList.cpp index 177075bc89a..a3c92afb054 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/RTS/PlayerList.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/RTS/PlayerList.cpp @@ -58,9 +58,9 @@ #include "GameLogic/Object.h" #endif #include "GameLogic/SidesList.h" +#include "GameNetwork/GameInfo.h" #include "GameNetwork/NetworkDefs.h" - //----------------------------------------------------------------------------- /*extern*/ PlayerList *ThePlayerList = nullptr; @@ -226,6 +226,7 @@ void PlayerList::newGame() p->setDefaultTeam(); } + resolveSlotIndices(); } //----------------------------------------------------------------------------- @@ -237,6 +238,8 @@ void PlayerList::init() for (int i = 1; i < MAX_PLAYER_COUNT; i++) m_players[i]->init(nullptr); + std::fill(m_slotIndices, m_slotIndices + ARRAY_SIZE(m_slotIndices), -1); + // call setLocalPlayer so that becomingLocalPlayer() gets called appropriately setLocalPlayer(m_players[0]); @@ -383,7 +386,6 @@ Player *PlayerList::getEachPlayerFromMask( PlayerMaskType& maskToAdjust ) return nullptr; // mask not found } - //------------------------------------------------------------------------------------------------- PlayerMaskType PlayerList::getPlayersWithRelationship( Int srcPlayerIndex, UnsignedInt allowedRelationships ) { @@ -479,6 +481,49 @@ void PlayerList::xfer( Xfer *xfer ) // ------------------------------------------------------------------------------------------------ void PlayerList::loadPostProcess() { + std::fill(m_slotIndices, m_slotIndices + ARRAY_SIZE(m_slotIndices), -1); +} +//----------------------------------------------------------------------------- +void PlayerList::setSlotIndex(Int playerIndex, Int slotIndex) +{ + if (playerIndex >= 0 && playerIndex < ARRAY_SIZE(m_slotIndices)) + { + m_slotIndices[playerIndex] = slotIndex; + } } +//----------------------------------------------------------------------------- +Int PlayerList::getSlotIndex(Int playerIndex) const +{ + if (playerIndex >= 0 && playerIndex < ARRAY_SIZE(m_slotIndices)) + { + return m_slotIndices[playerIndex]; + } + + return -1; +} + +//----------------------------------------------------------------------------- +void PlayerList::resolveSlotIndices() +{ + if (!TheGameInfo) + return; + + AsciiString playerName; + + for (Int i = 0; i < MAX_SLOTS; ++i) + { + const GameSlot* slot = TheGameInfo->getSlot(i); + if (!slot || !slot->isOccupied()) + continue; + + playerName.format("player%d", i); + + Player* player = findPlayerWithNameKey(TheNameKeyGenerator->nameToKey(playerName)); + if (player) + { + setSlotIndex(player->getPlayerIndex(), i); + } + } +} diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index debe213997a..b7d16b86e08 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -2671,7 +2671,8 @@ void GameLogic::processCommandList( CommandList *list ) { // TheSuperHackers @bugfix Caball009 14/06/2026 Check if player is still connected, // to avoid spurious mismatches at low CRC intervals, e.g. every frame. - if (!TheNetwork->isPlayerConnected(it->first)) + const Int slotIndex = ThePlayerList->getSlotIndex(it->first); + if (slotIndex >= 0 && !TheNetwork->isPlayerConnected(slotIndex)) continue; const UnsignedInt crc = it->second;