Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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 setProductVersion(UnsignedInt productVersion) { m_productVersion = productVersion; }
UnsignedInt getProductVersion() const { return m_productVersion; }
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_productVersion; ///< Community made product version
};

/**
Expand Down
24 changes: 24 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 @@ -277,6 +278,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 +321,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 +423,14 @@ struct LANMessage
char options[m_lanMaxOptionsLength+1];
} GameOptions;

struct
{
UnsignedInt exeHash;
UnsignedInt iniHash;
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,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->getProductVersion() > 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)->getProductVersion() > 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_productVersion = 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].setProductVersion(game->getConstSlot(i)->getProductVersion());

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

game->setMap(mapName);
game->setMapCRC(mapCRC);
Expand Down
32 changes: 32 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 @@ -1112,6 +1132,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