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
13 changes: 13 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ enum
class GameSlot
{
public:
struct ProductInfo
{
UnsignedInt exeCRC;
UnsignedInt iniCRC;
UnsignedInt productVersion;
AsciiString gitTagOrHash;
UnicodeString productName;
};

GameSlot();
virtual void reset();

Expand Down Expand Up @@ -125,6 +134,9 @@ class GameSlot

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

void setProductInfo(const ProductInfo& productInfo) { m_productInfo = productInfo; }
const ProductInfo& getProductInfo() const { return m_productInfo; }
protected:
SlotState m_state;
Bool m_isAccepted;
Expand All @@ -143,6 +155,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
ProductInfo m_productInfo; ///< Community made product information
};

/**
Expand Down
27 changes: 27 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ class LANAPI : public LANAPIInterface
// Misc utility functions
virtual LANGameInfo * LookupGame( UnicodeString gameName ); ///< return a pointer to a game we know about
virtual LANGameInfo * LookupGameByListOffset( Int offset ); ///< return a pointer to a game we know about
virtual LANGameInfo * LookupGameByHost( UnsignedInt hostIP ); ///< return a pointer to a game we know about
virtual LANPlayer * LookupPlayer( UnsignedInt playerIP ); ///< return a pointer to a player we know about
virtual Bool SetLocalIP( UnsignedInt localIP ); ///< For multiple NIC machines
virtual void SetLocalIP( AsciiString localIP ); ///< For multiple NIC machines
Expand Down Expand Up @@ -259,6 +260,9 @@ class LANAPI : public LANAPIInterface
void addGame(LANGameInfo *game);
AsciiString createSlotString( void );

void setProductInfoFromLocalData(GameSlot *slot);
void setProductInfoFromMessage(LANMessage *msg, GameSlot *slot);

// Functions to handle incoming messages -----------------------------------
void handleRequestLocations( LANMessage *msg, UnsignedInt senderIP );
void handleGameAnnounce( LANMessage *msg, UnsignedInt senderIP );
Expand All @@ -277,6 +281,13 @@ class LANAPI : public LANAPIInterface
void handleGameOptions( LANMessage *msg, UnsignedInt senderIP );
void handleInActive( LANMessage *msg, UnsignedInt senderIP );

void sendProductInfoMessage(Int messageType, UnsignedInt senderIP);
void handleGameProductInfoRequest(LANMessage *msg, UnsignedInt senderIP);
void handleGameProductInfoResponse(LANMessage *msg, UnsignedInt senderIP);
void handleLobbyProductInfoRequest(LANMessage *msg, UnsignedInt senderIP);
void handleLobbyProductInfoResponse(LANMessage *msg, UnsignedInt senderIP);
void handleMatchProductInfoRequest(LANMessage *msg, UnsignedInt senderIP);
void handleMatchProductInfoResponse(LANMessage *msg, UnsignedInt senderIP);
};


Expand Down Expand Up @@ -313,6 +324,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 Product
MSG_GAME_REQUEST_PRODUCT_INFO = 1000,
MSG_GAME_RESPONSE_PRODUCT_INFO,
MSG_LOBBY_REQUEST_PRODUCT_INFO,
MSG_LOBBY_RESPONSE_PRODUCT_INFO,
MSG_MATCH_REQUEST_PRODUCT_INFO,
MSG_MATCH_RESPONSE_PRODUCT_INFO,
} messageType;

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

struct
{
UnsignedInt exeCRC;
UnsignedInt iniCRC;
UnsignedInt productVersion;
Char gitTagOrHash[33];
WideChar productName[129];
} ProductInfo;
Copy link
Author

Choose a reason for hiding this comment

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

This struct is kind of work-in-progress for now, but eventually any string sizes should be named like in the other structs.

};
};
#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_productVersion = 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 setProductVersion(UnsignedInt productVersion) { m_productVersion = productVersion; }
inline UnsignedInt getProductVersion() const { return m_productVersion; }

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_productVersion; ///< 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,27 @@ 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() && slot->getProductInfo().productVersion > 0)
{
UnicodeString gitTagOrHash;
gitTagOrHash.translate(slot->getProductInfo().gitTagOrHash);

text.format(L"%s [%s]", text.str(), gitTagOrHash.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 (myGame->getSlot(i)->getProductInfo().productVersion > 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_productInfo = ProductInfo();
}

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 product information if a slot is still occupied by the same player
if (game->getConstSlot(i)->getState() == SLOT_PLAYER && newSlot[i].getState() == SLOT_PLAYER)
newSlot[i].setProductInfo(game->getConstSlot(i)->getProductInfo());

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

game->setMap(mapName);
game->setMapCRC(mapCRC);
Expand Down
35 changes: 35 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 product information with other players.
case LANMessage::MSG_GAME_REQUEST_PRODUCT_INFO:
handleGameProductInfoRequest(msg, senderIP);
break;
case LANMessage::MSG_GAME_RESPONSE_PRODUCT_INFO:
handleGameProductInfoResponse(msg, senderIP);
break;
case LANMessage::MSG_LOBBY_REQUEST_PRODUCT_INFO:
handleLobbyProductInfoRequest(msg, senderIP);
break;
case LANMessage::MSG_LOBBY_RESPONSE_PRODUCT_INFO:
handleLobbyProductInfoResponse(msg, senderIP);
break;
case LANMessage::MSG_MATCH_REQUEST_PRODUCT_INFO:
handleMatchProductInfoRequest(msg, senderIP);
break;
case LANMessage::MSG_MATCH_RESPONSE_PRODUCT_INFO:
handleMatchProductInfoResponse(msg, senderIP);
break;

default:
DEBUG_LOG(("Unknown LAN message type %d", msg->messageType));
}
Expand Down Expand Up @@ -906,6 +926,9 @@ void LANAPI::RequestGameCreate( UnicodeString gameName, Bool isDirectConnect )
newSlot.setLogin(m_userName);
newSlot.setHost(m_hostName);

// set product information for local game slot
setProductInfoFromLocalData(&newSlot);

myGame->setSlot(0,newSlot);
myGame->setNext(NULL);
LANPreferences pref;
Expand Down Expand Up @@ -1112,6 +1135,18 @@ LANGameInfo * LANAPI::LookupGameByListOffset( Int offset )
return theGame; // NULL means we didn't find anything.
}

LANGameInfo * LANAPI::LookupGameByHost( UnsignedInt hostIP )
{
LANGameInfo* theGame = m_games;

while (theGame && theGame->getHostIP() != hostIP)
{
theGame = theGame->getNext();
}

return theGame; // NULL means we didn't find anything.
}

void LANAPI::removeGame( LANGameInfo *game )
{
LANGameInfo *g = m_games;
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->getProductVersion() > 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