Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
4 changes: 4 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ class GameSlot

void mute( Bool isMuted ) { m_isMuted = isMuted; }
Bool isMuted( void ) const { return m_isMuted; }

void setPatchVersion(UnsignedInt patchVersion) { m_patchVersion = patchVersion; }
UnsignedInt getPatchVersion() const { return m_patchVersion; }
protected:
SlotState m_state;
Bool m_isAccepted;
Expand All @@ -143,6 +146,7 @@ class GameSlot
FirewallHelperClass::FirewallBehaviorType m_NATBehavior; ///< The NAT behavior for this slot's player.
UnsignedInt m_lastFrameInGame; // only valid for human players
Bool m_disconnected; // only valid for human players
UnsignedInt m_patchVersion; ///< Community made product version
};

/**
Expand Down
20 changes: 20 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ class LANAPI : public LANAPIInterface
void handleGameOptions( LANMessage *msg, UnsignedInt senderIP );
void handleInActive( LANMessage *msg, UnsignedInt senderIP );

void handlePatchInfo(Int messageType, UnsignedInt senderIP, UnicodeString gameName);
void handleGameRequestPatchInfo(LANMessage *msg, UnsignedInt senderIP);
void handleGameAcknowledgePatchInfo(LANMessage *msg, UnsignedInt senderIP);
Copy link

Choose a reason for hiding this comment

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

Is "Acknowledge" synonymous for replying to the request message? Perhaps call it "Response". And add it to the end of the name.

handleGamePatchInfoRequest
handleGamePatchInfoResponse

Even when that breaks the current EA naming pattern, it is a better naming pattern in my opinion.

This comment was marked as outdated.

Copy link
Author

@Caball009 Caball009 Nov 8, 2025

Choose a reason for hiding this comment

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

Is "Acknowledge" synonymous for replying to the request message? Perhaps call it "Response".

Yes, 'Acknowledge' is a response to a patch info request.

Should the enum still contain 'ACKNOWLEDGE'? (e.g. MSG_GAME_ACKNOWLEDGE_PATCH_INFO)
There's also a bunch of comments where I'm currently using the term 'acknowledge'.

Copy link

Choose a reason for hiding this comment

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

I asked Chat what ACK refers to in Networking:

🧩 Definition

In networking, to acknowledge means:

To confirm receipt of data — that a packet, frame, or message has successfully arrived.

So when one device sends data to another, the receiver acknowledges it by sending back a message (an acknowledgment, or ACK) saying essentially:

“I got it — you can send the next one.”

Copy link

Choose a reason for hiding this comment

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

Use ACK terminology only to confirm the receipt of a message, not for a response to a request. When the message is a request and in need of a response, then use the term "Response" for the response.

Copy link
Author

Choose a reason for hiding this comment

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

I have moved away from 'acknowledge' now, except for in a few of the comments.

void handleLobbyRequestPatchInfo(LANMessage *msg, UnsignedInt senderIP);
void handleLobbyAcknowledgePatchInfo(LANMessage *msg, UnsignedInt senderIP);
void handleMatchRequestPatchInfo(LANMessage *msg, UnsignedInt senderIP);
void handleMatchAcknowledgePatchInfo(LANMessage *msg, UnsignedInt senderIP);
};


Expand Down Expand Up @@ -313,6 +320,14 @@ struct LANMessage
MSG_INACTIVE, ///< I've alt-tabbed out. Unaccept me cause I'm a poo-flinging monkey.

MSG_REQUEST_GAME_INFO, ///< For direct connect, get the game info from a specific IP Address

// Community patch
MSG_GAME_REQUEST_PATCH_INFO = 1000,
MSG_GAME_ACKNOWLEDGE_PATCH_INFO,
MSG_LOBBY_REQUEST_PATCH_INFO,
MSG_LOBBY_ACKNOWLEDGE_PATCH_INFO,
MSG_MATCH_REQUEST_PATCH_INFO,
MSG_MATCH_ACKNOWLEDGE_PATCH_INFO,
} messageType;

WideChar name[g_lanPlayerNameLength+1]; ///< My name, for convenience
Expand Down Expand Up @@ -407,6 +422,11 @@ struct LANMessage
char options[m_lanMaxOptionsLength+1];
} GameOptions;

struct
{
WideChar gameName[g_lanGameNameLength + 1];
UnsignedInt patchVersion;
Copy link

Choose a reason for hiding this comment

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

Product Name and Author Name are missing. Probably also needs to send EXE and INI hash, because Product Name and Version are not necessarily unique and hashes need to be part of identifying product.

Copy link
Author

Choose a reason for hiding this comment

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

I think I added all of these, but I'm not yet storing any of the data per player slot.

} PatchInfo;
};
};
#pragma pack(pop)
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ extern const Color chatSystemColor;
extern const Color chatSystemColor;
extern const Color acceptTrueColor;
extern const Color acceptFalseColor;
extern const Color gameColorPatchVersion;
extern const Color gameInProgressColorPatchVersion;
extern const Color playerColorPatchVersion;
extern const Color playerGrayedColorPatchVersion;


void lanUpdateSlotList( void );
Expand Down
5 changes: 4 additions & 1 deletion GeneralsMD/Code/GameEngine/Include/GameNetwork/LANPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
class LANPlayer
{
public:
LANPlayer() { m_name = m_login = m_host = L""; m_lastHeard = 0; m_next = NULL; m_IP = 0; }
LANPlayer() { m_name = m_login = m_host = L""; m_lastHeard = 0; m_next = NULL; m_IP = 0; m_patchVersion = 0; }

// Access functions
inline UnicodeString getName( void ) { return m_name; }
Expand All @@ -52,6 +52,8 @@ class LANPlayer
inline void setNext( LANPlayer *next ) { m_next = next; }
inline UnsignedInt getIP( void ) { return m_IP; }
inline void setIP( UnsignedInt IP ) { m_IP = IP; }
inline void setPatchVersion(UnsignedInt patchVersion) { m_patchVersion = patchVersion; }
inline UnsignedInt getPatchVersion() const { return m_patchVersion; }

protected:
UnicodeString m_name; ///< Player name
Expand All @@ -60,4 +62,5 @@ class LANPlayer
UnsignedInt m_lastHeard; ///< The last time we heard from this player (for timeout purposes)
LANPlayer *m_next; ///< Linked list pointer
UnsignedInt m_IP; ///< Player's IP
UnsignedInt m_patchVersion; ///< Community made product version
};
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "Common/PlayerList.h"
#include "Common/PlayerTemplate.h"
#include "Common/Recorder.h"
#include "Common/version.h"
#include "GameClient/AnimateWindowManager.h"
#include "GameClient/Diplomacy.h"
#include "GameClient/DisconnectMenu.h"
Expand Down Expand Up @@ -532,24 +533,28 @@ void PopulateInGameDiplomacyPopup( void )
if (staticTextStatus[rowNum])
{
staticTextStatus[rowNum]->winHide(FALSE);

Color frontColor = 0;
UnicodeString text;

if (isInGame)
{
if (isAlive)
{
staticTextStatus[rowNum]->winSetEnabledTextColors( aliveColor, backColor );
GadgetStaticTextSetText(staticTextStatus[rowNum], TheGameText->fetch("GUI:PlayerAlive"));
frontColor = aliveColor;
text = TheGameText->fetch("GUI:PlayerAlive");
}
else
{
if (isObserver)
{
staticTextStatus[rowNum]->winSetEnabledTextColors( observerInGameColor, backColor );
GadgetStaticTextSetText(staticTextStatus[rowNum], TheGameText->fetch("GUI:PlayerObserver"));
frontColor = observerInGameColor;
text = TheGameText->fetch("GUI:PlayerObserver");
}
else
{
staticTextStatus[rowNum]->winSetEnabledTextColors( deadColor, backColor );
GadgetStaticTextSetText(staticTextStatus[rowNum], TheGameText->fetch("GUI:PlayerDead"));
frontColor = deadColor;
text = TheGameText->fetch("GUI:PlayerDead");
}
}
}
Expand All @@ -558,15 +563,22 @@ void PopulateInGameDiplomacyPopup( void )
// not in game
if (isObserver)
{
staticTextStatus[rowNum]->winSetEnabledTextColors( observerGoneColor, backColor );
GadgetStaticTextSetText(staticTextStatus[rowNum], TheGameText->fetch("GUI:PlayerObserverGone"));
frontColor = observerGoneColor;
text = TheGameText->fetch("GUI:PlayerObserverGone");
}
else
{
staticTextStatus[rowNum]->winSetEnabledTextColors( goneColor, backColor );
GadgetStaticTextSetText(staticTextStatus[rowNum], TheGameText->fetch("GUI:PlayerGone"));
frontColor = goneColor;
text = TheGameText->fetch("GUI:PlayerGone");
}
}

// TheSuperHackers @feature Caball009 06/11/2025 Set special status for players that are using a patched client version.
if (slot->isHuman() && (TheGameInfo->getLocalSlotNum() == slotNum || slot->getPatchVersion() > 0))
text.format(L"%s [%s]", text.str(), TheVersion->getUnicodeGitTagOrHash().str());

staticTextStatus[rowNum]->winSetEnabledTextColors(frontColor, backColor);
GadgetStaticTextSetText(staticTextStatus[rowNum], text);
}

slotNumInRow[rowNum++] = slotNum;
Expand Down
7 changes: 7 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,13 @@ void UpdateSlotList( GameInfo *myGame, GameWindow *comboPlayer[],
}
if(slot->isHuman())
{
if (i == myGame->getLocalSlotNum() || myGame->getSlot(i)->getPatchVersion() > 0)
{
// TheSuperHackers @feature Caball009 06/11/2025 Set special color for players that are using a patched client version.
GadgetComboBoxSetEnabledTextColors(comboPlayer[i], playerColorPatchVersion, GameMakeColor(0, 0, 0, 255));
GadgetComboBoxSetDisabledTextColors(comboPlayer[i], playerGrayedColorPatchVersion, GameMakeColor(0, 0, 0, 255));
}

UnicodeString newName = slot->getName();
UnicodeString oldName = GadgetComboBoxGetText(comboPlayer[i]);
if (comboPlayer[i] && newName.compare(oldName))
Expand Down
7 changes: 7 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ void GameSlot::reset()
m_origPlayerTemplate = -1;
m_origStartPos = -1;
m_origColor = -1;
m_patchVersion = 0;
}

void GameSlot::saveOffOriginalInfo( void )
Expand Down Expand Up @@ -1484,7 +1485,13 @@ Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options)
//DEBUG_LOG(("ParseAsciiStringToGameInfo - game options all good, setting info"));

for(Int i = 0; i<MAX_SLOTS; i++)
{
// retain the patch version if a slot is still occupied by the same player
if (game->getConstSlot(i)->getState() == SLOT_PLAYER && newSlot[i].getState() == SLOT_PLAYER)
newSlot[i].setPatchVersion(game->getConstSlot(i)->getPatchVersion());

game->setSlot(i,newSlot[i]);
}

game->setMap(mapName);
game->setMapCRC(mapCRC);
Expand Down
20 changes: 20 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,26 @@ void LANAPI::update( void )
handleInActive( msg, senderIP );
break;

// TheSuperHackers @feature Caball009 06/11/2025 Exchange patch information with other players.
case LANMessage::MSG_GAME_REQUEST_PATCH_INFO:
handleGameRequestPatchInfo(msg, senderIP);
break;
case LANMessage::MSG_GAME_ACKNOWLEDGE_PATCH_INFO:
handleGameAcknowledgePatchInfo(msg, senderIP);
break;
case LANMessage::MSG_LOBBY_REQUEST_PATCH_INFO:
handleLobbyRequestPatchInfo(msg, senderIP);
break;
case LANMessage::MSG_LOBBY_ACKNOWLEDGE_PATCH_INFO:
handleLobbyAcknowledgePatchInfo(msg, senderIP);
break;
case LANMessage::MSG_MATCH_REQUEST_PATCH_INFO:
handleMatchRequestPatchInfo(msg, senderIP);
break;
case LANMessage::MSG_MATCH_ACKNOWLEDGE_PATCH_INFO:
handleMatchAcknowledgePatchInfo(msg, senderIP);
break;

default:
DEBUG_LOG(("Unknown LAN message type %d", msg->messageType));
}
Expand Down
28 changes: 17 additions & 11 deletions GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,20 @@ extern Bool LANbuttonPushed;


//Colors used for the chat dialogs
const Color playerColor = GameMakeColor(255,255,255,255);
const Color gameColor = GameMakeColor(255,255,255,255);
const Color gameInProgressColor = GameMakeColor(128,128,128,255);
const Color chatNormalColor = GameMakeColor(50,215,230,255);
const Color chatActionColor = GameMakeColor(255,0,255,255);
const Color chatLocalNormalColor = GameMakeColor(255,128,0,255);
const Color chatLocalActionColor = GameMakeColor(128,255,255,255);
const Color chatSystemColor = GameMakeColor(255,255,255,255);
const Color acceptTrueColor = GameMakeColor(0,255,0,255);
const Color acceptFalseColor = GameMakeColor(255,0,0,255);
const Color playerColor = GameMakeColor(255,255,255,255);
const Color gameColor = GameMakeColor(255,255,255,255);
const Color gameInProgressColor = GameMakeColor(128,128,0,255);
const Color chatNormalColor = GameMakeColor(50,215,230,255);
const Color chatActionColor = GameMakeColor(255,0,255,255);
const Color chatLocalNormalColor = GameMakeColor(255,128,0,255);
const Color chatLocalActionColor = GameMakeColor(128,255,255,255);
const Color chatSystemColor = GameMakeColor(255,255,255,255);
const Color acceptTrueColor = GameMakeColor(0,255,0,255);
const Color acceptFalseColor = GameMakeColor(255,0,0,255);
const Color gameColorPatchVersion = GameMakeColor(255,255,0,255);
const Color gameInProgressColorPatchVersion = GameMakeColor(192,192,0,255);
const Color playerColorPatchVersion = gameColorPatchVersion;
const Color playerGrayedColorPatchVersion = gameInProgressColorPatchVersion;


UnicodeString LANAPIInterface::getErrorStringFromReturnType( ReturnType ret )
Expand Down Expand Up @@ -640,7 +644,9 @@ void LANAPI::OnPlayerList( LANPlayer *playerList )
LANPlayer *player = m_lobbyPlayers;
while (player)
{
Int addedIndex = GadgetListBoxAddEntryText(listboxPlayers, player->getName(), playerColor, -1, -1);
// TheSuperHackers @feature Caball009 06/11/2025 Set special color for players that are using a patched client version.
const Color color = (player->getPatchVersion() > 0 || m_localIP == player->getIP()) ? playerColorPatchVersion : playerColor;
const Int addedIndex = GadgetListBoxAddEntryText(listboxPlayers, player->getName(), color, -1, -1);
GadgetListBoxSetItemData(listboxPlayers, (void *)player->getIP(),addedIndex, 0 );

if (selectedIP == player->getIP())
Expand Down
Loading
Loading