Skip to content

Commit f066518

Browse files
committed
feat(network): Exchange client patch identification
1 parent e2385c5 commit f066518

File tree

6 files changed

+161
-1
lines changed

6 files changed

+161
-1
lines changed

GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ class GameSlot
125125

126126
void mute( Bool isMuted ) { m_isMuted = isMuted; }
127127
Bool isMuted( void ) const { return m_isMuted; }
128+
129+
void setPatchVersion(UnsignedInt patchVersion) { m_patchVersion = patchVersion; }
130+
UnsignedInt getPatchVersion() const { return m_patchVersion; }
128131
protected:
129132
SlotState m_state;
130133
Bool m_isAccepted;
@@ -143,6 +146,7 @@ class GameSlot
143146
FirewallHelperClass::FirewallBehaviorType m_NATBehavior; ///< The NAT behavior for this slot's player.
144147
UnsignedInt m_lastFrameInGame; // only valid for human players
145148
Bool m_disconnected; // only valid for human players
149+
UnsignedInt m_patchVersion; ///< Community made product version
146150
};
147151

148152
/**

GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,13 @@ class LANAPI : public LANAPIInterface
277277
void handleGameOptions( LANMessage *msg, UnsignedInt senderIP );
278278
void handleInActive( LANMessage *msg, UnsignedInt senderIP );
279279

280+
void handlePatchInfo(Int messageType, UnsignedInt senderIP, UnicodeString gameName);
281+
void handleGameRequestPatchInfo(LANMessage *msg, UnsignedInt senderIP);
282+
void handleGameAcknowledgePatchInfo(LANMessage *msg, UnsignedInt senderIP);
283+
void handleLobbyRequestPatchInfo(LANMessage *msg, UnsignedInt senderIP);
284+
void handleLobbyAcknowledgePatchInfo(LANMessage *msg, UnsignedInt senderIP);
285+
void handleMatchRequestPatchInfo(LANMessage *msg, UnsignedInt senderIP);
286+
void handleMatchAcknowledgePatchInfo(LANMessage *msg, UnsignedInt senderIP);
280287
};
281288

282289

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

315322
MSG_REQUEST_GAME_INFO, ///< For direct connect, get the game info from a specific IP Address
323+
324+
// Community patch
325+
MSG_GAME_REQUEST_PATCH_INFO = 1000,
326+
MSG_GAME_ACKNOWLEDGE_PATCH_INFO,
327+
MSG_LOBBY_REQUEST_PATCH_INFO,
328+
MSG_LOBBY_ACKNOWLEDGE_PATCH_INFO,
329+
MSG_MATCH_REQUEST_PATCH_INFO,
330+
MSG_MATCH_ACKNOWLEDGE_PATCH_INFO,
316331
} messageType;
317332

318333
WideChar name[g_lanPlayerNameLength+1]; ///< My name, for convenience
@@ -407,6 +422,11 @@ struct LANMessage
407422
char options[m_lanMaxOptionsLength+1];
408423
} GameOptions;
409424

425+
struct
426+
{
427+
WideChar gameName[g_lanGameNameLength + 1];
428+
UnsignedInt patchVersion;
429+
} PatchInfo;
410430
};
411431
};
412432
#pragma pack(pop)

GeneralsMD/Code/GameEngine/Include/GameNetwork/LANPlayer.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
class LANPlayer
3636
{
3737
public:
38-
LANPlayer() { m_name = m_login = m_host = L""; m_lastHeard = 0; m_next = NULL; m_IP = 0; }
38+
LANPlayer() { m_name = m_login = m_host = L""; m_lastHeard = 0; m_next = NULL; m_IP = 0; m_patchVersion = 0; }
3939

4040
// Access functions
4141
inline UnicodeString getName( void ) { return m_name; }
@@ -52,6 +52,8 @@ class LANPlayer
5252
inline void setNext( LANPlayer *next ) { m_next = next; }
5353
inline UnsignedInt getIP( void ) { return m_IP; }
5454
inline void setIP( UnsignedInt IP ) { m_IP = IP; }
55+
inline void setPatchVersion(UnsignedInt patchVersion) { m_patchVersion = patchVersion; }
56+
inline UnsignedInt getPatchVersion() const { return m_patchVersion; }
5557

5658
protected:
5759
UnicodeString m_name; ///< Player name
@@ -60,4 +62,5 @@ class LANPlayer
6062
UnsignedInt m_lastHeard; ///< The last time we heard from this player (for timeout purposes)
6163
LANPlayer *m_next; ///< Linked list pointer
6264
UnsignedInt m_IP; ///< Player's IP
65+
UnsignedInt m_patchVersion; ///< Community made product version
6366
};

GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ void GameSlot::reset()
7373
m_origPlayerTemplate = -1;
7474
m_origStartPos = -1;
7575
m_origColor = -1;
76+
m_patchVersion = 0;
7677
}
7778

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

14861487
for(Int i = 0; i<MAX_SLOTS; i++)
1488+
{
1489+
// retain the patch version if a slot is still occupied by the same player
1490+
if (game->getConstSlot(i)->getState() == SLOT_PLAYER && newSlot[i].getState() == SLOT_PLAYER)
1491+
newSlot[i].setPatchVersion(game->getConstSlot(i)->getPatchVersion());
1492+
14871493
game->setSlot(i,newSlot[i]);
1494+
}
14881495

14891496
game->setMap(mapName);
14901497
game->setMapCRC(mapCRC);

GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,26 @@ void LANAPI::update( void )
425425
handleInActive( msg, senderIP );
426426
break;
427427

428+
// TheSuperHackers @feature Caball009 06/11/2025 Exchange patch information with other players.
429+
case LANMessage::MSG_GAME_REQUEST_PATCH_INFO:
430+
handleGameRequestPatchInfo(msg, senderIP);
431+
break;
432+
case LANMessage::MSG_GAME_ACKNOWLEDGE_PATCH_INFO:
433+
handleGameAcknowledgePatchInfo(msg, senderIP);
434+
break;
435+
case LANMessage::MSG_LOBBY_REQUEST_PATCH_INFO:
436+
handleLobbyRequestPatchInfo(msg, senderIP);
437+
break;
438+
case LANMessage::MSG_LOBBY_ACKNOWLEDGE_PATCH_INFO:
439+
handleLobbyAcknowledgePatchInfo(msg, senderIP);
440+
break;
441+
case LANMessage::MSG_MATCH_REQUEST_PATCH_INFO:
442+
handleMatchRequestPatchInfo(msg, senderIP);
443+
break;
444+
case LANMessage::MSG_MATCH_ACKNOWLEDGE_PATCH_INFO:
445+
handleMatchAcknowledgePatchInfo(msg, senderIP);
446+
break;
447+
428448
default:
429449
DEBUG_LOG(("Unknown LAN message type %d", msg->messageType));
430450
}

GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,107 @@
3636
#include "Common/GlobalData.h"
3737
#include "Common/QuotedPrintable.h"
3838
#include "Common/UserPreferences.h"
39+
#include "Common/version.h"
3940
#include "GameNetwork/LANAPI.h"
4041
#include "GameNetwork/LANAPICallbacks.h"
4142
#include "GameClient/MapUtil.h"
4243

44+
void LANAPI::handlePatchInfo(Int messageType, UnsignedInt senderIP, UnicodeString gameName)
45+
{
46+
LANMessage msg;
47+
fillInLANMessage(&msg);
48+
msg.messageType = (LANMessage::Type)messageType;
49+
wcslcpy(msg.PatchInfo.gameName, gameName.str(), ARRAY_SIZE(msg.PatchInfo.gameName));
50+
msg.PatchInfo.patchVersion = TheVersion->getVersionNumber();
51+
52+
sendMessage(&msg, senderIP);
53+
}
54+
55+
void LANAPI::handleGameRequestPatchInfo(LANMessage *msg, UnsignedInt senderIP)
56+
{
57+
if (!AmIHost())
58+
return;
59+
60+
// acknowledge as game host a request for patch information by a player in the lobby
61+
handlePatchInfo(LANMessage::MSG_GAME_ACKNOWLEDGE_PATCH_INFO, senderIP, m_currentGame->getName());
62+
}
63+
64+
void LANAPI::handleGameAcknowledgePatchInfo(LANMessage *msg, UnsignedInt senderIP)
65+
{
66+
if (!m_inLobby)
67+
return;
68+
69+
LANGameInfo *game = LookupGame(UnicodeString(msg->GameInfo.gameName));
70+
if (!game)
71+
return;
72+
73+
if (game->getIP(0) != senderIP)
74+
return;
75+
76+
// a game host has acknowledged our request for patch information
77+
game->getSlot(0)->setPatchVersion(msg->PatchInfo.patchVersion);
78+
79+
// update game list with colored names
80+
OnGameList(m_games);
81+
}
82+
83+
void LANAPI::handleLobbyRequestPatchInfo(LANMessage *msg, UnsignedInt senderIP)
84+
{
85+
if (!m_inLobby)
86+
return;
87+
88+
// acknowledge a request for patch information by a fellow player in the lobby
89+
handlePatchInfo(LANMessage::MSG_LOBBY_ACKNOWLEDGE_PATCH_INFO, senderIP, UnicodeString());
90+
}
91+
92+
void LANAPI::handleLobbyAcknowledgePatchInfo(LANMessage *msg, UnsignedInt senderIP)
93+
{
94+
if (!m_inLobby)
95+
return;
96+
97+
LANPlayer *player = LookupPlayer(senderIP);
98+
if (!player)
99+
return;
100+
101+
// a fellow player in the lobby has acknowledged our request for patch information
102+
player->setPatchVersion(msg->PatchInfo.patchVersion);
103+
104+
// update player list with colored names
105+
OnPlayerList(m_lobbyPlayers);
106+
}
107+
108+
void LANAPI::handleMatchRequestPatchInfo(LANMessage *msg, UnsignedInt senderIP)
109+
{
110+
if (!m_currentGame)
111+
return;
112+
113+
// acknowledge a request for patch information by a fellow player in the game
114+
handlePatchInfo(LANMessage::MSG_MATCH_ACKNOWLEDGE_PATCH_INFO, senderIP, m_currentGame->getName());
115+
116+
// treat request for patch information as acknowledgement
117+
handleMatchAcknowledgePatchInfo(msg, senderIP);
118+
}
119+
120+
void LANAPI::handleMatchAcknowledgePatchInfo(LANMessage *msg, UnsignedInt senderIP)
121+
{
122+
if (!m_currentGame)
123+
return;
124+
125+
for (Int i = 0; i < MAX_SLOTS; ++i)
126+
{
127+
if (!m_currentGame->getLANSlot(i)->isHuman() || m_currentGame->getIP(i) != senderIP)
128+
continue;
129+
130+
// a fellow player in the game has acknowledged our request for patch information
131+
m_currentGame->getSlot(i)->setPatchVersion(msg->PatchInfo.patchVersion);
132+
133+
// update player list with colored names
134+
lanUpdateSlotList();
135+
136+
break;
137+
}
138+
}
139+
43140
void LANAPI::handleRequestLocations( LANMessage *msg, UnsignedInt senderIP )
44141
{
45142
if (m_inLobby)
@@ -139,6 +236,9 @@ void LANAPI::handleGameAnnounce( LANMessage *msg, UnsignedInt senderIP )
139236
game = NEW LANGameInfo;
140237
game->setName(UnicodeString(msg->GameInfo.gameName));
141238
addGame(game);
239+
240+
// TheSuperHackers @feature Caball009 06/11/2025 Request a game host to send patch information.
241+
handlePatchInfo(LANMessage::MSG_GAME_REQUEST_PATCH_INFO, senderIP, game->getName());
142242
}
143243
Bool success = ParseGameOptionsString(game,AsciiString(msg->GameInfo.options));
144244
game->setGameInProgress(msg->GameInfo.inProgress);
@@ -165,6 +265,9 @@ void LANAPI::handleLobbyAnnounce( LANMessage *msg, UnsignedInt senderIP )
165265
{
166266
player = NEW LANPlayer;
167267
player->setIP(senderIP);
268+
269+
// TheSuperHackers @feature Caball009 06/11/2025 Request a player in the lobby to send patch information.
270+
handlePatchInfo(LANMessage::MSG_LOBBY_REQUEST_PATCH_INFO, senderIP, UnicodeString());
168271
}
169272
else
170273
{
@@ -401,6 +504,9 @@ void LANAPI::handleJoinAccept( LANMessage *msg, UnsignedInt senderIP )
401504
OnGameJoin(RET_OK, m_currentGame);
402505
//DEBUG_ASSERTCRASH(false, ("setting host to %ls@%ls", m_currentGame->getLANSlot(0)->getUser()->getLogin().str(),
403506
// m_currentGame->getLANSlot(0)->getUser()->getHost().str()));
507+
508+
// TheSuperHackers @feature Caball009 06/11/2025 Request players in the match to send patch information.
509+
handlePatchInfo(LANMessage::MSG_MATCH_REQUEST_PATCH_INFO, 0, m_currentGame->getName());
404510
}
405511
m_pendingAction = ACT_NONE;
406512
m_expiration = 0;

0 commit comments

Comments
 (0)