From ad2ed8124298a8cca62dc3ccc91d539008164dfa Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 1 Aug 2025 21:51:58 +0200 Subject: [PATCH 1/7] Added patch version member and member functions. --- GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h | 4 ++++ GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h | 1 + GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp | 1 + GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp | 1 + .../Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp | 4 +++- 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h index abb37a4da5..d9d0770785 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h @@ -128,6 +128,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; @@ -146,6 +149,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; // TheSuperHackers patch version }; /** diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h index 784b27bb4e..fccd6aec40 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h @@ -366,6 +366,7 @@ struct LANMessage UnsignedInt exeCRC; UnsignedInt iniCRC; char serial[g_maxSerialLength]; + UnsignedInt patchVersion; } GameToJoin; // GameJoined is sent with JOIN_ACCEPT diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp index 273bdbc5dc..af98a14512 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp @@ -73,6 +73,7 @@ void GameSlot::reset() m_origPlayerTemplate = -1; m_origStartPos = -1; m_origColor = -1; + m_patchVersion = 0; } void GameSlot::saveOffOriginalInfo( void ) diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp index 797930d68d..c3d268149f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp @@ -635,6 +635,7 @@ void LANAPI::RequestGameJoin( LANGameInfo *game, UnsignedInt ip /* = 0 */ ) GetStringFromRegistry("\\ergc", "", s); strncpy(msg.GameToJoin.serial, s.str(), g_maxSerialLength); msg.GameToJoin.serial[g_maxSerialLength-1] = '\0'; + msg.GameToJoin.patchVersion = 1337; sendMessage(&msg, ip); diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp index 466b9e2d48..f8270e8782 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp @@ -348,7 +348,9 @@ void LANAPI::handleRequestJoin( LANMessage *msg, UnsignedInt senderIP ) newSlot.setPort(NETWORK_BASE_PORT_NUMBER); newSlot.setLastHeard(timeGetTime()); newSlot.setSerial(msg->GameToJoin.serial); - m_currentGame->setSlot(player,newSlot); + if (msg->GameToJoin.patchVersion == 1337) + newSlot.setPatchVersion(msg->GameToJoin.patchVersion); + m_currentGame->setSlot(player, newSlot); DEBUG_LOG(("LANAPI::handleRequestJoin - added player %ls at ip 0x%08x to the game", msg->name, senderIP)); OnPlayerJoin(player, UnicodeString(msg->name)); From 06eea3c2f5517b9240b69a4c7aefcde70fe8016f Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 1 Aug 2025 21:53:04 +0200 Subject: [PATCH 2/7] Added (de)serialization to game options string. --- .../Source/GameNetwork/GameInfo.cpp | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp index af98a14512..a7298ce69a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp @@ -922,8 +922,19 @@ AsciiString GameInfoToAsciiString( const GameInfo *game ) DEBUG_LOG(("Map name is %s", mapName.str())); } + UnsignedByte patchedClients = 0; + for (Int i = 0; i < MAX_SLOTS; ++i) + { + const GameSlot* slot = game->getConstSlot(i); + if (slot && slot->isHuman() && (i == game->getLocalSlotNum() || slot->getPatchVersion() >= 1337)) + patchedClients |= (1 << i); + } + + AsciiString statsString; + statsString.format("%d P%cP", game->getUseStats() & 1, patchedClients); + AsciiString optionsString; - optionsString.format("US=%d;M=%2.2x%s;MC=%X;MS=%d;SD=%d;C=%d;SR=%u;SC=%u;O=%c;", game->getUseStats(), game->getMapContentsMask(), newMapName.str(), + optionsString.format("US=%s;M=%2.2x%s;MC=%X;MS=%d;SD=%d;C=%d;SR=%u;SC=%u;O=%c;", statsString.str(), game->getMapContentsMask(), newMapName.str(), game->getMapCRC(), game->getMapSize(), game->getSeed(), game->getCRCInterval(), game->getSuperweaponRestriction(), game->getStartingCash().countMoney(), game->oldFactionsOnly() ? 'Y' : 'N' ); @@ -1018,6 +1029,7 @@ Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options) Int useStats = TRUE; Money startingCash = TheGlobalData->m_defaultStartingCash; UnsignedShort restriction = 0; // Always the default + UnsignedByte patchedClients = 0; Bool sawMap, sawMapCRC, sawMapSize, sawSeed, sawSlotlist, sawUseStats, sawSuperweaponRestriction, sawStartingCash, sawOldFactions; sawMap = sawMapCRC = sawMapSize = sawSeed = sawSlotlist = sawUseStats = sawSuperweaponRestriction = sawStartingCash = sawOldFactions = FALSE; @@ -1051,6 +1063,9 @@ Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options) { useStats = atoi(val.str()); sawUseStats = true; + + if (val.getLength() == 5 && val.getCharAt(2) == 'P' && val.getCharAt(4) == 'P') + patchedClients = val.getCharAt(3); } else if (key.compare("M") == 0) @@ -1480,7 +1495,12 @@ Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options) //DEBUG_LOG(("ParseAsciiStringToGameInfo - game options all good, setting info")); for(Int i = 0; isetSlot(i,newSlot[i]); + { + if (patchedClients & (1 << i)) + newSlot[i].setPatchVersion(1337); + + game->setSlot(i, newSlot[i]); + } game->setMap(mapName); game->setMapCRC(mapCRC); From 9ddafcb800b67ed2c59a4a36b095bd3f71272fb5 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 1 Aug 2025 21:56:39 +0200 Subject: [PATCH 3/7] Made patch players' names yellow and added [SH] tag to patch players' status. --- .../GameClient/GUI/GUICallbacks/Diplomacy.cpp | 30 ++++++++++++------- .../GUI/GUICallbacks/Menus/GameInfoWindow.cpp | 2 +- .../GameEngine/Source/GameNetwork/GUIUtil.cpp | 6 ++++ 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp index 53df52341b..26f005f6db 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp @@ -532,24 +532,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"); } } } @@ -558,15 +562,21 @@ 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"); } } + + if (slot->isHuman() && (TheGameInfo->getLocalSlotNum() == slotNum || slot->getPatchVersion() >= 1337)) + text.concat(L"[SH]"); + + staticTextStatus[rowNum]->winSetEnabledTextColors(frontColor, backColor); + GadgetStaticTextSetText(staticTextStatus[rowNum], text); } slotNumInRow[rowNum++] = slotNum; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/GameInfoWindow.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/GameInfoWindow.cpp index 96916bc542..e6fa1448cc 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/GameInfoWindow.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/GameInfoWindow.cpp @@ -177,7 +177,7 @@ void RefreshGameInfoWindow(GameInfo *gameInfo, UnicodeString gameName) } else if(slot->isHuman()) { - addedRow = GadgetListBoxAddEntryText(listBoxPlayers, slot->getName(),playerColor,-1,1); + addedRow = GadgetListBoxAddEntryText(listBoxPlayers, slot->getName(), (slot->getPatchVersion() >= 1337) ? 0xFFFFFF00 : playerColor, -1, 1); } Int playerTemplate = slot->getPlayerTemplate(); if(playerTemplate == PLAYERTEMPLATE_OBSERVER) diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp index 51ee6b34d0..5d0dee46d7 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp @@ -423,6 +423,12 @@ void UpdateSlotList( GameInfo *myGame, GameWindow *comboPlayer[], } if(slot->isHuman()) { + if (i == myGame->getLocalSlotNum() || myGame->getSlot(i)->getPatchVersion() >= 1337) + { + GadgetComboBoxSetEnabledTextColors(comboPlayer[i], 0xFFFFFF00, 0xFF000000); + GadgetComboBoxSetDisabledTextColors(comboPlayer[i], 0xFFC0C000, 0xFF000000); + } + UnicodeString newName = slot->getName(); UnicodeString oldName = GadgetComboBoxGetText(comboPlayer[i]); if (comboPlayer[i] && newName.compare(oldName)) From 549e098e8b8452630e5c8cfd5022a82ada447f47 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 1 Aug 2025 21:58:42 +0200 Subject: [PATCH 4/7] Relaxed string length check. --- GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp index a7298ce69a..1f3daeb29c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp @@ -1064,7 +1064,7 @@ Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options) useStats = atoi(val.str()); sawUseStats = true; - if (val.getLength() == 5 && val.getCharAt(2) == 'P' && val.getCharAt(4) == 'P') + if (val.getLength() >= 5 && val.getCharAt(2) == 'P' && val.getCharAt(4) == 'P') patchedClients = val.getCharAt(3); } else From 634eb6b61e948a28d1bc92867df0c978f20bdb23 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 1 Aug 2025 22:21:48 +0200 Subject: [PATCH 5/7] Add extra scope to make the code compile with VC6. --- .../Code/GameEngine/Source/GameNetwork/GameInfo.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp index 1f3daeb29c..befdff0cd1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp @@ -923,11 +923,13 @@ AsciiString GameInfoToAsciiString( const GameInfo *game ) } UnsignedByte patchedClients = 0; - for (Int i = 0; i < MAX_SLOTS; ++i) { - const GameSlot* slot = game->getConstSlot(i); - if (slot && slot->isHuman() && (i == game->getLocalSlotNum() || slot->getPatchVersion() >= 1337)) - patchedClients |= (1 << i); + for (Int i = 0; i < MAX_SLOTS; ++i) + { + const GameSlot* slot = game->getConstSlot(i); + if (slot && slot->isHuman() && (i == game->getLocalSlotNum() || slot->getPatchVersion() >= 1337)) + patchedClients |= (1 << i); + } } AsciiString statsString; From a059c0b4df106a2b47d7e6669b172011a8dccecf Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Sun, 3 Aug 2025 20:09:48 +0200 Subject: [PATCH 6/7] Reverted original lines. --- GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp | 2 +- .../Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp index befdff0cd1..0e441ba32f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp @@ -1501,7 +1501,7 @@ Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options) if (patchedClients & (1 << i)) newSlot[i].setPatchVersion(1337); - game->setSlot(i, newSlot[i]); + game->setSlot(i,newSlot[i]); } game->setMap(mapName); diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp index f8270e8782..21568785b2 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp @@ -350,7 +350,7 @@ void LANAPI::handleRequestJoin( LANMessage *msg, UnsignedInt senderIP ) newSlot.setSerial(msg->GameToJoin.serial); if (msg->GameToJoin.patchVersion == 1337) newSlot.setPatchVersion(msg->GameToJoin.patchVersion); - m_currentGame->setSlot(player, newSlot); + m_currentGame->setSlot(player,newSlot); DEBUG_LOG(("LANAPI::handleRequestJoin - added player %ls at ip 0x%08x to the game", msg->name, senderIP)); OnPlayerJoin(player, UnicodeString(msg->name)); From 9fb6a0198b2e8ddad7b0f067b348f575aa4c004f Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Sun, 10 Aug 2025 21:16:09 +0200 Subject: [PATCH 7/7] Major implementation refactor. --- .../GameEngine/Include/GameNetwork/LANAPI.h | 8 ++- .../Include/GameNetwork/LANPlayer.h | 17 +++--- .../GameClient/GUI/GUICallbacks/Diplomacy.cpp | 2 +- .../GUI/GUICallbacks/Menus/GameInfoWindow.cpp | 2 +- .../GameEngine/Source/GameNetwork/GUIUtil.cpp | 2 +- .../Source/GameNetwork/GameInfo.cpp | 23 +------- .../GameEngine/Source/GameNetwork/LANAPI.cpp | 13 ++++- .../Source/GameNetwork/LANAPICallbacks.cpp | 3 +- .../Source/GameNetwork/LANAPIhandlers.cpp | 57 ++++++++++++++++++- .../Source/GameNetwork/LANGameInfo.cpp | 5 +- 10 files changed, 96 insertions(+), 36 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h index 09505f8cb6..01c0b6fc54 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h @@ -282,6 +282,7 @@ class LANAPI : public LANAPIInterface void handleGameStartTimer( LANMessage *msg, UnsignedInt senderIP ); void handleGameOptions( LANMessage *msg, UnsignedInt senderIP ); void handleInActive( LANMessage *msg, UnsignedInt senderIP ); + void handlePatchVersion( LANMessage *msg, UnsignedInt senderIP ); }; @@ -319,6 +320,7 @@ 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 + MSG_PATCH_VERSION, ///< TheSuperHackers patch version MSG_MAX } LANMessageType; @@ -366,7 +368,6 @@ struct LANMessage UnsignedInt exeCRC; UnsignedInt iniCRC; char serial[g_maxSerialLength]; - UnsignedInt patchVersion; } GameToJoin; // GameJoined is sent with JOIN_ACCEPT @@ -416,6 +417,11 @@ struct LANMessage char options[m_lanMaxOptionsLength+1]; } GameOptions; + struct + { + UnsignedInt patchVersion; + } PatchInfo; + }; }; #pragma pack(pop) diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANPlayer.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANPlayer.h index 032a5992ff..e0668fe305 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANPlayer.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANPlayer.h @@ -39,7 +39,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; } @@ -56,14 +56,17 @@ 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 - UnicodeString m_login; ///< login name - UnicodeString m_host; ///< machine name - 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 + UnicodeString m_name; ///< Player name + UnicodeString m_login; ///< login name + UnicodeString m_host; ///< machine name + 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; ///< TheSuperHackers patch version }; #endif //_LANPLAYER_H_ diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp index 853f9b2067..409ad38ad6 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp @@ -572,7 +572,7 @@ void PopulateInGameDiplomacyPopup( void ) } } - if (slot->isHuman() && (TheGameInfo->getLocalSlotNum() == slotNum || slot->getPatchVersion() >= 1337)) + if (slot->isHuman() && (TheGameInfo->getLocalSlotNum() == slotNum || slot->getPatchVersion() > 0)) text.concat(L"[SH]"); staticTextStatus[rowNum]->winSetEnabledTextColors(frontColor, backColor); diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/GameInfoWindow.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/GameInfoWindow.cpp index 30b6968fb4..6b301d5d4a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/GameInfoWindow.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/GameInfoWindow.cpp @@ -177,7 +177,7 @@ void RefreshGameInfoWindow(GameInfo *gameInfo, UnicodeString gameName) } else if(slot->isHuman()) { - addedRow = GadgetListBoxAddEntryText(listBoxPlayers, slot->getName(), (slot->getPatchVersion() >= 1337) ? 0xFFFFFF00 : playerColor, -1, 1); + addedRow = GadgetListBoxAddEntryText(listBoxPlayers, slot->getName(),playerColor,-1,1); } Int playerTemplate = slot->getPlayerTemplate(); if(playerTemplate == PLAYERTEMPLATE_OBSERVER) diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp index 77d437e363..95dae4eb4a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp @@ -423,7 +423,7 @@ void UpdateSlotList( GameInfo *myGame, GameWindow *comboPlayer[], } if(slot->isHuman()) { - if (i == myGame->getLocalSlotNum() || myGame->getSlot(i)->getPatchVersion() >= 1337) + if (i == myGame->getLocalSlotNum() || myGame->getSlot(i)->getPatchVersion() > 0) { GadgetComboBoxSetEnabledTextColors(comboPlayer[i], 0xFFFFFF00, 0xFF000000); GadgetComboBoxSetDisabledTextColors(comboPlayer[i], 0xFFC0C000, 0xFF000000); diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp index c40159c3bf..120a9edee9 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp @@ -922,21 +922,8 @@ AsciiString GameInfoToAsciiString( const GameInfo *game ) DEBUG_LOG(("Map name is %s", mapName.str())); } - UnsignedByte patchedClients = 0; - { - for (Int i = 0; i < MAX_SLOTS; ++i) - { - const GameSlot* slot = game->getConstSlot(i); - if (slot && slot->isHuman() && (i == game->getLocalSlotNum() || slot->getPatchVersion() >= 1337)) - patchedClients |= (1 << i); - } - } - - AsciiString statsString; - statsString.format("%d P%cP", game->getUseStats() & 1, patchedClients); - AsciiString optionsString; - optionsString.format("US=%s;M=%2.2x%s;MC=%X;MS=%d;SD=%d;C=%d;SR=%u;SC=%u;O=%c;", statsString.str(), game->getMapContentsMask(), newMapName.str(), + optionsString.format("US=%d;M=%2.2x%s;MC=%X;MS=%d;SD=%d;C=%d;SR=%u;SC=%u;O=%c;", game->getUseStats(), game->getMapContentsMask(), newMapName.str(), game->getMapCRC(), game->getMapSize(), game->getSeed(), game->getCRCInterval(), game->getSuperweaponRestriction(), game->getStartingCash().countMoney(), game->oldFactionsOnly() ? 'Y' : 'N' ); @@ -1031,7 +1018,6 @@ Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options) Int useStats = TRUE; Money startingCash = TheGlobalData->m_defaultStartingCash; UnsignedShort restriction = 0; // Always the default - UnsignedByte patchedClients = 0; Bool sawMap, sawMapCRC, sawMapSize, sawSeed, sawSlotlist, sawUseStats, sawSuperweaponRestriction, sawStartingCash, sawOldFactions; sawMap = sawMapCRC = sawMapSize = sawSeed = sawSlotlist = sawUseStats = sawSuperweaponRestriction = sawStartingCash = sawOldFactions = FALSE; @@ -1065,9 +1051,6 @@ Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options) { useStats = atoi(val.str()); sawUseStats = true; - - if (val.getLength() >= 5 && val.getCharAt(2) == 'P' && val.getCharAt(4) == 'P') - patchedClients = val.getCharAt(3); } else if (key.compare("M") == 0) @@ -1498,8 +1481,8 @@ Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options) for(Int i = 0; igetConstSlot(i)->getState() == SLOT_PLAYER && newSlot[i].getState() == SLOT_PLAYER) + newSlot[i].setPatchVersion(game->getConstSlot(i)->getPatchVersion()); game->setSlot(i,newSlot[i]); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp index d3920bcbf2..e4d9bed9f2 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp @@ -29,6 +29,7 @@ #include "Common/crc.h" #include "Common/GameState.h" #include "Common/Registry.h" +#include "Common/version.h" #include "GameNetwork/LANAPI.h" #include "GameNetwork/networkutil.h" #include "Common/GlobalData.h" @@ -417,6 +418,9 @@ void LANAPI::update( void ) case LANMessage::MSG_INACTIVE: // someone is telling us that we're inactive. handleInActive( msg, senderIP ); break; + case LANMessage::MSG_PATCH_VERSION: // someone is sharing their patch version with us + handlePatchVersion( msg, senderIP ); + break; default: DEBUG_LOG(("Unknown LAN message type %d", msg->LANMessageType)); @@ -461,6 +465,14 @@ void LANAPI::update( void ) } } + if (m_inLobby || (m_currentGame && !m_currentGame->isGameInProgress())) { + LANMessage msg; + fillInLANMessage(&msg); + msg.LANMessageType = LANMessage::MSG_PATCH_VERSION; + msg.PatchInfo.patchVersion = TheVersion->getVersionNumber(); + sendMessage(&msg); + } + Bool playerListChanged = false; Bool gameListChanged = false; @@ -635,7 +647,6 @@ void LANAPI::RequestGameJoin( LANGameInfo *game, UnsignedInt ip /* = 0 */ ) GetStringFromRegistry("\\ergc", "", s); strncpy(msg.GameToJoin.serial, s.str(), g_maxSerialLength); msg.GameToJoin.serial[g_maxSerialLength-1] = '\0'; - msg.GameToJoin.patchVersion = 1337; sendMessage(&msg, ip); diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp index 647c00ec83..96012dbf01 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp @@ -642,7 +642,8 @@ void LANAPI::OnPlayerList( LANPlayer *playerList ) LANPlayer *player = m_lobbyPlayers; while (player) { - Int addedIndex = GadgetListBoxAddEntryText(listboxPlayers, player->getName(), playerColor, -1, -1); + const Color color = (player->getPatchVersion() > 0 || m_localIP == player->getIP()) ? 0xFFFFFF00 : playerColor; + Int addedIndex = GadgetListBoxAddEntryText(listboxPlayers, player->getName(), color, -1, -1); GadgetListBoxSetItemData(listboxPlayers, (void *)player->getIP(),addedIndex, 0 ); if (selectedIP == player->getIP()) diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp index 04f7617f86..0dc81a10d6 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp @@ -348,8 +348,6 @@ void LANAPI::handleRequestJoin( LANMessage *msg, UnsignedInt senderIP ) newSlot.setPort(NETWORK_BASE_PORT_NUMBER); newSlot.setLastHeard(timeGetTime()); newSlot.setSerial(msg->GameToJoin.serial); - if (msg->GameToJoin.patchVersion == 1337) - newSlot.setPatchVersion(msg->GameToJoin.patchVersion); m_currentGame->setSlot(player,newSlot); DEBUG_LOG(("LANAPI::handleRequestJoin - added player %ls at ip 0x%08x to the game", msg->name, senderIP)); @@ -684,3 +682,58 @@ void LANAPI::handleInActive(LANMessage *msg, UnsignedInt senderIP) { RequestGameOptions(options, FALSE); lanUpdateSlotList(); } + +void LANAPI::handlePatchVersion(LANMessage* msg, UnsignedInt senderIP) +{ + if (m_inLobby) + { + LANPlayer *player = m_lobbyPlayers; + while (player) + { + if (player->getIP() == senderIP) + { + if (!player->getPatchVersion() && msg->PatchInfo.patchVersion > 0) + { + player->setPatchVersion(msg->PatchInfo.patchVersion); + OnPlayerList(m_lobbyPlayers); + } + break; + } + + player = player->getNext(); + } + + LANGameInfo* game = m_games; + while (game) + { + GameSlot *slot = game->getSlot(0); + if (slot->getIP() == senderIP) + { + DEBUG_ASSERTCRASH(game->getHostIP() == slot->getIP(), ("First game slot is not used by the host")); + + if (!slot->getPatchVersion() && msg->PatchInfo.patchVersion > 0) + { + slot->setPatchVersion(msg->PatchInfo.patchVersion); + OnGameList(m_games); + } + break; + } + + game = game->getNext(); + } + } + else if (m_currentGame && !m_currentGame->isGameInProgress()) + { + for (int player = 0; player < MAX_SLOTS; ++player) + { + if (m_currentGame->getIP(player) == senderIP) + { + if (!m_currentGame->getSlot(player)->getPatchVersion() && msg->PatchInfo.patchVersion > 0) + { + m_currentGame->getSlot(player)->setPatchVersion(msg->PatchInfo.patchVersion); + } + break; + } + } + } +} diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANGameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANGameInfo.cpp index ec8eb4ffbd..c9159af740 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANGameInfo.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANGameInfo.cpp @@ -226,7 +226,10 @@ void LANDisplayGameList( GameWindow *gameListbox, LANGameInfo *gameList ) { txtGName.concat(L"]"); } - Int addedIndex = GadgetListBoxAddEntryText(gameListbox, txtGName, (gameList->isGameInProgress())?gameInProgressColor:gameColor, -1, -1); + const Color color = (gameList->getSlot(0)->getPatchVersion() > 0) + ? ((gameList->isGameInProgress()) ? 0xFF808000 : 0xFFFFFF00) + : ((gameList->isGameInProgress()) ? gameInProgressColor : gameColor); + Int addedIndex = GadgetListBoxAddEntryText(gameListbox, txtGName, color, -1, -1); GadgetListBoxSetItemData(gameListbox, (void *)gameList, addedIndex, 0 ); if (selectedPtr == gameList)