Skip to content
Open
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: 2 additions & 9 deletions Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2393,15 +2393,8 @@ bool GameLogic::onLogicCrc(MAYBE_UNUSED GameMessage *msg)
Player *msgPlayer = getMessagePlayer(msg);
if (TheNetwork)
{
Int slotIndex = -1;
for (Int i=0; i<MAX_SLOTS; ++i)
{
if (msgPlayer->getPlayerType() == PLAYER_HUMAN && TheNetwork->getPlayerName(i) == msgPlayer->getPlayerDisplayName())
{
slotIndex = i;
break;
}
}
// GeneralsX @bugfix felipebraz 05/07/2026 Use pre-computed slot index to avoid string comparisons
Int slotIndex = ThePlayerList->getSlotIndex(msgPlayer->getPlayerIndex());

if (slotIndex < 0 || !TheNetwork->isPlayerConnected(slotIndex))
return false;
Expand Down
5 changes: 5 additions & 0 deletions Generals/Code/GameEngine/Include/Common/PlayerList.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ class PlayerList : public SubsystemInterface,
*/
PlayerMaskType getPlayersWithRelationship( Int srcPlayerIndex, UnsignedInt allowedRelationships );

Byte getSlotIndex(Int playerIndex) const;

protected:

// snapshot methods
Expand All @@ -164,10 +166,13 @@ class PlayerList : public SubsystemInterface,
virtual void loadPostProcess() override;

private:
void resolveSlotIndices();
void setSlotIndex(Int playerIndex, Byte slotIndex);

Player *m_local;
Int m_playerCount;
Player *m_players[MAX_PLAYER_COUNT];
Byte m_slotIndices[MAX_PLAYER_COUNT];

};

Expand Down
53 changes: 51 additions & 2 deletions Generals/Code/GameEngine/Source/Common/RTS/PlayerList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
#endif
#include "GameLogic/SidesList.h"
#include "GameNetwork/NetworkDefs.h"

#include "GameNetwork/GameInfo.h"
#include <algorithm>

//-----------------------------------------------------------------------------
/*extern*/ PlayerList *ThePlayerList = nullptr;
Expand All @@ -69,9 +70,10 @@ PlayerList::PlayerList() :
m_local(nullptr),
m_playerCount(0)
{
// we only allocate a few of these, so don't bother pooling 'em
for (Int i = 0; i < MAX_PLAYER_COUNT; i++)
{
m_players[ i ] = NEW Player( i );
}
init();
}

Expand Down Expand Up @@ -239,6 +241,8 @@ void PlayerList::newGame()
p->setDefaultTeam();
}

// GeneralsX @bugfix felipebraz 05/07/2026 Pre-compute the network slot to player mapping
resolveSlotIndices();
}

//-----------------------------------------------------------------------------
Expand All @@ -250,6 +254,8 @@ void PlayerList::init()
for (int i = 1; i < MAX_PLAYER_COUNT; i++)
m_players[i]->init(nullptr);

std::fill(m_slotIndices, m_slotIndices + MAX_PLAYER_COUNT, -1);

// call setLocalPlayer so that becomingLocalPlayer() gets called appropriately
setLocalPlayer(m_players[0]);

Expand Down Expand Up @@ -495,3 +501,46 @@ void PlayerList::loadPostProcess()

}

//-----------------------------------------------------------------------------
void PlayerList::setSlotIndex(Int playerIndex, Byte slotIndex)
{
if (playerIndex >= 0 && playerIndex < ARRAY_SIZE(m_slotIndices))
{
m_slotIndices[playerIndex] = slotIndex;
}
}

//-----------------------------------------------------------------------------
Byte 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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2379,9 +2379,10 @@ 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))
// GeneralsX @bugfix felipebraz 05/07/2026 Use pre-computed slot index.
const Int slotIndex = ThePlayerList->getSlotIndex(it->first);
if (slotIndex >= 0 && !TheNetwork->isPlayerConnected(slotIndex))
continue;

const UnsignedInt crc = it->second;

if (!hasReferenceCRC)
Expand Down
5 changes: 5 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/PlayerList.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ class PlayerList : public SubsystemInterface,
*/
PlayerMaskType getPlayersWithRelationship( Int srcPlayerIndex, UnsignedInt allowedRelationships );

Byte getSlotIndex(Int playerIndex) const;

protected:

// snapshot methods
Expand All @@ -164,10 +166,13 @@ class PlayerList : public SubsystemInterface,
virtual void loadPostProcess() override;

private:
void resolveSlotIndices();
void setSlotIndex(Int playerIndex, Byte slotIndex);

Player *m_local;
Int m_playerCount;
Player *m_players[MAX_PLAYER_COUNT];
Byte m_slotIndices[MAX_PLAYER_COUNT];

};

Expand Down
54 changes: 52 additions & 2 deletions GeneralsMD/Code/GameEngine/Source/Common/RTS/PlayerList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
#endif
#include "GameLogic/SidesList.h"
#include "GameNetwork/NetworkDefs.h"

#include "GameNetwork/GameInfo.h"
#include <algorithm>

//-----------------------------------------------------------------------------
/*extern*/ PlayerList *ThePlayerList = nullptr;
Expand All @@ -69,9 +70,10 @@ PlayerList::PlayerList() :
m_local(nullptr),
m_playerCount(0)
{
// we only allocate a few of these, so don't bother pooling 'em
for (Int i = 0; i < MAX_PLAYER_COUNT; i++)
{
m_players[ i ] = NEW Player( i );
}
init();
}

