diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h index 5fb3320de7..5539e955a7 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 3ea69e9e71..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; @@ -415,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 e34de5cc71..409ad38ad6 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() > 0)) + text.concat(L"[SH]"); + + staticTextStatus[rowNum]->winSetEnabledTextColors(frontColor, backColor); + GadgetStaticTextSetText(staticTextStatus[rowNum], text); } slotNumInRow[rowNum++] = slotNum; diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp index 15a55db16e..95dae4eb4a 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() > 0) + { + 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)) diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp index 4a2526ed45..120a9edee9 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 ) @@ -1479,7 +1480,12 @@ Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options) //DEBUG_LOG(("ParseAsciiStringToGameInfo - game options all good, setting info")); 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]); + } game->setMap(mapName); game->setMapCRC(mapCRC); diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp index c0013fade9..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; 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 66c4547863..0dc81a10d6 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp @@ -682,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)