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
3 changes: 1 addition & 2 deletions Core/GameEngine/Include/GameNetwork/NetworkDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,10 @@ extern Int MIN_RUNAHEAD;
extern Int FRAME_DATA_LENGTH;
extern Int FRAMES_TO_KEEP;

// This is the connection numbering: 1-8 are for players, 9 is a broadcast con.
// This is the connection numbering: 1-8 are for players
enum ConnectionNumbers CPP_11(: Int)
{
MAX_PLAYER = 7, // The index of the highest possible player number. This is 0 based, so the most players allowed in a game is MAX_PLAYER+1.
NUM_CONNECTIONS
};

static const Int MAX_SLOTS = MAX_PLAYER+1;
Copy link

@Mauller Mauller Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe MAX_SLOTS should be made unsigned and instances where it is used with an iterator should all be made unsigned int, i noticed there are a few places where a mix of int or unsigned int is used.

And in some instances MAX_SLOT is explicitly cast while in others it's not.
It would be better to clean this up with this change.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow up change

Expand Down
85 changes: 53 additions & 32 deletions Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ ConnectionManager::~ConnectionManager(void)
m_frameData[i] = nullptr;
}

for (i = 0; i < NUM_CONNECTIONS; ++i) {
for (i = 0; i < MAX_SLOTS; ++i) {
deleteInstance(m_connections[i]);
m_connections[i] = nullptr;
}
Expand Down Expand Up @@ -160,7 +160,7 @@ void ConnectionManager::init()
// m_transport->reset();

UnsignedInt i = 0;
for (; i < NUM_CONNECTIONS; ++i) {
for (; i < MAX_SLOTS; ++i) {
m_connections[i] = nullptr;
}

Expand Down Expand Up @@ -236,7 +236,7 @@ void ConnectionManager::reset()
m_transport = nullptr;

UnsignedInt i = 0;
for (; i < (UnsignedInt)NUM_CONNECTIONS; ++i) {
for (; i < (UnsignedInt)MAX_SLOTS; ++i) {
deleteInstance(m_connections[i]);
m_connections[i] = nullptr;
}
Expand Down Expand Up @@ -302,6 +302,7 @@ Int ConnectionManager::getPingsReceived()

Bool ConnectionManager::isPlayerConnected( Int playerID )
{
DEBUG_ASSERTCRASH( playerID < MAX_SLOTS, ("ConnectionManager::isPlayerConnected - %d is an invalid player number", playerID) );
return ( playerID == m_localSlot || (m_connections[playerID] && !m_connections[playerID]->isQuitting()) );
}

Expand Down Expand Up @@ -431,6 +432,10 @@ Bool ConnectionManager::processNetCommand(NetCommandRef *ref) {
}

// Early validation checks
if (msg->getPlayerID() >= MAX_SLOTS) {
return TRUE;
}

if ((m_connections[msg->getPlayerID()] == nullptr) && (msg->getPlayerID() != m_localSlot)) {
// if this is from a player that is no longer in the game, then ignore them.
return TRUE;
Expand All @@ -442,7 +447,7 @@ Bool ConnectionManager::processNetCommand(NetCommandRef *ref) {
return FALSE;
}

if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS) && (msg->getPlayerID() != m_localSlot)) {
if (msg->getPlayerID() != m_localSlot) {
if (m_connections[msg->getPlayerID()] == nullptr) {
return TRUE;
}
Expand Down Expand Up @@ -536,8 +541,8 @@ Bool ConnectionManager::processNetCommand(NetCommandRef *ref) {

void ConnectionManager::processFrameResendRequest(NetFrameResendRequestCommandMsg *msg) {
// first make sure this is a valid slot
Int playerID = msg->getPlayerID();
if ((playerID < 0) || (playerID >= MAX_SLOTS)) {
const UnsignedInt playerID = msg->getPlayerID();
if (playerID >= MAX_SLOTS) {
return;
}

Expand Down Expand Up @@ -601,16 +606,19 @@ void ConnectionManager::processWrapper(NetCommandRef *ref)
*/
void ConnectionManager::processRunAheadMetrics(NetRunAheadMetricsCommandMsg *msg)
{
UnsignedInt player = msg->getPlayerID();
if ((player >= 0) && (player < MAX_SLOTS) && (isPlayerConnected(player))) {
m_latencyAverages[player] = msg->getAverageLatency();
m_fpsAverages[player] = msg->getAverageFps();
const UnsignedInt playerID = msg->getPlayerID();
if (playerID >= MAX_SLOTS) {
return;
}
if (isPlayerConnected(playerID)) {
m_latencyAverages[playerID] = msg->getAverageLatency();
m_fpsAverages[playerID] = msg->getAverageFps();
//DEBUG_LOG(("ConnectionManager::processRunAheadMetrics - player %d, fps = %d, latency = %f", player, msg->getAverageFps(), msg->getAverageLatency()));
if (m_fpsAverages[player] > 100) {
if (m_fpsAverages[playerID] > 100) {
// limit the reported frame rate average to 100. This is done because if a
// user alt-tab's out of the game their frame rate climbs to in the neighborhood of
// 300, that was deemed "ugly" by the powers that be.
m_fpsAverages[player] = 100;
m_fpsAverages[playerID] = 100;
}
}
}
Expand All @@ -619,7 +627,10 @@ void ConnectionManager::processDisconnectChat(NetDisconnectChatCommandMsg *msg)
{
UnicodeString unitext;
UnicodeString name;
UnsignedByte playerID = msg->getPlayerID();
const UnsignedInt playerID = msg->getPlayerID();
if (playerID >= MAX_SLOTS) {
return;
}
if (playerID == m_localSlot) {
name = m_localUser->GetName();
} else if (isPlayerConnected(playerID)) {
Expand All @@ -634,12 +645,15 @@ void ConnectionManager::processChat(NetChatCommandMsg *msg)
{
UnicodeString unitext;
UnicodeString name;
UnsignedByte playerID = msg->getPlayerID();
const UnsignedInt playerID = msg->getPlayerID();
if (playerID >= MAX_SLOTS) {
return;
}
//DEBUG_LOG(("processChat(): playerID = %d", playerID));
if (playerID == m_localSlot) {
name = m_localUser->GetName();
//DEBUG_LOG(("connection is null, using %ls", name.str()));
} else if (((m_connections[playerID] != nullptr) && (m_connections[playerID]->isQuitting() == FALSE))) {
} else if ((m_connections[playerID] != nullptr) && (m_connections[playerID]->isQuitting() == FALSE)) {
name = m_connections[playerID]->getUser()->GetName();
//DEBUG_LOG(("connection is non-null, using %ls", name.str()));
}
Expand Down Expand Up @@ -794,9 +808,14 @@ void ConnectionManager::processFileProgress(NetFileProgressCommandMsg *msg)
{
DEBUG_LOG(("ConnectionManager::processFileProgress() - command %d is at %d%%",
msg->getFileID(), msg->getProgress()));
Int oldProgress = s_fileProgressMap[msg->getPlayerID()][msg->getFileID()];

s_fileProgressMap[msg->getPlayerID()][msg->getFileID()] = max(oldProgress, msg->getProgress());
const UnsignedInt playerID = msg->getPlayerID();
if (playerID >= MAX_SLOTS) {
return;
}
const UnsignedShort fileID = msg->getFileID();
const Int oldProgress = s_fileProgressMap[playerID][fileID];
s_fileProgressMap[playerID][fileID] = max(oldProgress, msg->getProgress());
}

void ConnectionManager::processProgress( NetProgressCommandMsg *msg )
Expand All @@ -820,9 +839,9 @@ void ConnectionManager::processTimeOutGameStart( NetCommandMsg *msg )
void ConnectionManager::processFrameInfo(NetFrameCommandMsg *msg) {
//stupid frame info, why don't you process yourself?

UnsignedInt playerID = msg->getPlayerID();
const UnsignedInt playerID = msg->getPlayerID();

if ((playerID >= 0) && (playerID < MAX_SLOTS)) {
if (playerID < MAX_SLOTS) {
if (m_frameData[playerID] != nullptr) {
// DEBUG_LOG(("ConnectionManager::processFrameInfo - player %d, frame %d, command count %d, received on frame %d", playerID, msg->getExecutionFrame(), msg->getCommandCount(), TheGameLogic->getFrame()));
m_frameData[playerID]->setFrameCommandCount(msg->getExecutionFrame(), msg->getCommandCount());
Expand All @@ -839,7 +858,7 @@ void ConnectionManager::processAckStage1(NetCommandMsg *msg) {
Bool doDebug = (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTFRAME) ? TRUE : FALSE;
#endif

UnsignedByte playerID = msg->getPlayerID();
const UnsignedInt playerID = msg->getPlayerID();
NetCommandRef *ref = nullptr;

#if defined(RTS_DEBUG)
Expand All @@ -848,12 +867,12 @@ void ConnectionManager::processAckStage1(NetCommandMsg *msg) {
}
#endif

if ((playerID >= 0) && (playerID < NUM_CONNECTIONS)) {
if (playerID < MAX_SLOTS) {
if (m_connections[playerID] != nullptr) {
ref = m_connections[playerID]->processAck(msg);
}
} else {
DEBUG_ASSERTCRASH((playerID >= 0) && (playerID < NUM_CONNECTIONS), ("ConnectionManager::processAck - %d is an invalid player number", playerID));
DEBUG_CRASH(("ConnectionManager::processAck - %d is an invalid player number", playerID));
}

if (ref != nullptr) {
Expand Down Expand Up @@ -1073,7 +1092,7 @@ void ConnectionManager::ackCommand(NetCommandRef *ref, UnsignedInt localSlot) {

if (CommandRequiresDirectSend(msg) && CommandRequiresAck(msg)) {
// Send this ack directly back to the sending player, don't go through the packet router.
if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS)) {
if (msg->getPlayerID() < MAX_SLOTS) {
if (m_connections[msg->getPlayerID()] != nullptr) {
m_connections[msg->getPlayerID()]->sendNetCommandMsg(ackmsg, 1 << msg->getPlayerID());
}
Expand All @@ -1086,21 +1105,21 @@ void ConnectionManager::ackCommand(NetCommandRef *ref, UnsignedInt localSlot) {
m_connections[m_packetRouterSlot]->sendNetCommandMsg(ackmsg, 1 << m_packetRouterSlot);
} else if (m_localSlot == m_packetRouterSlot) {
// we are the packet router, send the ack to the player that sent the command.
if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS)) {
if (msg->getPlayerID() < MAX_SLOTS) {
if (m_connections[msg->getPlayerID()] != nullptr) {
// DEBUG_LOG(("ConnectionManager::ackCommand - acking command %d from player %d directly to player.", commandID, msg->getPlayerID()));
m_connections[msg->getPlayerID()]->sendNetCommandMsg(ackmsg, 1 << msg->getPlayerID());
} else {
// DEBUG_ASSERTCRASH(m_connections[msg->getPlayerID()] != nullptr, ("Connection to player is null"));
// DEBUG_CRASH(("Connection to player is null"));
}
} else {
DEBUG_ASSERTCRASH((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS), ("Command sent by an invalid player ID."));
DEBUG_CRASH(("Command sent by an invalid player ID."));
}
} else {
DEBUG_ASSERTCRASH(m_connections[m_packetRouterSlot] != nullptr, ("Connection to packet router is null"));
DEBUG_CRASH(("Connection to packet router is null"));
}
} else {
DEBUG_ASSERTCRASH((m_packetRouterSlot >= 0) && (m_packetRouterSlot < MAX_SLOTS), ("I don't know who the packet router is."));
DEBUG_CRASH(("I don't know who the packet router is."));
}
}

Expand All @@ -1120,11 +1139,13 @@ void ConnectionManager::sendRemoteCommand(NetCommandRef *msg) {
DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendRemoteCommand - sending net command %d of type %s from player %d, relay is 0x%x",
msg->getCommand()->getID(), GetNetCommandTypeAsString(msg->getCommand()->getNetCommandType()), msg->getCommand()->getPlayerID(), msg->getRelay()));

UnsignedByte relay = msg->getRelay();
if ((relay & (1 << m_localSlot)) && (m_frameData[msg->getCommand()->getPlayerID()] != nullptr)) {
const UnsignedByte relay = msg->getRelay();
const UnsignedInt playerID = msg->getCommand()->getPlayerID();
FrameDataManager *frameDataMgr = playerID < MAX_SLOTS ? m_frameData[playerID] : nullptr;
if ((relay & (1 << m_localSlot)) && (frameDataMgr != nullptr)) {
if (IsCommandSynchronized(msg->getCommand()->getNetCommandType())) {
DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendRemoteCommand - adding net command of type %s to player %d for frame %d", GetNetCommandTypeAsString(msg->getCommand()->getNetCommandType()), msg->getCommand()->getPlayerID(), msg->getCommand()->getExecutionFrame()));
m_frameData[msg->getCommand()->getPlayerID()]->addNetCommandMsg(msg->getCommand());
frameDataMgr->addNetCommandMsg(msg->getCommand());
}
}

Expand Down Expand Up @@ -1190,7 +1211,7 @@ void ConnectionManager::update(Bool isInGame) {
// send any necessary keep-alive packets.
doKeepAlive();

for (Int i = 0; i < NUM_CONNECTIONS; ++i) {
for (Int i = 0; i < MAX_SLOTS; ++i) {
if (m_connections[i] != nullptr) {
/*
if (m_connections[i]->isQueueEmpty() == FALSE) {
Expand Down
8 changes: 6 additions & 2 deletions Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,11 @@ void DisconnectManager::processDisconnectVote(NetCommandMsg *msg, ConnectionMana

void DisconnectManager::processDisconnectFrame(NetCommandMsg *msg, ConnectionManager *conMgr) {
NetDisconnectFrameCommandMsg *cmdMsg = (NetDisconnectFrameCommandMsg *)msg;
UnsignedInt playerID = cmdMsg->getPlayerID();
const UnsignedInt playerID = cmdMsg->getPlayerID();
if (playerID >= MAX_SLOTS) {
return;
}

if (m_disconnectFrames[playerID] >= cmdMsg->getDisconnectFrame()) {
// this message isn't valid, we have a disconnect frame that is later than this already.
return;
Expand Down Expand Up @@ -415,7 +419,7 @@ void DisconnectManager::processDisconnectScreenOff(NetCommandMsg *msg, Connectio

DEBUG_LOG(("DisconnectManager::processDisconnectScreenOff - got a screen off command from player %d for frame %d", cmdMsg->getPlayerID(), cmdMsg->getNewFrame()));

if ((playerID < 0) || (playerID >= MAX_SLOTS)) {
if (playerID >= MAX_SLOTS) {
return;
}

Expand Down
Loading