Expand Down Expand Up @@ -241,6 +243,8 @@ void PlayerList::newGame()
p->setDefaultTeam();
}

// GeneralsX @bugfix felipebraz 05/07/2026 Pre-compute the network slot to player mapping
resolveSlotIndices();
}

//-----------------------------------------------------------------------------
Expand All @@ -252,6 +256,8 @@ void PlayerList::init()
for (int i = 1; i < MAX_PLAYER_COUNT; i++)
m_players[i]->init(nullptr);

std::fill(m_slotIndices, m_slotIndices + MAX_PLAYER_COUNT, -1);

// call setLocalPlayer so that becomingLocalPlayer() gets called appropriately
setLocalPlayer(m_players[0]);

Expand Down Expand Up @@ -494,6 +500,50 @@ void PlayerList::xfer( Xfer *xfer )
// ------------------------------------------------------------------------------------------------
void PlayerList::loadPostProcess()
{
std::fill(m_slotIndices, m_slotIndices + ARRAY_SIZE(m_slotIndices), 255);
}

//-----------------------------------------------------------------------------
void PlayerList::setSlotIndex(Int playerIndex, Byte slotIndex)
{
if (playerIndex >= 0 && playerIndex < ARRAY_SIZE(m_slotIndices))
{
m_slotIndices[playerIndex] = slotIndex;
}
}

//-----------------------------------------------------------------------------
Byte 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);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -2730,9 +2730,10 @@ 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))
// GeneralsX @bugfix felipebraz 05/07/2026 Use pre-computed slot index.
const Int slotIndex = ThePlayerList->getSlotIndex(it->first);
if (slotIndex >= 0 && !TheNetwork->isPlayerConnected(slotIndex))
continue;

const UnsignedInt crc = it->second;

if (!hasReferenceCRC)
Expand Down
2 changes: 1 addition & 1 deletion GeneralsReplays
Submodule GeneralsReplays updated 30 files
+ Generals/1.08/Maps/Defcon6/Defcon6.map
+ Generals/1.08/Maps/Defcon6/Defcon6.tga
+ Generals/1.08/Maps/Tournament Desert [2024]/Tournament Desert [2024].map
+ Generals/1.08/Maps/Tournament Desert [2024]/Tournament Desert [2024].tga
+ Generals/1.08/Replays/15-00-59_2v6_AKAKIY_umar_HardAI_HardAI_HardAI_HardAI_HardAI_HardAI.rep
+ Generals/1.08/Replays/20-49-07_1v1v1v1v1v1v1_Scotsman_Viking_LoMMiKwA_DooM_Mr_jas_RDR.rep
+ Generals/1.08/Replays/20_17_41_1v1v1v1v1v1_Scotsman_JoKeR_jas_DooM_Viking_mp3.rep
+ Generals/1.08/Replays/20_51_02_2v2v2_mp3_jas_Scotsman_Viking_DooM_JoKeR.rep
+ Generals/1.08/Replays/CW_050307_OoE_Silver_CvC_awesome.rep
+0 −0 GeneralsX/Replays/.gitkeep
+0 −222 GeneralsXZH/Maps/MapCache.ini
+ GeneralsXZH/Replays/macos_2p_custom_map.rep
+ GeneralsXZH/Replays/macos_2p_vanilla_map.rep
+ GeneralsXZH/Replays/macos_6p_custom_map.rep
+ GeneralsZH/1.04/Maps/[RANK] Arctic Arena ZH v1/[RANK] Arctic Arena ZH v1.map
+ GeneralsZH/1.04/Maps/[RANK] Arctic Arena ZH v1/[RANK] Arctic Arena ZH v1.tga
+0 −0 GeneralsZH/1.04/Maps/[RANK] Arctic Arena ZH v1/map.ini
+0 −0 GeneralsZH/1.04/Maps/[RANK] Arctic Arena ZH v1/map.str
+ GeneralsZH/1.04/Maps/tansooo/tansooo.map
+ GeneralsZH/1.04/Maps/tansooo/tansooo.tga
+ GeneralsZH/1.04/Replays/!Golden Replay #1.rep
+ GeneralsZH/1.04/Replays/00-03-45_2v6_PC03_ss_HardAI_HardAI_HardAI_HardAI_HardAI_HardAI.rep
+ GeneralsZH/1.04/Replays/00-31-22_2v2_Derky_DESKTOPJ_HardAI_HardAI.rep
+ GeneralsZH/1.04/Replays/00-41-30_2v2_Nic_BOMD2MAS_HardAI_HardAI.rep
+ GeneralsZH/1.04/Replays/05-01-50_2v2_amoor123_beshr_HardAI_HardAI.rep
+ GeneralsZH/1.04/Replays/11-25-57_2v2_Kana_HardAI_Erbolat_Hulk.rep
+ GeneralsZH/1.04/Replays/12-11-35_2v2_babai_ILnur_HardAI_HardAI.rep
+ GeneralsZH/1.04/Replays/15-07-24_2v2v2_Emkill_haker_HardAI_HardAI_HardAI_HardAI.rep
+ GeneralsZH/1.04/Replays/18-13-02_3v3_Supremac_Loonen_JB_HardAI_HardAI_HardAI.rep
+ GeneralsZH/1.04/Replays/366648.rep
2 changes: 1 addition & 1 deletion references/fbraz3-dxvk
Submodule fbraz3-dxvk updated 1 files
+1 −0 .gitignore
Loading